Commit 043aa21d authored by Dominik Charousset's avatar Dominik Charousset

Fix spawn_in_group<T>, close #509

parent 4746c434
...@@ -360,20 +360,24 @@ public: ...@@ -360,20 +360,24 @@ public:
return actor_cast<Handle>(std::move(*res)); return actor_cast<Handle>(std::move(*res));
} }
template <class T, spawn_options Os = no_spawn_options, /// Spawns a class-based actor `T` immediately joining the groups in
class Iter, class F, class... Ts> /// range `[first, last)`.
/// @private
template <class T, spawn_options Os, class Iter, class... Ts>
infer_handle_from_class_t<T> infer_handle_from_class_t<T>
spawn_in_groups_impl(actor_config& cfg, Iter first, Iter second, Ts&&... xs) { spawn_class_in_groups(actor_config& cfg, Iter first, Iter last, Ts&&... xs) {
check_invariants<T>(); check_invariants<T>();
auto irange = make_input_range(first, second); auto irange = make_input_range(first, last);
cfg.groups = &irange; cfg.groups = &irange;
return spawn_class<T, Os>(cfg, std::forward<Ts>(xs)...); return spawn_class<T, Os>(cfg, std::forward<Ts>(xs)...);
} }
template <spawn_options Os = no_spawn_options, /// Spawns a class-based actor `T` immediately joining the groups in
class Iter, class F, class... Ts> /// range `[first, last)`.
/// @private
template <spawn_options Os, class Iter, class F, class... Ts>
infer_handle_from_fun_t<F> infer_handle_from_fun_t<F>
spawn_in_groups_impl(actor_config& cfg, Iter first, Iter second, spawn_fun_in_groups(actor_config& cfg, Iter first, Iter second,
F& fun, Ts&&... xs) { F& fun, Ts&&... xs) {
check_invariants<infer_impl_from_fun_t<F>>(); check_invariants<infer_impl_from_fun_t<F>>();
auto irange = make_input_range(first, second); auto irange = make_input_range(first, second);
...@@ -386,7 +390,7 @@ public: ...@@ -386,7 +390,7 @@ public:
infer_handle_from_fun_t<F> infer_handle_from_fun_t<F>
spawn_in_groups(std::initializer_list<group> gs, F fun, Ts&&... xs) { spawn_in_groups(std::initializer_list<group> gs, F fun, Ts&&... xs) {
actor_config cfg; actor_config cfg;
return spawn_in_groups_impl(cfg, gs.begin(), gs.end(), fun, return spawn_fun_in_groups<Os>(cfg, gs.begin(), gs.end(), fun,
std::forward<Ts>(xs)...); std::forward<Ts>(xs)...);
} }
...@@ -395,7 +399,7 @@ public: ...@@ -395,7 +399,7 @@ public:
infer_handle_from_fun_t<F> infer_handle_from_fun_t<F>
spawn_in_groups(const Gs& gs, F fun, Ts&&... xs) { spawn_in_groups(const Gs& gs, F fun, Ts&&... xs) {
actor_config cfg; actor_config cfg;
return spawn_in_groups_impl(cfg, gs.begin(), gs.end(), fun, return spawn_fun_in_groups<Os>(cfg, gs.begin(), gs.end(), fun,
std::forward<Ts>(xs)...); std::forward<Ts>(xs)...);
} }
...@@ -403,7 +407,8 @@ public: ...@@ -403,7 +407,8 @@ public:
template <spawn_options Os = no_spawn_options, class F, class... Ts> template <spawn_options Os = no_spawn_options, class F, class... Ts>
infer_handle_from_fun_t<F> infer_handle_from_fun_t<F>
spawn_in_group(const group& grp, F fun, Ts&&... xs) { spawn_in_group(const group& grp, F fun, Ts&&... xs) {
return spawn_in_groups({grp}, std::move(fun), std::forward<Ts>(xs)...); return spawn_fun_in_groups<Os>({grp}, std::move(fun),
std::forward<Ts>(xs)...);
} }
/// Returns a new class-based actor subscribed to all groups in `gs`. /// Returns a new class-based actor subscribed to all groups in `gs`.
...@@ -411,7 +416,7 @@ public: ...@@ -411,7 +416,7 @@ public:
infer_handle_from_class_t<T> infer_handle_from_class_t<T>
spawn_in_groups(std::initializer_list<group> gs, Ts&&... xs) { spawn_in_groups(std::initializer_list<group> gs, Ts&&... xs) {
actor_config cfg; actor_config cfg;
return spawn_in_groups_impl<T>(cfg, gs.begin(), gs.end(), return spawn_class_in_groups<T, Os>(cfg, gs.begin(), gs.end(),
std::forward<Ts>(xs)...); std::forward<Ts>(xs)...);
} }
...@@ -420,7 +425,7 @@ public: ...@@ -420,7 +425,7 @@ public:
infer_handle_from_class_t<T> infer_handle_from_class_t<T>
spawn_in_groups(const Gs& gs, Ts&&... xs) { spawn_in_groups(const Gs& gs, Ts&&... xs) {
actor_config cfg; actor_config cfg;
return spawn_in_groups_impl<T>(cfg, gs.begin(), gs.end(), return spawn_class_in_groups<T, Os>(cfg, gs.begin(), gs.end(),
std::forward<Ts>(xs)...); std::forward<Ts>(xs)...);
} }
...@@ -428,7 +433,7 @@ public: ...@@ -428,7 +433,7 @@ public:
template <class T, spawn_options Os = no_spawn_options, class... Ts> template <class T, spawn_options Os = no_spawn_options, class... Ts>
infer_handle_from_class_t<T> infer_handle_from_class_t<T>
spawn_in_group(const group& grp, Ts&&... xs) { spawn_in_group(const group& grp, Ts&&... xs) {
return spawn_in_groups<T>({grp}, std::forward<Ts>(xs)...); return spawn_in_groups<T, Os>({grp}, std::forward<Ts>(xs)...);
} }
/// Returns whether this actor system calls `await_all_actors_done` /// Returns whether this actor system calls `await_all_actors_done`
......
...@@ -140,39 +140,39 @@ public: ...@@ -140,39 +140,39 @@ public:
class... Ts> class... Ts>
actor spawn_in_groups(const Groups& gs, Ts&&... xs) { actor spawn_in_groups(const Groups& gs, Ts&&... xs) {
actor_config cfg{context()}; actor_config cfg{context()};
return eval_opts(Os, system().spawn_in_groups_impl<T, make_unbound(Os)>(cfg, gs.begin(), gs.end(), std::forward<Ts>(xs)...)); return eval_opts(Os, system().spawn_class_in_groups<T, make_unbound(Os)>(cfg, gs.begin(), gs.end(), std::forward<Ts>(xs)...));
} }
template <class T, spawn_options Os = no_spawn_options, class... Ts> template <class T, spawn_options Os = no_spawn_options, class... Ts>
actor spawn_in_groups(std::initializer_list<group> gs, Ts&&... xs) { actor spawn_in_groups(std::initializer_list<group> gs, Ts&&... xs) {
actor_config cfg{context()}; actor_config cfg{context()};
return eval_opts(Os, system().spawn_in_groups_impl<T, make_unbound(Os)>(cfg, gs.begin(), gs.end(), std::forward<Ts>(xs)...)); return eval_opts(Os, system().spawn_class_in_groups<T, make_unbound(Os)>(cfg, gs.begin(), gs.end(), std::forward<Ts>(xs)...));
} }
template <class T, spawn_options Os = no_spawn_options, class... Ts> template <class T, spawn_options Os = no_spawn_options, class... Ts>
actor spawn_in_group(const group& grp, Ts&&... xs) { actor spawn_in_group(const group& grp, Ts&&... xs) {
actor_config cfg{context()}; actor_config cfg{context()};
auto first = &grp; auto first = &grp;
return eval_opts(Os, system().spawn_in_groups_impl<T, make_unbound(Os)>(cfg, first, first + 1, std::forward<Ts>(xs)...)); return eval_opts(Os, system().spawn_class_in_groups<T, make_unbound(Os)>(cfg, first, first + 1, std::forward<Ts>(xs)...));
} }
template <spawn_options Os = no_spawn_options, class Groups, class F, class... Ts> template <spawn_options Os = no_spawn_options, class Groups, class F, class... Ts>
actor spawn_in_groups(const Groups& gs, F fun, Ts&&... xs) { actor spawn_in_groups(const Groups& gs, F fun, Ts&&... xs) {
actor_config cfg{context()}; actor_config cfg{context()};
return eval_opts(Os, system().spawn_in_groups_impl<make_unbound(Os)>(cfg, gs.begin(), gs.end(), fun, std::forward<Ts>(xs)...)); return eval_opts(Os, system().spawn_fun_in_groups<make_unbound(Os)>(cfg, gs.begin(), gs.end(), fun, std::forward<Ts>(xs)...));
} }
template <spawn_options Os = no_spawn_options, class F, class... Ts> template <spawn_options Os = no_spawn_options, class F, class... Ts>
actor spawn_in_groups(std::initializer_list<group> gs, F fun, Ts&&... xs) { actor spawn_in_groups(std::initializer_list<group> gs, F fun, Ts&&... xs) {
actor_config cfg{context()}; actor_config cfg{context()};
return eval_opts(Os, system().spawn_in_groups_impl<make_unbound(Os)>(cfg, gs.begin(), gs.end(), fun, std::forward<Ts>(xs)...)); return eval_opts(Os, system().spawn_fun_in_groups<make_unbound(Os)>(cfg, gs.begin(), gs.end(), fun, std::forward<Ts>(xs)...));
} }
template <spawn_options Os = no_spawn_options, class F, class... Ts> template <spawn_options Os = no_spawn_options, class F, class... Ts>
actor spawn_in_group(const group& grp, F fun, Ts&&... xs) { actor spawn_in_group(const group& grp, F fun, Ts&&... xs) {
actor_config cfg{context()}; actor_config cfg{context()};
auto first = &grp; auto first = &grp;
return eval_opts(Os, system().spawn_in_groups_impl<make_unbound(Os)>(cfg, first, first + 1, fun, std::forward<Ts>(xs)...)); return eval_opts(Os, system().spawn_fun_in_groups<make_unbound(Os)>(cfg, first, first + 1, fun, std::forward<Ts>(xs)...));
} }
// -- sending asynchronous messages ------------------------------------------ // -- sending asynchronous messages ------------------------------------------
......
...@@ -28,10 +28,30 @@ ...@@ -28,10 +28,30 @@
using namespace caf; using namespace caf;
namespace {
using msg_atom = atom_constant<atom("msg")>; using msg_atom = atom_constant<atom("msg")>;
using timeout_atom = atom_constant<atom("timeout")>; using timeout_atom = atom_constant<atom("timeout")>;
behavior testee(event_based_actor* self) { class testee1 : public event_based_actor {
public:
testee1(actor_config& cfg) : event_based_actor(cfg), x_(0) {
// nop
}
behavior make_behavior() override {
return {
[=](put_atom, int x) { x_ = x; },
[=](get_atom) { return x_; }
};
}
private:
int x_;
};
behavior testee2(event_based_actor* self) {
auto counter = std::make_shared<int>(0); auto counter = std::make_shared<int>(0);
auto grp = self->system().groups().get_local("test"); auto grp = self->system().groups().get_local("test");
self->join(grp); self->join(grp);
...@@ -53,8 +73,35 @@ behavior testee(event_based_actor* self) { ...@@ -53,8 +73,35 @@ behavior testee(event_based_actor* self) {
}; };
} }
CAF_TEST(test_local_group) { struct fixture {
actor_system_config cfg; actor_system_config config;
actor_system system{cfg}; actor_system system{config};
system.spawn(testee); scoped_actor self{system};
};
} // namespace <anonymous>
CAF_TEST_FIXTURE_SCOPE(group_tests, fixture)
CAF_TEST(function_based_self_joining) {
system.spawn(testee2);
} }
CAF_TEST(class_based_joined_at_spawn) {
auto grp = system.groups().get_local("test");
auto tst = system.spawn_in_group<testee1>(grp);
self->send(grp, put_atom::value, 42);
self->request(tst, infinite, get_atom::value).receive(
[&](int x) {
CAF_REQUIRE_EQUAL(x, 42);
},
[&](const error& e) {
CAF_FAIL("error: " << system.render(e));
}
);
// groups holds a reference to testee, stop manually
self->send_exit(tst, exit_reason::user_shutdown);
}
CAF_TEST_FIXTURE_SCOPE_END()
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