Commit f46e717b authored by Dominik Charousset's avatar Dominik Charousset

Allow using typed_actor_pointer as self pointer

parent d19ca0d6
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#pragma once #pragma once
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/typed_actor_view.hpp" #include "caf/typed_actor_view.hpp"
namespace caf { namespace caf {
...@@ -33,22 +34,54 @@ public: ...@@ -33,22 +34,54 @@ public:
// nop // nop
} }
template <class Supertype> template <class Supertype,
explicit typed_actor_pointer(Supertype* selfptr) : view_(selfptr) { class = detail::enable_if_t< //
using namespace caf::detail; detail::tl_subset_of<detail::type_list<Sigs...>,
static_assert( typename Supertype::signatures>::value>>
tl_subset_of<type_list<Sigs...>, typename Supertype::signatures>::value, typed_actor_pointer(Supertype* selfptr) : view_(selfptr) {
"cannot create a pointer view to an unrelated actor type"); // nop
} }
explicit typed_actor_pointer(std::nullptr_t) : view_(nullptr) { template <class... OtherSigs,
class = detail::enable_if_t< //
detail::tl_subset_of<detail::type_list<Sigs...>,
detail::type_list<OtherSigs...>>::value>>
typed_actor_pointer(typed_actor_pointer<OtherSigs...> other)
: view_(other.internal_ptr()) {
// nop // nop
} }
typed_actor_pointer(const typed_actor_pointer&) = default; typed_actor_pointer(const typed_actor_pointer&) = default;
explicit typed_actor_pointer(std::nullptr_t) : view_(nullptr) {
// nop
}
typed_actor_pointer& operator=(const typed_actor_pointer&) = default; typed_actor_pointer& operator=(const typed_actor_pointer&) = default;
template <class Supertype>
typed_actor_pointer& operator=(Supertype* ptr) {
using namespace detail;
static_assert(
tl_subset_of<type_list<Sigs...>, typename Supertype::signatures>::value,
"cannot assign pointer of unrelated actor type");
view_.reset(ptr);
return *this;
}
template <class... OtherSigs,
class = detail::enable_if_t< //
detail::tl_subset_of<detail::type_list<Sigs...>,
detail::type_list<OtherSigs...>>::value>>
typed_actor_pointer& operator=(typed_actor_pointer<OtherSigs...> other) {
using namespace detail;
static_assert(
tl_subset_of<type_list<Sigs...>, type_list<OtherSigs...>>::value,
"cannot assign pointer of unrelated actor type");
view_.reset(other.internal_ptr());
return *this;
}
typed_actor_view<Sigs...>* operator->() { typed_actor_view<Sigs...>* operator->() {
return &view_; return &view_;
} }
...@@ -75,16 +108,6 @@ public: ...@@ -75,16 +108,6 @@ public:
return view_.internal_ptr(); return view_.internal_ptr();
} }
template <class Supertype>
typed_actor_pointer& operator=(Supertype* ptr) {
using namespace caf::detail;
static_assert(
tl_subset_of<type_list<Sigs...>, typename Supertype::signatures>::value,
"cannot assign pointer of unrelated actor type");
view_ = ptr;
return *this;
}
private: private:
typed_actor_view<Sigs...> view_; typed_actor_view<Sigs...> view_;
}; };
......
...@@ -31,30 +31,24 @@ namespace caf { ...@@ -31,30 +31,24 @@ namespace caf {
/// Decorates a pointer to a @ref scheduled_actor with a statically typed actor /// Decorates a pointer to a @ref scheduled_actor with a statically typed actor
/// interface. /// interface.
template <class... Sigs> template <class... Sigs>
class typed_actor_view : public extend<typed_actor_view_base, class typed_actor_view
typed_actor_view<Sigs...>>::template : public extend<typed_actor_view_base, typed_actor_view<Sigs...>>::
with<mixin::sender, mixin::requester> { template with<mixin::sender, mixin::requester> {
public: public:
/// Stores the template parameter pack. /// Stores the template parameter pack.
using signatures = detail::type_list<Sigs...>; using signatures = detail::type_list<Sigs...>;
using pointer = scheduled_actor*; using pointer = scheduled_actor*;
typed_actor_view(scheduled_actor* ptr) : self_(ptr) { explicit typed_actor_view(scheduled_actor* ptr) : self_(ptr) {
// nop // nop
} }
typed_actor_view& operator=(scheduled_actor* ptr) {
self_ = ptr;
return *this;
}
// -- spawn functions -------------------------------------------------------- // -- spawn functions --------------------------------------------------------
/// @copydoc local_actor::spawn /// @copydoc local_actor::spawn
template <class T, spawn_options Os = no_spawn_options, class... Ts> template <class T, spawn_options Os = no_spawn_options, class... Ts>
typename infer_handle_from_class<T>::type typename infer_handle_from_class<T>::type spawn(Ts&&... xs) {
spawn(Ts&&... xs) {
return self_->spawn<T, Os>(std::forward<Ts>(xs)...); return self_->spawn<T, Os>(std::forward<Ts>(xs)...);
} }
...@@ -66,8 +60,7 @@ public: ...@@ -66,8 +60,7 @@ public:
/// @copydoc local_actor::spawn /// @copydoc local_actor::spawn
template <spawn_options Os = no_spawn_options, class F, class... Ts> template <spawn_options Os = no_spawn_options, class F, class... Ts>
typename infer_handle_from_fun<F>::type typename infer_handle_from_fun<F>::type spawn(F fun, Ts&&... xs) {
spawn(F fun, Ts&&... xs) {
return self_->spawn<Os>(std::move(fun), std::forward<Ts>(xs)...); return self_->spawn<Os>(std::move(fun), std::forward<Ts>(xs)...);
} }
...@@ -208,10 +201,8 @@ public: ...@@ -208,10 +201,8 @@ public:
} }
template <class... Ts, template <class... Ts,
class R = class R = typename detail::make_response_promise_helper<
typename detail::make_response_promise_helper< typename std::decay<Ts>::type...>::type>
typename std::decay<Ts>::type...
>::type>
R response(Ts&&... xs) { R response(Ts&&... xs) {
return self_->response(std::forward<Ts>(xs)...); return self_->response(std::forward<Ts>(xs)...);
} }
...@@ -230,6 +221,11 @@ public: ...@@ -230,6 +221,11 @@ public:
std::move(bhvr)); std::move(bhvr));
} }
template <class Handle, class... Ts>
auto delegate(const Handle& dest, Ts&&... xs) {
return self_->delegate(dest, std::forward<Ts>(xs)...);
}
/// Returns a pointer to the sender of the current message. /// Returns a pointer to the sender of the current message.
/// @pre `current_mailbox_element() != nullptr` /// @pre `current_mailbox_element() != nullptr`
strong_actor_ptr& current_sender() { strong_actor_ptr& current_sender() {
...@@ -244,7 +240,8 @@ public: ...@@ -244,7 +240,8 @@ public:
/// @private /// @private
actor_control_block* ctrl() const noexcept { actor_control_block* ctrl() const noexcept {
CAF_ASSERT(self_ != nullptr); CAF_ASSERT(self_ != nullptr);
return actor_control_block::from(self_);; return actor_control_block::from(self_);
;
} }
/// @private /// @private
...@@ -252,6 +249,11 @@ public: ...@@ -252,6 +249,11 @@ public:
return self_; return self_;
} }
/// @private
void reset(scheduled_actor* ptr) {
self_ = ptr;
}
operator scheduled_actor*() const noexcept { operator scheduled_actor*() const noexcept {
return self_; return self_;
} }
......
...@@ -189,4 +189,28 @@ CAF_TEST(states optionally take the self pointer as first argument) { ...@@ -189,4 +189,28 @@ CAF_TEST(states optionally take the self pointer as first argument) {
expect((std::string), from(testee).to(self).with("testee"s)); expect((std::string), from(testee).to(self).with("testee"s));
} }
CAF_TEST(typed actors can use typed_actor_pointer as self pointer) {
struct state_type {
using self_pointer = typed_adder_actor::pointer_view;
self_pointer self;
const char* name = "testee";
int value;
state_type(self_pointer self, int x) : self(self), value(x) {
// nop
}
auto make_behavior() {
return make_typed_behavior([=](add_atom, int x) { value += x; },
[=](get_atom) { return value; });
}
};
using actor_type = typed_adder_actor::stateful_base<state_type>;
auto testee = sys.spawn<actor_type>(10);
auto& state = deref<actor_type>(testee).state;
CAF_CHECK(state.self == &deref<actor_type>(testee));
CAF_CHECK_EQUAL(state.value, 10);
inject((add_atom, int), from(self).to(testee).with(add_atom_v, 1));
inject((get_atom), from(self).to(testee).with(get_atom_v));
expect((int), from(testee).to(self).with(11));
}
CAF_TEST_FIXTURE_SCOPE_END() 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