Commit f99c9526 authored by Dominik Charousset's avatar Dominik Charousset

Simplify implementation of composable behaviors

parent 22b1bc45
......@@ -31,7 +31,7 @@ class abstract_composable_behavior {
public:
virtual ~abstract_composable_behavior();
virtual void init_behavior(behavior& x) = 0;
virtual unit_t init_behavior(message_handler& x) = 0;
};
} // namespace caf
......
......@@ -33,54 +33,30 @@ namespace caf {
/// of the apply operator is derived from the typed message passing interface
/// `MPI`.
template <class MPI>
class abstract_composable_behavior_mixin;
class composable_behavior_base;
template <class... Xs, class... Ys>
class abstract_composable_behavior_mixin<typed_mpi<detail::type_list<Xs...>,
detail::type_list<Ys...>>> {
class composable_behavior_base<typed_mpi<detail::type_list<Xs...>,
detail::type_list<Ys...>>> {
public:
virtual ~abstract_composable_behavior_mixin() noexcept {
virtual ~composable_behavior_base() noexcept {
// nop
}
virtual result<Ys...> operator()(param_t<Xs>...) = 0;
};
// this class works around compiler issues on GCC
template <class... Ts>
struct abstract_composable_behavior_mixin_helper;
template <class T, class... Ts>
struct abstract_composable_behavior_mixin_helper<T, Ts...>
: public abstract_composable_behavior_mixin<T>,
public abstract_composable_behavior_mixin_helper<Ts...> {
using abstract_composable_behavior_mixin<T>::operator();
using abstract_composable_behavior_mixin_helper<Ts...>::operator();
};
template <class T>
struct abstract_composable_behavior_mixin_helper<T>
: public abstract_composable_behavior_mixin<T> {
using abstract_composable_behavior_mixin<T>::operator();
};
template <class T, class... Fs>
void init_behavior_impl(T*, detail::type_list<>, behavior& storage, Fs... fs) {
storage.assign(std::move(fs)...);
}
template <class T, class... Xs, class... Ys, class... Ts, class... Fs>
void init_behavior_impl(T* thisptr,
detail::type_list<typed_mpi<detail::type_list<Xs...>,
detail::type_list<Ys...>>,
Ts...>,
behavior& storage, Fs... fs) {
auto f = [=](param_t<Xs>... xs) {
return (*thisptr)(std::move(xs)...);
// C++14 and later
# if __cplusplus > 201103L
auto make_callback() {
return [=](param_t<Xs>... xs) { return (*this)(std::move(xs)...); };
};
detail::type_list<Ts...> token;
init_behavior_impl(thisptr, token, storage, fs..., f);
}
# else
// C++11
std::function<result<Ys...> (param_t<Xs>...)> make_callback() {
return [=](param_t<Xs>... xs) { return (*this)(std::move(xs)...); };
};
# endif
};
/// Base type for composable actor states.
template <class TypedActor>
......@@ -89,7 +65,7 @@ class composable_behavior;
template <class... Clauses>
class composable_behavior<typed_actor<Clauses...>>
: virtual public abstract_composable_behavior,
public abstract_composable_behavior_mixin_helper<Clauses...> {
public composable_behavior_base<Clauses>... {
public:
using signatures = detail::type_list<Clauses...>;
......@@ -108,13 +84,17 @@ public:
}
template <class SelfPointer>
void init_selfptr(SelfPointer selfptr) {
unit_t init_selfptr(SelfPointer selfptr) {
self = selfptr;
return unit;
}
void init_behavior(behavior& x) override {
signatures token;
init_behavior_impl(this, token, x);
unit_t init_behavior(message_handler& x) override {
if (x)
x = x.or_else(composable_behavior_base<Clauses>::make_callback()...);
else
x.assign(composable_behavior_base<Clauses>::make_callback()...);
return unit;
}
typed_actor_pointer<Clauses...> self;
......
......@@ -42,7 +42,7 @@ class composable_behavior_based_actor : public stateful_actor<State, Base> {
behavior_type make_behavior() override {
this->state.init_selfptr(this);
behavior tmp;
message_handler tmp;
this->state.init_behavior(tmp);
return behavior_type{typename behavior_type::unsafe_init{}, std::move(tmp)};
}
......
......@@ -26,67 +26,8 @@
namespace caf {
template <class InterfaceIntersection, class... States>
class composed_behavior_base;
template <class T>
class composed_behavior_base<detail::type_list<>, T> : public T {
public:
using T::operator();
// make this pure again, since the compiler can otherwise
// runs into a "multiple final overriders" error
virtual void init_behavior(behavior& x) override = 0;
};
template <class A, class B, class... Ts>
class composed_behavior_base<detail::type_list<>, A, B, Ts...>
: public A,
public composed_behavior_base<detail::type_list<>, B, Ts...> {
public:
using super = composed_behavior_base<detail::type_list<>, B, Ts...>;
using A::operator();
using super::operator();
template <class SelfPtr>
void init_selfptr(SelfPtr ptr) {
A::init_selfptr(ptr);
super::init_selfptr(ptr);
}
// make this pure again, since the compiler can otherwise
// runs into a "multiple final overriders" error
virtual void init_behavior(behavior& x) override = 0;
};
template <class... Xs, class... Ys, class... Ts, class... States>
class composed_behavior_base<detail::type_list<typed_mpi<detail::type_list<Xs...>,
detail::type_list<Ys...>>,
Ts...>,
States...>
: public composed_behavior_base<detail::type_list<Ts...>, States...> {
public:
using super = composed_behavior_base<detail::type_list<Ts...>, States...>;
using super::operator();
virtual result<Ys...> operator()(param_t<Xs>...) override = 0;
};
template <class... Ts>
class composed_behavior
: public composed_behavior_base<typename detail::tl_intersect<
typename Ts::signatures...
>::type,
Ts...> {
private:
using super =
composed_behavior_base<typename detail::tl_intersect<
typename Ts::signatures...
>::type,
Ts...>;
class composed_behavior : public Ts... {
public:
using signatures =
typename detail::tl_union<typename Ts::signatures...>::type;
......@@ -99,8 +40,6 @@ public:
using behavior_type = typename handle_type::behavior_type;
using combined_type = composed_behavior;
using actor_base = typename handle_type::base;
using self_pointer =
......@@ -113,17 +52,13 @@ public:
// nop
}
template <class SelfPtr>
void init_selfptr(SelfPtr ptr) {
self = ptr;
super::init_selfptr(ptr);
template <class SelfPointer>
unit_t init_selfptr(SelfPointer x) {
return unit(Ts::init_selfptr(x)...);
}
using super::operator();
void init_behavior(behavior& x) override {
signatures token;
init_behavior_impl(this, token, x);
unit_t init_behavior(message_handler& x) override {
return unit(Ts::init_behavior(x)...);
}
protected:
......
......@@ -21,6 +21,7 @@
#define CAF_TYPED_BEHAVIOR_HPP
#include "caf/behavior.hpp"
#include "caf/message_handler.hpp"
#include "caf/system_messages.hpp"
#include "caf/typed_continue_helper.hpp"
......@@ -169,7 +170,11 @@ public:
struct unsafe_init { };
typed_behavior(unsafe_init, behavior bhvr) : bhvr_(std::move(bhvr)) {
typed_behavior(unsafe_init, behavior x) : bhvr_(std::move(x)) {
// nop
}
typed_behavior(unsafe_init, message_handler x) : bhvr_(std::move(x)) {
// nop
}
......
......@@ -30,22 +30,27 @@ namespace caf {
/// to enable higher-order abstraction without cluttering code with
/// exceptions for `void` (which can't be stored, for example).
struct unit_t : detail::comparable<unit_t> {
constexpr unit_t() {
constexpr unit_t() noexcept {
// nop
}
constexpr unit_t(const unit_t&) {
constexpr unit_t(const unit_t&) noexcept {
// nop
}
template <class T>
explicit constexpr unit_t(T&&) {
explicit constexpr unit_t(T&&) noexcept {
// nop
}
static constexpr int compare(const unit_t&) {
static constexpr int compare(const unit_t&) noexcept {
return 0;
}
template <class... Ts>
constexpr unit_t operator()(Ts&&...) const noexcept {
return {};
}
};
static constexpr unit_t unit = unit_t{};
......
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