Commit f1d7e9ce authored by Dominik Charousset's avatar Dominik Charousset

Add missing member functions to typed_actor_view

parent 3ae23f9e
...@@ -14,6 +14,8 @@ is based on [Keep a Changelog](https://keepachangelog.com). ...@@ -14,6 +14,8 @@ is based on [Keep a Changelog](https://keepachangelog.com).
- Add new `*_weak` variants of `scheduled_actor::run_{delayed, scheduled}`. - Add new `*_weak` variants of `scheduled_actor::run_{delayed, scheduled}`.
These functions add no reference count to their actor, allowing it to become These functions add no reference count to their actor, allowing it to become
unreachable if other actors no longer reference it. unreachable if other actors no longer reference it.
- Typed actors that use a `typed_actor_pointer` can now access the
`run_{delayed,scheduled}` member functions.
### Fixed ### Fixed
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
namespace caf { namespace caf {
/// Provides a view to an actor that implements this messaging interface without
/// knowledge of the actual type.
template <class... Sigs> template <class... Sigs>
class typed_actor_pointer : public typed_actor_view_base { class typed_actor_pointer : public typed_actor_view_base {
public: public:
...@@ -76,8 +78,12 @@ public: ...@@ -76,8 +78,12 @@ public:
return &view_; return &view_;
} }
explicit operator bool() const { bool operator!() const noexcept {
return static_cast<bool>(view_.internal_ptr()); return internal_ptr() == nullptr;
}
explicit operator bool() const noexcept {
return internal_ptr() != nullptr;
} }
/// @private /// @private
......
...@@ -204,6 +204,35 @@ public: ...@@ -204,6 +204,35 @@ public:
self_->send_exit(whom, std::move(reason)); self_->send_exit(whom, std::move(reason));
} }
// -- scheduling actions -----------------------------------------------------
/// @copydoc scheduled_actor::run_scheduled
template <class Clock, class Duration, class F>
disposable
run_scheduled(std::chrono::time_point<Clock, Duration> when, F what) {
return self_->run_scheduled(when, std::move(what));
}
/// @copydoc scheduled_actor::run_scheduled_weak
template <class Clock, class Duration, class F>
disposable
run_scheduled_weak(std::chrono::time_point<Clock, Duration> when, F what) {
return self_->run_scheduled_weak(when, std::move(what));
}
/// @copydoc scheduled_actor::run_delayed
template <class Rep, class Period, class F>
disposable run_delayed(std::chrono::duration<Rep, Period> delay, F what) {
return self_->run_delayed(delay, std::move(what));
}
/// @copydoc scheduled_actor::run_delayed_weak
template <class Rep, class Period, class F>
disposable
run_delayed_weak(std::chrono::duration<Rep, Period> delay, F what) {
return self_->run_delayed_weak(delay, std::move(what));
}
// -- miscellaneous actor operations ----------------------------------------- // -- miscellaneous actor operations -----------------------------------------
void quit(exit_reason reason = exit_reason::normal) { void quit(exit_reason reason = exit_reason::normal) {
......
...@@ -13,14 +13,43 @@ using namespace std::literals; ...@@ -13,14 +13,43 @@ using namespace std::literals;
namespace { namespace {
using fixture = test_coordinator_fixture<>; behavior int_behavior() {
behavior dummy_behavior() {
return { return {
[](int) {}, [](int) {},
}; };
} }
using int_actor = typed_actor<result<void>(int)>;
using int_actor_ptr = int_actor::pointer_view;
struct int_actor_state {
using init_fn = std::function<void(int_actor_ptr)>;
int_actor_state(int_actor_ptr ptr, init_fn fn)
: self(ptr), init(std::move(fn)) {
// nop
}
int_actor::behavior_type make_behavior() {
init(self);
return {
[](int) {},
};
}
int_actor_ptr self;
init_fn init;
};
using int_actor_impl = int_actor::stateful_impl<int_actor_state>;
struct fixture : test_coordinator_fixture<> {
int_actor spawn_int_actor(int_actor_state ::init_fn init) {
return sys.spawn<int_actor_impl>(std::move(init));
}
};
} // namespace } // namespace
BEGIN_FIXTURE_SCOPE(fixture) BEGIN_FIXTURE_SCOPE(fixture)
...@@ -32,7 +61,7 @@ SCENARIO("run_delayed triggers an action after a relative timeout") { ...@@ -32,7 +61,7 @@ SCENARIO("run_delayed triggers an action after a relative timeout") {
auto called = std::make_shared<bool>(false); auto called = std::make_shared<bool>(false);
auto aut = sys.spawn([called](event_based_actor* self) { auto aut = sys.spawn([called](event_based_actor* self) {
self->run_delayed(1s, [called] { *called = true; }); self->run_delayed(1s, [called] { *called = true; });
return dummy_behavior(); return int_behavior();
}); });
sched.run(); sched.run();
CHECK(!*called); CHECK(!*called);
...@@ -45,7 +74,35 @@ SCENARIO("run_delayed triggers an action after a relative timeout") { ...@@ -45,7 +74,35 @@ SCENARIO("run_delayed triggers an action after a relative timeout") {
auto pending = disposable{}; auto pending = disposable{};
auto aut = sys.spawn([called, &pending](event_based_actor* self) { auto aut = sys.spawn([called, &pending](event_based_actor* self) {
pending = self->run_delayed(1s, [called] { *called = true; }); pending = self->run_delayed(1s, [called] { *called = true; });
return dummy_behavior(); return int_behavior();
});
sched.run();
CHECK(!*called);
pending.dispose();
advance_time(1s);
sched.run();
CHECK(!*called);
}
}
}
GIVEN("a typed actor") {
WHEN("the actor schedules an action with run_delayed") {
THEN("the action triggers after the relative timeout") {
auto called = std::make_shared<bool>(false);
auto aut = spawn_int_actor([called](int_actor_ptr self) {
self->run_delayed(1s, [called] { *called = true; });
});
sched.run();
CHECK(!*called);
advance_time(1s);
sched.run();
CHECK(*called);
}
AND_THEN("disposing the pending timeout cancels the action") {
auto called = std::make_shared<bool>(false);
auto pending = disposable{};
auto aut = spawn_int_actor([called, &pending](int_actor_ptr self) {
pending = self->run_delayed(1s, [called] { *called = true; });
}); });
sched.run(); sched.run();
CHECK(!*called); CHECK(!*called);
...@@ -65,7 +122,7 @@ SCENARIO("run_delayed_weak triggers an action after a relative timeout") { ...@@ -65,7 +122,7 @@ SCENARIO("run_delayed_weak triggers an action after a relative timeout") {
auto called = std::make_shared<bool>(false); auto called = std::make_shared<bool>(false);
auto aut = sys.spawn([called](event_based_actor* self) { auto aut = sys.spawn([called](event_based_actor* self) {
self->run_delayed_weak(1s, [called] { *called = true; }); self->run_delayed_weak(1s, [called] { *called = true; });
return dummy_behavior(); return int_behavior();
}); });
sched.run(); sched.run();
CHECK(!*called); CHECK(!*called);
...@@ -77,7 +134,7 @@ SCENARIO("run_delayed_weak triggers an action after a relative timeout") { ...@@ -77,7 +134,7 @@ SCENARIO("run_delayed_weak triggers an action after a relative timeout") {
auto called = std::make_shared<bool>(false); auto called = std::make_shared<bool>(false);
sys.spawn([called](event_based_actor* self) { sys.spawn([called](event_based_actor* self) {
self->run_delayed_weak(1s, [called] { *called = true; }); self->run_delayed_weak(1s, [called] { *called = true; });
return dummy_behavior(); return int_behavior();
}); });
sched.run(); // Note: actor cleaned up after this line. sched.run(); // Note: actor cleaned up after this line.
CHECK(!*called); CHECK(!*called);
...@@ -90,7 +147,46 @@ SCENARIO("run_delayed_weak triggers an action after a relative timeout") { ...@@ -90,7 +147,46 @@ SCENARIO("run_delayed_weak triggers an action after a relative timeout") {
auto pending = disposable{}; auto pending = disposable{};
auto aut = sys.spawn([called, &pending](event_based_actor* self) { auto aut = sys.spawn([called, &pending](event_based_actor* self) {
pending = self->run_delayed_weak(1s, [called] { *called = true; }); pending = self->run_delayed_weak(1s, [called] { *called = true; });
return dummy_behavior(); return int_behavior();
});
sched.run();
CHECK(!*called);
pending.dispose();
advance_time(1s);
sched.run();
CHECK(!*called);
}
}
}
GIVEN("a typed actor") {
WHEN("the actor schedules an action with run_delayed") {
THEN("the action triggers after the relative timeout for live actors") {
auto called = std::make_shared<bool>(false);
auto aut = spawn_int_actor([called](int_actor_ptr self) {
self->run_delayed_weak(1s, [called] { *called = true; });
});
sched.run();
CHECK(!*called);
advance_time(1s);
sched.run();
CHECK(*called);
}
AND_THEN("no action triggers for terminated actors") {
auto called = std::make_shared<bool>(false);
spawn_int_actor([called](int_actor_ptr self) {
self->run_delayed_weak(1s, [called] { *called = true; });
});
sched.run(); // Note: actor cleaned up after this line.
CHECK(!*called);
advance_time(1s);
sched.run();
CHECK(!*called);
}
AND_THEN("disposing the pending timeout cancels the action") {
auto called = std::make_shared<bool>(false);
auto pending = disposable{};
auto aut = spawn_int_actor([called, &pending](int_actor_ptr self) {
pending = self->run_delayed_weak(1s, [called] { *called = true; });
}); });
sched.run(); sched.run();
CHECK(!*called); CHECK(!*called);
......
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