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

Fix spawn_in_group<T>, close #509

parent 4746c434
......@@ -360,20 +360,24 @@ public:
return actor_cast<Handle>(std::move(*res));
}
template <class T, spawn_options Os = no_spawn_options,
class Iter, class F, class... Ts>
/// Spawns a class-based actor `T` immediately joining the groups in
/// range `[first, last)`.
/// @private
template <class T, spawn_options Os, class Iter, class... Ts>
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>();
auto irange = make_input_range(first, second);
auto irange = make_input_range(first, last);
cfg.groups = &irange;
return spawn_class<T, Os>(cfg, std::forward<Ts>(xs)...);
}
template <spawn_options Os = no_spawn_options,
class Iter, class F, class... Ts>
/// Spawns a class-based actor `T` immediately joining the groups in
/// range `[first, last)`.
/// @private
template <spawn_options Os, class Iter, class F, class... Ts>
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) {
check_invariants<infer_impl_from_fun_t<F>>();
auto irange = make_input_range(first, second);
......@@ -386,7 +390,7 @@ public:
infer_handle_from_fun_t<F>
spawn_in_groups(std::initializer_list<group> gs, F fun, Ts&&... xs) {
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)...);
}
......@@ -395,7 +399,7 @@ public:
infer_handle_from_fun_t<F>
spawn_in_groups(const Gs& gs, F fun, Ts&&... xs) {
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)...);
}
......@@ -403,7 +407,8 @@ public:
template <spawn_options Os = no_spawn_options, class F, class... Ts>
infer_handle_from_fun_t<F>
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`.
......@@ -411,7 +416,7 @@ public:
infer_handle_from_class_t<T>
spawn_in_groups(std::initializer_list<group> gs, Ts&&... xs) {
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)...);
}
......@@ -420,7 +425,7 @@ public:
infer_handle_from_class_t<T>
spawn_in_groups(const Gs& gs, Ts&&... xs) {
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)...);
}
......@@ -428,7 +433,7 @@ public:
template <class T, spawn_options Os = no_spawn_options, class... Ts>
infer_handle_from_class_t<T>
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`
......
......@@ -140,39 +140,39 @@ public:
class... Ts>
actor spawn_in_groups(const Groups& gs, Ts&&... xs) {
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>
actor spawn_in_groups(std::initializer_list<group> gs, Ts&&... xs) {
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>
actor spawn_in_group(const group& grp, Ts&&... xs) {
actor_config cfg{context()};
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>
actor spawn_in_groups(const Groups& gs, F fun, Ts&&... xs) {
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>
actor spawn_in_groups(std::initializer_list<group> gs, F fun, Ts&&... xs) {
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>
actor spawn_in_group(const group& grp, F fun, Ts&&... xs) {
actor_config cfg{context()};
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 ------------------------------------------
......
......@@ -28,10 +28,30 @@
using namespace caf;
namespace {
using msg_atom = atom_constant<atom("msg")>;
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 grp = self->system().groups().get_local("test");
self->join(grp);
......@@ -53,8 +73,35 @@ behavior testee(event_based_actor* self) {
};
}
CAF_TEST(test_local_group) {
actor_system_config cfg;
actor_system system{cfg};
system.spawn(testee);
struct fixture {
actor_system_config config;
actor_system system{config};
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