Commit f46e717b authored by Dominik Charousset's avatar Dominik Charousset

Allow using typed_actor_pointer as self pointer

parent d19ca0d6
......@@ -19,6 +19,7 @@
#pragma once
#include "caf/detail/type_list.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/typed_actor_view.hpp"
namespace caf {
......@@ -33,22 +34,54 @@ public:
// nop
}
template <class Supertype>
explicit typed_actor_pointer(Supertype* selfptr) : view_(selfptr) {
using namespace caf::detail;
static_assert(
tl_subset_of<type_list<Sigs...>, typename Supertype::signatures>::value,
"cannot create a pointer view to an unrelated actor type");
template <class Supertype,
class = detail::enable_if_t< //
detail::tl_subset_of<detail::type_list<Sigs...>,
typename Supertype::signatures>::value>>
typed_actor_pointer(Supertype* selfptr) : view_(selfptr) {
// 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
}
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;
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->() {
return &view_;
}
......@@ -75,16 +108,6 @@ public:
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:
typed_actor_view<Sigs...> view_;
};
......
......@@ -31,30 +31,24 @@ namespace caf {
/// Decorates a pointer to a @ref scheduled_actor with a statically typed actor
/// interface.
template <class... Sigs>
class typed_actor_view : public extend<typed_actor_view_base,
typed_actor_view<Sigs...>>::template
with<mixin::sender, mixin::requester> {
class typed_actor_view
: public extend<typed_actor_view_base, typed_actor_view<Sigs...>>::
template with<mixin::sender, mixin::requester> {
public:
/// Stores the template parameter pack.
using signatures = detail::type_list<Sigs...>;
using pointer = scheduled_actor*;
typed_actor_view(scheduled_actor* ptr) : self_(ptr) {
explicit typed_actor_view(scheduled_actor* ptr) : self_(ptr) {
// nop
}
typed_actor_view& operator=(scheduled_actor* ptr) {
self_ = ptr;
return *this;
}
// -- spawn functions --------------------------------------------------------
/// @copydoc local_actor::spawn
template <class T, spawn_options Os = no_spawn_options, class... Ts>
typename infer_handle_from_class<T>::type
spawn(Ts&&... xs) {
typename infer_handle_from_class<T>::type spawn(Ts&&... xs) {
return self_->spawn<T, Os>(std::forward<Ts>(xs)...);
}
......@@ -66,8 +60,7 @@ public:
/// @copydoc local_actor::spawn
template <spawn_options Os = no_spawn_options, class F, class... Ts>
typename infer_handle_from_fun<F>::type
spawn(F fun, Ts&&... xs) {
typename infer_handle_from_fun<F>::type spawn(F fun, Ts&&... xs) {
return self_->spawn<Os>(std::move(fun), std::forward<Ts>(xs)...);
}
......@@ -208,10 +201,8 @@ public:
}
template <class... Ts,
class R =
typename detail::make_response_promise_helper<
typename std::decay<Ts>::type...
>::type>
class R = typename detail::make_response_promise_helper<
typename std::decay<Ts>::type...>::type>
R response(Ts&&... xs) {
return self_->response(std::forward<Ts>(xs)...);
}
......@@ -230,6 +221,11 @@ public:
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.
/// @pre `current_mailbox_element() != nullptr`
strong_actor_ptr& current_sender() {
......@@ -244,7 +240,8 @@ public:
/// @private
actor_control_block* ctrl() const noexcept {
CAF_ASSERT(self_ != nullptr);
return actor_control_block::from(self_);;
return actor_control_block::from(self_);
;
}
/// @private
......@@ -252,6 +249,11 @@ public:
return self_;
}
/// @private
void reset(scheduled_actor* ptr) {
self_ = ptr;
}
operator scheduled_actor*() const noexcept {
return self_;
}
......
......@@ -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));
}
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()
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