Commit c6904641 authored by Dominik Charousset's avatar Dominik Charousset

Make delayed_anon_send a free function

parent 5d6cda55
...@@ -64,11 +64,11 @@ public: ...@@ -64,11 +64,11 @@ public:
group(intrusive_ptr<abstract_group> gptr); group(intrusive_ptr<abstract_group> gptr);
inline explicit operator bool() const noexcept { explicit operator bool() const noexcept {
return static_cast<bool>(ptr_); return static_cast<bool>(ptr_);
} }
inline bool operator!() const noexcept { bool operator!() const noexcept {
return !ptr_; return !ptr_;
} }
...@@ -76,7 +76,7 @@ public: ...@@ -76,7 +76,7 @@ public:
intptr_t compare(const group& other) const noexcept; intptr_t compare(const group& other) const noexcept;
inline intptr_t compare(const invalid_group_t&) const noexcept { intptr_t compare(const invalid_group_t&) const noexcept {
return ptr_ ? 1 : 0; return ptr_ ? 1 : 0;
} }
...@@ -98,12 +98,16 @@ public: ...@@ -98,12 +98,16 @@ public:
friend error inspect(deserializer&, group&); friend error inspect(deserializer&, group&);
inline abstract_group* get() const noexcept { abstract_group* get() const noexcept {
return ptr_.get(); return ptr_.get();
} }
/// @cond PRIVATE /// @cond PRIVATE
actor_system& system() const {
return ptr_->system();
}
template <class... Ts> template <class... Ts>
void eq_impl(message_id mid, strong_actor_ptr sender, void eq_impl(message_id mid, strong_actor_ptr sender,
execution_unit* ctx, Ts&&... xs) const { execution_unit* ctx, Ts&&... xs) const {
...@@ -113,27 +117,25 @@ public: ...@@ -113,27 +117,25 @@ public:
make_message(std::forward<Ts>(xs)...), ctx); make_message(std::forward<Ts>(xs)...), ctx);
} }
inline bool subscribe(strong_actor_ptr who) const { bool subscribe(strong_actor_ptr who) const {
if (!ptr_) if (!ptr_)
return false; return false;
return ptr_->subscribe(std::move(who)); return ptr_->subscribe(std::move(who));
} }
inline void unsubscribe(const actor_control_block* who) const { void unsubscribe(const actor_control_block* who) const {
if (ptr_) if (ptr_)
ptr_->unsubscribe(who); ptr_->unsubscribe(who);
} }
/// CAF's messaging primitives assume a non-null guarantee. A group const group* operator->() const noexcept {
/// object indirects pointer-like access to a group to prevent UB.
inline const group* operator->() const noexcept {
return this; return this;
} }
/// @endcond /// @endcond
private: private:
inline abstract_group* release() noexcept { abstract_group* release() noexcept {
return ptr_.release(); return ptr_.release();
} }
...@@ -150,7 +152,7 @@ std::string to_string(const group& x); ...@@ -150,7 +152,7 @@ std::string to_string(const group& x);
namespace std { namespace std {
template <> template <>
struct hash<caf::group> { struct hash<caf::group> {
inline size_t operator()(const caf::group& x) const { size_t operator()(const caf::group& x) const {
// groups are singleton objects, the address is thus the best possible hash // groups are singleton objects, the address is thus the best possible hash
return !x ? 0 : reinterpret_cast<size_t>(x.get()); return !x ? 0 : reinterpret_cast<size_t>(x.get());
} }
......
...@@ -23,19 +23,18 @@ ...@@ -23,19 +23,18 @@
#include "caf/actor.hpp" #include "caf/actor.hpp"
#include "caf/actor_cast.hpp" #include "caf/actor_cast.hpp"
#include "caf/actor_clock.hpp"
#include "caf/actor_control_block.hpp" #include "caf/actor_control_block.hpp"
#include "caf/check_typed_input.hpp" #include "caf/check_typed_input.hpp"
#include "caf/duration.hpp" #include "caf/duration.hpp"
#include "caf/no_stages.hpp"
#include "caf/response_type.hpp"
#include "caf/response_handle.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/message.hpp" #include "caf/message.hpp"
#include "caf/message_priority.hpp" #include "caf/message_priority.hpp"
#include "caf/no_stages.hpp"
#include "caf/response_handle.hpp" #include "caf/response_handle.hpp"
#include "caf/response_type.hpp" #include "caf/response_type.hpp"
#include "caf/scheduler/abstract_coordinator.hpp" #include "caf/scheduler/abstract_coordinator.hpp"
#include "caf/send.hpp"
namespace caf { namespace caf {
namespace mixin { namespace mixin {
...@@ -119,7 +118,8 @@ public: ...@@ -119,7 +118,8 @@ public:
template <message_priority P = message_priority::normal, class Rep = int, template <message_priority P = message_priority::normal, class Rep = int,
class Period = std::ratio<1>, class Dest = actor, class... Ts> class Period = std::ratio<1>, class Dest = actor, class... Ts>
void delayed_send(const Dest& dest, std::chrono::duration<Rep, Period> rtime, detail::enable_if_t<!std::is_same<Dest, group>::value>
delayed_send(const Dest& dest, std::chrono::duration<Rep, Period> rtime,
Ts&&... xs) { Ts&&... xs) {
using token = using token =
detail::type_list< detail::type_list<
...@@ -156,56 +156,46 @@ public: ...@@ -156,56 +156,46 @@ public:
"this actor does not accept the response message"); "this actor does not accept the response message");
if (dest) { if (dest) {
auto& clock = dptr()->system().clock(); auto& clock = dptr()->system().clock();
auto t = clock.now() + rtime; auto timeout = clock.now() + rtime;
delayed_send_impl(clock, dptr()->ctrl(), dest, P, t, clock.schedule_message(timeout, actor_cast<strong_actor_ptr>(dest),
std::forward<Ts>(xs)...); make_mailbox_element(dptr()->ctrl(),
make_message_id(P), no_stages,
std::forward<Ts>(xs)...));
} }
} }
template <message_priority P = message_priority::normal, class Dest = actor, template <class Rep = int, class Period = std::ratio<1>, class Dest = actor,
class Rep = int, class Period = std::ratio<1>, class... Ts> class... Ts>
void delayed_anon_send(const Dest& dest, void delayed_send(const group& dest, std::chrono::duration<Rep, Period> rtime,
std::chrono::duration<Rep, Period> rtime, Ts&&... xs) { Ts&&... xs) {
static_assert(sizeof...(Ts) > 0, "no message to send"); static_assert(!statically_typed<Subtype>(),
using token = "statically typed actors are not allowed to send to groups");
detail::type_list<
typename detail::implicit_conversions<
typename std::decay<Ts>::type
>::type...>;
static_assert(response_type_unbox<
signatures_of_t<Dest>,
token
>::valid,
"receiver does not accept given message");
if (dest) { if (dest) {
auto& clock = dptr()->system().clock(); auto& clock = dptr()->system().clock();
auto t = clock.now() + rtime; auto timeout = clock.now() + rtime;
delayed_send_impl(clock, nullptr, dest, P, t, std::forward<Ts>(xs)...); clock.schedule_message(timeout, dest, dptr()->ctrl(),
make_message(std::forward<Ts>(xs)...));
} }
} }
private: template <message_priority P = message_priority::normal, class Dest = actor,
Subtype* dptr() { class Rep = int, class Period = std::ratio<1>, class... Ts>
return static_cast<Subtype*>(this); void delayed_anon_send(const Dest& dest,
std::chrono::duration<Rep, Period> rtime, Ts&&... xs)
CAF_DEPRECATED_MSG("use the free function instead") {
caf::delayed_anon_send<P>(dest, rtime, std::forward<Ts>(xs)...);
} }
template <class... Ts> template <class Rep = int, class Period = std::ratio<1>, class... Ts>
static void delayed_send_impl(actor_clock& clk, strong_actor_ptr src, void delayed_anon_send(const group& dest,
const group& dst, message_priority, std::chrono::duration<Rep, Period> rtime, Ts&&... xs)
actor_clock::time_point tout, Ts&&... xs) { CAF_DEPRECATED_MSG("use the free function instead") {
clk.schedule_message(tout, dst, std::move(src), caf::delayed_anon_send(dest, rtime, std::forward<Ts>(xs)...);
make_message(std::forward<Ts>(xs)...));
} }
template <class ActorHandle, class... Ts> private:
static void delayed_send_impl(actor_clock& clk, strong_actor_ptr src, Subtype* dptr() {
const ActorHandle& dst, message_priority prio, return static_cast<Subtype*>(this);
actor_clock::time_point tout,
Ts&&... xs) {
clk.schedule_message(tout, actor_cast<strong_actor_ptr>(dst),
make_mailbox_element(std::move(src),
make_message_id(prio), no_stages,
std::forward<Ts>(xs)...));
} }
}; };
......
...@@ -19,17 +19,19 @@ ...@@ -19,17 +19,19 @@
#pragma once #pragma once
#include "caf/actor.hpp" #include "caf/actor.hpp"
#include "caf/message.hpp"
#include "caf/actor_cast.hpp"
#include "caf/actor_addr.hpp" #include "caf/actor_addr.hpp"
#include "caf/message_id.hpp" #include "caf/actor_cast.hpp"
#include "caf/typed_actor.hpp" #include "caf/check_typed_input.hpp"
#include "caf/is_message_sink.hpp"
#include "caf/local_actor.hpp" #include "caf/local_actor.hpp"
#include "caf/mailbox_element.hpp"
#include "caf/message.hpp"
#include "caf/message_id.hpp"
#include "caf/message_priority.hpp"
#include "caf/no_stages.hpp"
#include "caf/response_type.hpp" #include "caf/response_type.hpp"
#include "caf/system_messages.hpp" #include "caf/system_messages.hpp"
#include "caf/is_message_sink.hpp" #include "caf/typed_actor.hpp"
#include "caf/message_priority.hpp"
#include "caf/check_typed_input.hpp"
namespace caf { namespace caf {
...@@ -108,6 +110,38 @@ void anon_send(const Dest& dest, Ts&&... xs) { ...@@ -108,6 +110,38 @@ void anon_send(const Dest& dest, Ts&&... xs) {
std::forward<Ts>(xs)...); std::forward<Ts>(xs)...);
} }
template <message_priority P = message_priority::normal, class Dest = actor,
class Rep = int, class Period = std::ratio<1>, class... Ts>
detail::enable_if_t<!std::is_same<Dest, group>::value>
delayed_anon_send(const Dest& dest, std::chrono::duration<Rep, Period> rtime,
Ts&&... xs) {
static_assert(sizeof...(Ts) > 0, "no message to send");
using token = detail::type_list<typename detail::implicit_conversions<
typename std::decay<Ts>::type>::type...>;
static_assert(response_type_unbox<signatures_of_t<Dest>, token>::valid,
"receiver does not accept given message");
if (dest) {
auto& clock = dest->home_system().clock();
auto timeout = clock.now() + rtime;
clock.schedule_message(timeout, actor_cast<strong_actor_ptr>(dest),
make_mailbox_element(nullptr, make_message_id(P),
no_stages,
std::forward<Ts>(xs)...));
}
}
template <class Rep = int, class Period = std::ratio<1>, class... Ts>
void delayed_anon_send(const group& dest,
std::chrono::duration<Rep, Period> rtime, Ts&&... xs) {
static_assert(sizeof...(Ts) > 0, "no message to send");
if (dest) {
auto& clock = dest->system().clock();
auto timeout = clock.now() + rtime;
clock.schedule_message(timeout, dest,
make_message(std::forward<Ts>(xs)...));
}
}
/// Anonymously sends `dest` an exit message. /// Anonymously sends `dest` an exit message.
template <class Dest> template <class Dest>
void anon_send_exit(const Dest& dest, exit_reason reason) { void anon_send_exit(const Dest& dest, exit_reason reason) {
......
...@@ -48,7 +48,11 @@ public: ...@@ -48,7 +48,11 @@ public:
return &view_; return &view_;
} }
inline explicit operator bool() const { const typed_actor_view<Sigs...>* operator->() const {
return &view_;
}
explicit operator bool() const {
return static_cast<bool>(view_.internal_ptr()); return static_cast<bool>(view_.internal_ptr());
} }
......
...@@ -77,6 +77,10 @@ public: ...@@ -77,6 +77,10 @@ public:
return self_->system(); return self_->system();
} }
actor_system& home_system() const {
return self_->home_system();
}
void quit(exit_reason reason = exit_reason::normal) { void quit(exit_reason reason = exit_reason::normal) {
self_->quit(reason); self_->quit(reason);
} }
......
...@@ -212,7 +212,7 @@ class delayed_testee : public composable_behavior<delayed_testee_actor> { ...@@ -212,7 +212,7 @@ class delayed_testee : public composable_behavior<delayed_testee_actor> {
public: public:
result<void> operator()(int x) override { result<void> operator()(int x) override {
CAF_CHECK_EQUAL(x, 42); CAF_CHECK_EQUAL(x, 42);
self->delayed_anon_send(self, std::chrono::milliseconds(10), true); delayed_anon_send(self, std::chrono::milliseconds(10), true);
return unit; return unit;
} }
......
...@@ -57,7 +57,7 @@ timer::behavior_type timer_impl(timer::stateful_pointer<timer_state> self) { ...@@ -57,7 +57,7 @@ timer::behavior_type timer_impl(timer::stateful_pointer<timer_state> self) {
timer::behavior_type timer_impl2(timer::pointer self) { timer::behavior_type timer_impl2(timer::pointer self) {
auto had_reset = std::make_shared<bool>(false); auto had_reset = std::make_shared<bool>(false);
self->delayed_anon_send(self, ms(100), reset_atom::value); delayed_anon_send(self, ms(100), reset_atom::value);
return { return {
[=](reset_atom) { [=](reset_atom) {
CAF_MESSAGE("timer reset"); CAF_MESSAGE("timer reset");
......
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