Commit 3b25a510 authored by Dominik Charousset's avatar Dominik Charousset

typed actors: proper impl for spawning & sending

parent 3ce764a9
...@@ -166,7 +166,9 @@ cppa/serializer.hpp ...@@ -166,7 +166,9 @@ cppa/serializer.hpp
cppa/single_timeout.hpp cppa/single_timeout.hpp
cppa/singletons.hpp cppa/singletons.hpp
cppa/spawn.hpp cppa/spawn.hpp
cppa/spawn_fwd.hpp
cppa/spawn_options.hpp cppa/spawn_options.hpp
cppa/sync_sender.hpp
cppa/system_messages.hpp cppa/system_messages.hpp
cppa/timeout_definition.hpp cppa/timeout_definition.hpp
cppa/to_string.hpp cppa/to_string.hpp
...@@ -176,6 +178,7 @@ cppa/type_lookup_table.hpp ...@@ -176,6 +178,7 @@ cppa/type_lookup_table.hpp
cppa/typed_actor.hpp cppa/typed_actor.hpp
cppa/typed_actor_ptr.hpp cppa/typed_actor_ptr.hpp
cppa/typed_behavior.hpp cppa/typed_behavior.hpp
cppa/typed_continue_helper.hpp
cppa/typed_event_based_actor.hpp cppa/typed_event_based_actor.hpp
cppa/uniform_type_info.hpp cppa/uniform_type_info.hpp
cppa/unit.hpp cppa/unit.hpp
...@@ -345,5 +348,3 @@ unit_testing/test_tuple.cpp ...@@ -345,5 +348,3 @@ unit_testing/test_tuple.cpp
unit_testing/test_typed_spawn.cpp unit_testing/test_typed_spawn.cpp
unit_testing/test_uniform_type.cpp unit_testing/test_uniform_type.cpp
unit_testing/test_yield_interface.cpp unit_testing/test_yield_interface.cpp
cppa/typed_continue_helper.hpp
cppa/sync_sender.hpp
...@@ -156,16 +156,29 @@ compound_member(const std::pair<GRes (Parent::*)() const, ...@@ -156,16 +156,29 @@ compound_member(const std::pair<GRes (Parent::*)() const,
return {gspair, new detail::default_uniform_type_info_impl<mtype>(args...)}; return {gspair, new detail::default_uniform_type_info_impl<mtype>(args...)};
} }
/** /**
* @brief Adds a new type mapping for @p T to the libcppa type system. * @brief Adds a new type mapping for @p C to the libcppa type system.
* @param args Members of @p T. * @tparam C A class that is default constructible, copy constructible,
* and comparable.
* @param arg First members of @p C.
* @param args Additional members of @p C.
* @warning @p announce is <b>not</b> thead safe! * @warning @p announce is <b>not</b> thead safe!
*/ */
template<typename T, typename... Ts> template<class C, typename... Ts>
inline const uniform_type_info* announce(const Ts&... args) { inline const uniform_type_info* announce(const Ts&... args) {
auto ptr = new detail::default_uniform_type_info_impl<T>(args...); auto ptr = new detail::default_uniform_type_info_impl<C>(args...);
return announce(typeid(T), std::unique_ptr<uniform_type_info>{ptr}); return announce(typeid(C), std::unique_ptr<uniform_type_info>{ptr});
}
/**
* @brief Adds a new type mapping for an empty or "tag" class.
* @tparam C A class without any member.
* @warning @p announce_tag is <b>not</b> thead safe!
*/
template<class C>
inline const uniform_type_info* announce_tag() {
auto ptr = new detail::empty_uniform_type_info_impl<C>();
return announce(typeid(C), std::unique_ptr<uniform_type_info>{ptr});
} }
/** /**
......
...@@ -33,8 +33,6 @@ ...@@ -33,8 +33,6 @@
#include <cstdint> #include <cstdint>
#include "cppa/spawn_options.hpp"
namespace cppa { namespace cppa {
// classes // classes
...@@ -76,21 +74,6 @@ typedef intrusive_ptr<node_id> node_id_ptr; ...@@ -76,21 +74,6 @@ typedef intrusive_ptr<node_id> node_id_ptr;
// weak intrusive pointer typedefs // weak intrusive pointer typedefs
typedef weak_intrusive_ptr<actor_proxy> weak_actor_proxy_ptr; typedef weak_intrusive_ptr<actor_proxy> weak_actor_proxy_ptr;
// prototype definitions of the spawn function famility;
// implemented in spawn.hpp (this header is included there)
template<class Impl, spawn_options Options = no_spawn_options, typename... Ts>
actor spawn(Ts&&... args);
template<spawn_options Options = no_spawn_options, typename... Ts>
actor spawn(Ts&&... args);
template<class Impl, spawn_options Options = no_spawn_options, typename... Ts>
actor spawn_in_group(const group&, Ts&&... args);
template<spawn_options Options = no_spawn_options, typename... Ts>
actor spawn_in_group(const group&, Ts&&... args);
} // namespace cppa } // namespace cppa
#endif // CPPA_FWD_HPP #endif // CPPA_FWD_HPP
...@@ -457,16 +457,68 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T ...@@ -457,16 +457,68 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
m_members.push_back(unique_uti(new result_type)); m_members.push_back(unique_uti(new result_type));
} }
void serialize(const void* obj, serializer* s) const { void serialize(const void* obj, serializer* s) const override {
for (auto& m : m_members) m->serialize(obj, s); for (auto& m : m_members) m->serialize(obj, s);
} }
void deserialize(void* obj, deserializer* d) const { void deserialize(void* obj, deserializer* d) const override {
for (auto& m : m_members) m->deserialize(obj, d); for (auto& m : m_members) m->deserialize(obj, d);
} }
}; };
template<typename T>
class empty_uniform_type_info_impl : public uniform_type_info {
public:
bool equals(const std::type_info& tinfo) const override {
return typeid(T) == tinfo;
}
const char* name() const override {
return m_name.c_str();
}
any_tuple as_any_tuple(void*) const override {
return make_any_tuple(T{});
}
void serialize(const void*, serializer*) const override {
// no members means: nothing to do
}
void deserialize(void*, deserializer*) const override {
// no members means: nothing to do
}
empty_uniform_type_info_impl() {
auto uname = detail::to_uniform_name<T>();
auto cname = detail::mapped_name_by_decorated_name(uname.c_str());
if (cname == uname.c_str()) m_name = std::move(uname);
else m_name = cname;
}
protected:
bool equals(const void*, const void*) const override {
return true;
}
void* new_instance(const void*) const override {
return new T();
}
void delete_instance(void* instance) const override {
delete reinterpret_cast<T*>(instance);
}
private:
std::string m_name;
};
} } // namespace detail } } // namespace detail
#endif // CPPA_DEFAULT_UNIFORM_TYPE_INFO_IMPL_HPP #endif // CPPA_DEFAULT_UNIFORM_TYPE_INFO_IMPL_HPP
...@@ -39,9 +39,9 @@ ...@@ -39,9 +39,9 @@
#include "cppa/extend.hpp" #include "cppa/extend.hpp"
#include "cppa/channel.hpp" #include "cppa/channel.hpp"
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/cppa_fwd.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/cow_tuple.hpp" #include "cppa/cow_tuple.hpp"
#include "cppa/spawn_fwd.hpp"
#include "cppa/message_id.hpp" #include "cppa/message_id.hpp"
#include "cppa/match_expr.hpp" #include "cppa/match_expr.hpp"
#include "cppa/actor_state.hpp" #include "cppa/actor_state.hpp"
...@@ -91,31 +91,66 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> { ...@@ -91,31 +91,66 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
~local_actor(); ~local_actor();
/**************************************************************************
* spawn untyped actors *
**************************************************************************/
template<class Impl, spawn_options Options = no_spawn_options, typename... Ts> template<class C, spawn_options Os = no_spawn_options, typename... Ts>
actor spawn(Ts&&... args) { actor spawn(Ts&&... args) {
auto res = cppa::spawn<Impl, make_unbound(Options)>(std::forward<Ts>(args)...); constexpr auto os = make_unbound(Os);
return eval_opts(Options, std::move(res)); auto res = cppa::spawn<C, os>(std::forward<Ts>(args)...);
return eval_opts(Os, std::move(res));
} }
template<spawn_options Options = no_spawn_options, typename... Ts> template<spawn_options Os = no_spawn_options, typename... Ts>
actor spawn(Ts&&... args) { actor spawn(Ts&&... args) {
auto res = cppa::spawn<make_unbound(Options)>(std::forward<Ts>(args)...); constexpr auto os = make_unbound(Os);
return eval_opts(Options, std::move(res)); auto res = cppa::spawn<os>(std::forward<Ts>(args)...);
return eval_opts(Os, std::move(res));
} }
template<spawn_options Options = no_spawn_options, typename... Ts> template<spawn_options Os = no_spawn_options, typename... Ts>
actor spawn_in_group(const group& grp, Ts&&... args) { actor spawn_in_group(const group& grp, Ts&&... args) {
auto res = cppa::spawn_in_group<make_unbound(Options)>(grp, std::forward<Ts>(args)...); constexpr auto os = make_unbound(Os);
return eval_opts(Options, std::move(res)); auto res = cppa::spawn_in_group<os>(grp, std::forward<Ts>(args)...);
return eval_opts(Os, std::move(res));
} }
template<class Impl, spawn_options Options, typename... Ts> template<class C, spawn_options Os, typename... Ts>
actor spawn_in_group(const group& grp, Ts&&... args) { actor spawn_in_group(const group& grp, Ts&&... args) {
auto res = cppa::spawn_in_group<Impl, make_unbound(Options)>(grp, std::forward<Ts>(args)...); constexpr auto os = make_unbound(Os);
return eval_opts(Options, std::move(res)); auto res = cppa::spawn_in_group<C, os>(grp, std::forward<Ts>(args)...);
return eval_opts(Os, std::move(res));
} }
/**************************************************************************
* spawn typed actors *
**************************************************************************/
template<spawn_options Os = no_spawn_options, typename F>
typename detail::actor_handle_from_typed_behavior<
typename util::get_callable_trait<F>::result_type
>::type
spawn_typed(F fun) {
constexpr auto os = make_unbound(Os);
auto res = cppa::spawn_typed<os>(std::move(fun));
return eval_opts(Os, std::move(res));
}
template<class C, spawn_options Os = no_spawn_options, typename... Ts>
typename detail::actor_handle_from_signature_list<
typename C::signatures
>::type
spawn_typed(Ts&&... args) {
constexpr auto os = make_unbound(Os);
auto res = cppa::spawn_typed<C, os>(std::forward<Ts>(args)...);
return eval_opts(Os, std::move(res));
}
/**************************************************************************
* send asynchronous messages *
**************************************************************************/
/** /**
* @brief Sends @p what to the receiver specified in @p dest. * @brief Sends @p what to the receiver specified in @p dest.
*/ */
...@@ -283,6 +318,10 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> { ...@@ -283,6 +318,10 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
make_any_tuple(std::forward<Ts>(args)...)); make_any_tuple(std::forward<Ts>(args)...));
} }
/**************************************************************************
* miscellaneous actor operations *
**************************************************************************/
/** /**
* @brief Causes this actor to subscribe to the group @p what. * @brief Causes this actor to subscribe to the group @p what.
* *
...@@ -422,16 +461,21 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> { ...@@ -422,16 +461,21 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
on_sync_failure(fun); on_sync_failure(fun);
} }
/**************************************************************************
* here be dragons: end of public interface *
**************************************************************************/
/** @cond PRIVATE */ /** @cond PRIVATE */
local_actor(); local_actor();
inline actor eval_opts(spawn_options opts, actor res) { template<class ActorHandle>
inline ActorHandle eval_opts(spawn_options opts, ActorHandle res) {
if (has_monitor_flag(opts)) { if (has_monitor_flag(opts)) {
monitor(res); monitor(res.address());
} }
if (has_link_flag(opts)) { if (has_link_flag(opts)) {
link_to(res); link_to(res.address());
} }
return res; return res;
} }
......
...@@ -44,6 +44,14 @@ struct replies_to { ...@@ -44,6 +44,14 @@ struct replies_to {
}; };
}; };
template<class InputList, class OutputList>
struct replies_to_from_type_list;
template<typename... Is, typename... Os>
struct replies_to_from_type_list<util::type_list<Is...>, util::type_list<Os...>> {
typedef typename replies_to<Is...>::template with<Os...> type;
};
} // namespace cppa } // namespace cppa
#endif // CPPA_REPLIES_TO_HPP #endif // CPPA_REPLIES_TO_HPP
This diff is collapsed.
...@@ -28,68 +28,71 @@ ...@@ -28,68 +28,71 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_TYPED_ACTOR_PTR_HPP // this header contains prototype definitions of the spawn function famility;
#define CPPA_TYPED_ACTOR_PTR_HPP // implementations can be found in spawn.hpp (this header is included there)
#include "cppa/replies_to.hpp" #ifndef CPPA_SPAWN_FWD_HPP
#include "cppa/match_expr.hpp" #define CPPA_SPAWN_FWD_HPP
#include "cppa/typed_actor.hpp"
#include "cppa/spawn_options.hpp" #include "cppa/spawn_options.hpp"
#include "cppa/detail/typed_actor_util.hpp"
#include "cppa/util/type_list.hpp"
namespace cppa { namespace cppa {
template<typename... Signatures> /******************************************************************************
class typed_actor_ptr { * untyped actors *
******************************************************************************/
public: template<class Impl, spawn_options Options = no_spawn_options, typename... Ts>
actor spawn(Ts&&... args);
typedef util::type_list<Signatures...> signatures; template<spawn_options Options = no_spawn_options, typename... Ts>
actor spawn(Ts&&... args);
typed_actor_ptr() = default; template<class Impl, spawn_options Options = no_spawn_options, typename... Ts>
typed_actor_ptr(typed_actor_ptr&&) = default; actor spawn_in_group(const group&, Ts&&... args);
typed_actor_ptr(const typed_actor_ptr&) = default;
typed_actor_ptr& operator=(typed_actor_ptr&&) = default;
typed_actor_ptr& operator=(const typed_actor_ptr&) = default;
template<typename... Others> template<spawn_options Options = no_spawn_options, typename... Ts>
typed_actor_ptr(typed_actor_ptr<Others...> other) { actor spawn_in_group(const group&, Ts&&... args);
set(std::move(other));
}
template<typename... Others> /******************************************************************************
typed_actor_ptr& operator=(typed_actor_ptr<Others...> other) { * typed actors *
set(std::move(other)); ******************************************************************************/
return *this;
}
/** @cond PRIVATE */ namespace detail { // some utility
static typed_actor_ptr cast_from(actor_ptr from) {
return {std::move(from)};
}
const actor_ptr& type_erased() const { return m_ptr; }
actor_ptr& type_erased() { return m_ptr; }
/** @endcond */
private: template<typename TypedBehavior>
struct actor_handle_from_typed_behavior;
typed_actor_ptr(actor_ptr ptr) : m_ptr(std::move(ptr)) { } template<typename... Signatures>
struct actor_handle_from_typed_behavior<typed_behavior<Signatures...>> {
typedef typed_actor<Signatures...> type;
};
template<class ListA, class ListB> template<typename SignatureList>
inline void check_signatures() { struct actor_handle_from_signature_list;
static_assert(util::tl_is_strict_subset<ListA, ListB>::value,
"'this' must be a strict subset of 'other'");
}
template<typename... Others> template<typename... Signatures>
inline void set(typed_actor_ptr<Others...> other) { struct actor_handle_from_signature_list<util::type_list<Signatures...>> {
check_signatures<signatures, util::type_list<Others...>>(); typedef typed_actor<Signatures...> type;
m_ptr = std::move(other.type_erased()); };
}
actor_ptr m_ptr; } // namespace detail
}; template<spawn_options Options = no_spawn_options, typename F>
typename detail::actor_handle_from_typed_behavior<
typename util::get_callable_trait<F>::result_type
>::type
spawn_typed(F fun);
template<class Impl, spawn_options Options = no_spawn_options, typename... Ts>
typename detail::actor_handle_from_signature_list<
typename Impl::signatures
>::type
spawn_typed(Ts&&... args);
} // namespace cppa } // namespace cppa
#endif // CPPA_TYPED_ACTOR_PTR_HPP #endif // CPPA_SPAWN_FWD_HPP
...@@ -73,7 +73,7 @@ class typed_actor : util::comparable<typed_actor<Signatures...>> ...@@ -73,7 +73,7 @@ class typed_actor : util::comparable<typed_actor<Signatures...>>
/** /**
* @brief Identifies the base class for this kind of actor. * @brief Identifies the base class for this kind of actor.
*/ */
typedef typed_event_based_actor<Signatures...> impl; typedef typed_event_based_actor<Signatures...> base;
typedef util::type_list<Signatures...> signatures; typedef util::type_list<Signatures...> signatures;
......
...@@ -38,6 +38,49 @@ ...@@ -38,6 +38,49 @@
namespace cppa { namespace cppa {
namespace detail {
template<typename T>
struct match_hint_to_void {
typedef T type;
};
template<>
struct match_hint_to_void<match_hint> {
typedef void type;
};
template<typename T>
struct all_match_hints_to_void {
typedef typename T::input_types input_types;
typedef typename util::tl_map<
typename T::output_types,
match_hint_to_void
>::type
output_types;
typedef typename replies_to_from_type_list<
input_types,
output_types
>::type
type;
};
// this function is called from typed_behavior<...>::set and its whole
// purpose is to give users a nicer error message on a type mismatch
// (this function only has the type informations needed to understand the error)
template<class SignatureList, class InputList>
void static_check_typed_behavior_input() {
constexpr bool is_equal = util::tl_equal<SignatureList, InputList>::value;
// note: it might be worth considering to allow a wildcard in the
// InputList if its return type is identical to all "missing"
// input types ... however, it might lead to unexpected results
// and would cause a lot of not-so-straightforward code here
static_assert(is_equal, "given pattern cannot be used to initialize "
"typed behavior (exact match needed)");
}
} // namespace detail
template<typename... Signatures> template<typename... Signatures>
class typed_actor; class typed_actor;
...@@ -64,15 +107,13 @@ class typed_behavior { ...@@ -64,15 +107,13 @@ class typed_behavior {
typedef util::type_list<Signatures...> signatures; typedef util::type_list<Signatures...> signatures;
template<typename... Cs> template<typename... Cs, typename... Ts>
typed_behavior(match_expr<Cs...> expr) { typed_behavior(match_expr<Cs...> expr, Ts&&... args) {
static_asserts(expr); set(match_expr_collect(std::move(expr), std::forward<Ts>(args)...));
set(std::move(expr));
} }
template<typename... Cs> template<typename... Cs>
typed_behavior& operator=(match_expr<Cs...> expr) { typed_behavior& operator=(match_expr<Cs...> expr) {
static_asserts(expr);
set(std::move(expr)); set(std::move(expr));
return *this; return *this;
} }
...@@ -101,29 +142,24 @@ class typed_behavior { ...@@ -101,29 +142,24 @@ class typed_behavior {
behavior& unbox() { return m_bhvr; } behavior& unbox() { return m_bhvr; }
template<typename... Cs> template<typename... Cs>
void static_asserts(const match_expr<Cs...>&) { void set(match_expr<Cs...>&& expr) {
// check for (the lack of) guards
static_assert(util::conjunction< static_assert(util::conjunction<
detail::match_expr_has_no_guard<Cs>::value... detail::match_expr_has_no_guard<Cs>::value...
>::value, >::value,
"typed actors are not allowed to use guard expressions"); "typed actors are not allowed to use guard expressions");
static_assert(util::tl_is_distinct< // returning a match_hint from a message handler does
util::type_list< // not send anything back, so we can consider match_hint to be void
typename detail::deduce_signature<Cs>::arg_types... typedef typename util::tl_map<
> util::type_list<
>::value, typename detail::deduce_signature<Cs>::type...
"typed actors are not allowed to define " >,
"multiple patterns with identical signature"); detail::all_match_hints_to_void
} >::type
input;
template<typename... Cs> detail::static_check_typed_behavior_input<signatures, input>();
void set(match_expr<Cs...>&& expr) { // final (type-erasure) step
m_bhvr = std::move(expr); m_bhvr = std::move(expr);
using input = util::type_list<
typename detail::deduce_signature<Cs>::type...
>;
// check whether the signature is an exact match
static_assert(util::tl_equal<signatures, input>::value,
"'expr' does not match given signature");
} }
behavior m_bhvr; behavior m_bhvr;
......
...@@ -35,6 +35,10 @@ ...@@ -35,6 +35,10 @@
using namespace std; using namespace std;
using namespace cppa; using namespace cppa;
/******************************************************************************
* simple request/response test *
******************************************************************************/
struct my_request { int a; int b; }; struct my_request { int a; int b; };
typedef typed_actor<replies_to<my_request>::with<bool>> server_type; typedef typed_actor<replies_to<my_request>::with<bool>> server_type;
...@@ -55,7 +59,7 @@ server_type::behavior_type typed_server2(server_type::pointer) { ...@@ -55,7 +59,7 @@ server_type::behavior_type typed_server2(server_type::pointer) {
return typed_server1(); return typed_server1();
} }
class typed_server3 : public server_type::impl { class typed_server3 : public server_type::base {
public: public:
...@@ -71,11 +75,13 @@ class typed_server3 : public server_type::impl { ...@@ -71,11 +75,13 @@ class typed_server3 : public server_type::impl {
void client(event_based_actor* self, actor parent, server_type serv) { void client(event_based_actor* self, actor parent, server_type serv) {
self->sync_send(serv, my_request{0, 0}).then( self->sync_send(serv, my_request{0, 0}).then(
[](bool value) { [](bool value) -> int {
CPPA_CHECK_EQUAL(value, true); CPPA_CHECK_EQUAL(value, true);
return 42;
} }
) )
.continue_with([=] { .continue_with([=](int ival) {
CPPA_CHECK_EQUAL(ival, 42);
self->sync_send(serv, my_request{10, 20}).then( self->sync_send(serv, my_request{10, 20}).then(
[=](bool value) { [=](bool value) {
CPPA_CHECK_EQUAL(value, false); CPPA_CHECK_EQUAL(value, false);
...@@ -121,9 +127,111 @@ void test_typed_spawn(server_type ts) { ...@@ -121,9 +127,111 @@ void test_typed_spawn(server_type ts) {
self->send_exit(ts, exit_reason::user_shutdown); self->send_exit(ts, exit_reason::user_shutdown);
} }
/******************************************************************************
* test skipping of messages intentionally + using become() *
******************************************************************************/
struct get_state_msg { };
typedef typed_actor<
replies_to<get_state_msg>::with<string>,
replies_to<string>::with<void>,
replies_to<float>::with<void>,
replies_to<int>::with<void>
>
event_testee_type;
class event_testee : public event_testee_type::base {
public:
behavior_type wait4string() {
return {
on<get_state_msg>() >> [] {
return "wait4string";
},
on<string>() >> [=] {
become(wait4int());
},
(on<float>() || on<int>()) >> skip_message
};
}
behavior_type wait4int() {
return {
on<get_state_msg>() >> [] {
return "wait4int";
},
on<int>() >> [=] {
become(wait4float());
},
(on<float>() || on<string>()) >> [] {
return match_hint::skip;
}
};
}
behavior_type wait4float() {
return {
on<get_state_msg>() >> [] {
return "wait4float";
},
on<float>() >> [=] {
become(wait4string());
},
(on<string>() || on<int>()) >> [] {
return match_hint::skip;
}
};
}
behavior_type make_behavior() override {
return wait4int();
}
};
void test_event_testee() {
scoped_actor self;
auto et = self->spawn_typed<event_testee>();
string result;
self->send(et, 1);
self->send(et, 2);
self->send(et, 3);
self->send(et, .1f);
self->send(et, "hello event testee!");
self->send(et, .2f);
self->send(et, .3f);
self->send(et, "hello again event testee!");
self->send(et, "goodbye event testee!");
self->send(et, get_state_msg{});
self->receive (
on_arg_match >> [&](const string& str) {
result = str;
},
after(chrono::minutes(1)) >> [&]() {
CPPA_LOGF_ERROR("event_testee does not reply");
throw runtime_error("event_testee does not reply");
}
);
self->send_exit(et, exit_reason::user_shutdown);
self->await_all_other_actors_done();
CPPA_CHECK_EQUAL(result, "wait4int");
}
/******************************************************************************
* put it all together *
******************************************************************************/
int main() { int main() {
CPPA_TEST(test_typed_spawn); CPPA_TEST(test_typed_spawn);
// announce stuff
announce_tag<get_state_msg>();
announce<my_request>(&my_request::a, &my_request::b); announce<my_request>(&my_request::a, &my_request::b);
// run test series with typed_server*
test_typed_spawn(spawn_typed(typed_server1)); test_typed_spawn(spawn_typed(typed_server1));
CPPA_CHECKPOINT(); CPPA_CHECKPOINT();
await_all_actors_done(); await_all_actors_done();
...@@ -141,6 +249,13 @@ int main() { ...@@ -141,6 +249,13 @@ int main() {
} }
CPPA_CHECKPOINT(); CPPA_CHECKPOINT();
await_all_actors_done(); await_all_actors_done();
// run test series with event_testee
test_event_testee();
CPPA_CHECKPOINT();
await_all_actors_done();
// call it a day
shutdown(); shutdown();
/* /*
auto sptr = spawn_typed_server(); auto sptr = spawn_typed_server();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment