Commit 63e96260 authored by Dominik Charousset's avatar Dominik Charousset

Add scaffold for composable states to CAF headers

parent 662cff11
......@@ -13,6 +13,7 @@ file(GLOB_RECURSE LIBCAF_CORE_HDRS "caf/*.hpp")
set (LIBCAF_CORE_SRCS
src/abstract_actor.cpp
src/abstract_channel.cpp
src/abstract_composable_state.cpp
src/abstract_group.cpp
src/abstract_coordinator.cpp
src/actor.cpp
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_ABSTRACT_COMPOSABLE_STATE_HPP
#define CAF_ABSTRACT_COMPOSABLE_STATE_HPP
#include "caf/fwd.hpp"
namespace caf {
/// Marker type that allows CAF to spawn actors from composable states.
class abstract_composable_state {
public:
virtual ~abstract_composable_state();
virtual void init_behavior(behavior& x) = 0;
};
} // namespace caf
#endif // CAF_ABSTRACT_COMPOSABLE_STATE_HPP
......@@ -54,15 +54,17 @@
#include "caf/typed_actor.hpp"
#include "caf/actor_system.hpp"
#include "caf/deserializer.hpp"
#include "caf/function_view.hpp"
#include "caf/scoped_actor.hpp"
#include "caf/skip_message.hpp"
#include "caf/actor_ostream.hpp"
#include "caf/function_view.hpp"
#include "caf/handler_input.hpp"
#include "caf/index_mapping.hpp"
#include "caf/spawn_options.hpp"
#include "caf/abstract_actor.hpp"
#include "caf/abstract_group.hpp"
#include "caf/blocking_actor.hpp"
#include "caf/composed_state.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/execution_unit.hpp"
#include "caf/memory_managed.hpp"
......@@ -77,18 +79,22 @@
#include "caf/response_handle.hpp"
#include "caf/system_messages.hpp"
#include "caf/abstract_channel.hpp"
#include "caf/composable_state.hpp"
#include "caf/may_have_timeout.hpp"
#include "caf/message_priority.hpp"
#include "caf/typed_actor_view.hpp"
#include "caf/binary_serializer.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/primitive_variant.hpp"
#include "caf/timeout_definition.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/typed_actor_pointer.hpp"
#include "caf/scoped_execution_unit.hpp"
#include "caf/typed_continue_helper.hpp"
#include "caf/typed_response_promise.hpp"
#include "caf/typed_event_based_actor.hpp"
#include "caf/abstract_composable_state.hpp"
#include "caf/decorator/adapter.hpp"
#include "caf/decorator/sequencer.hpp"
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_COMPOSABLE_STATE_HPP
#define CAF_COMPOSABLE_STATE_HPP
#include "caf/behavior.hpp"
#include "caf/replies_to.hpp"
#include "caf/typed_actor.hpp"
#include "caf/typed_actor_pointer.hpp"
#include "caf/abstract_composable_state.hpp"
namespace caf {
/// Generates an interface class that provides `operator()`. The signature
/// of the apply operator is derived from the typed message passing interface
/// `MPI`.
template <class MPI>
class abstract_composable_state_mixin;
template <class... Xs, class... Ys>
class abstract_composable_state_mixin<typed_mpi<detail::type_list<Xs...>,
detail::type_list<Ys...>>> {
public:
virtual ~abstract_composable_state_mixin() noexcept {
// nop
}
virtual result<Ys...> operator()(handler_input_t<Xs>...) = 0;
};
// this class works around compiler issues on GCC
template <class... Ts>
struct abstract_composable_state_mixin_helper;
template <class T, class... Ts>
struct abstract_composable_state_mixin_helper<T, Ts...>
: public abstract_composable_state_mixin<T>,
public abstract_composable_state_mixin_helper<Ts...> {
using abstract_composable_state_mixin<T>::operator();
using abstract_composable_state_mixin_helper<Ts...>::operator();
};
template <class T>
struct abstract_composable_state_mixin_helper<T>
: public abstract_composable_state_mixin<T> {
using abstract_composable_state_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 = [=](handler_input_t<Xs>... xs) {
return (*thisptr)(xs...);
};
detail::type_list<Ts...> token;
init_behavior_impl(thisptr, token, storage, fs..., f);
}
/// Base type for composable actor states.
template <class TypedActor>
class composable_state;
template <class... Clauses>
class composable_state<typed_actor<Clauses...>>
: virtual public abstract_composable_state,
public abstract_composable_state_mixin_helper<Clauses...> {
public:
using signatures = detail::type_list<Clauses...>;
using handle_type =
typename detail::tl_apply<
signatures,
typed_actor
>::type;
using actor_base = typename handle_type::base;
using behavior_type = typename handle_type::behavior_type;
composable_state() : self(nullptr) {
// nop
}
template <class SelfPointer>
void init_selfptr(SelfPointer selfptr) {
self = selfptr;
}
void init_behavior(behavior& x) override {
signatures token;
init_behavior_impl(this, token, x);
}
protected:
typed_actor_pointer<Clauses...> self;
};
} // namespace caf
#endif // CAF_COMPOSABLE_STATE_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_COMPOSED_STATE_HPP
#define CAF_COMPOSED_STATE_HPP
#include "caf/composable_state.hpp"
#include "caf/typed_actor_pointer.hpp"
namespace caf {
template <class InterfaceIntersection, class... States>
class composed_state_base;
template <class T>
class composed_state_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_state_base<detail::type_list<>, A, B, Ts...>
: public A,
public composed_state_base<detail::type_list<>, B, Ts...> {
public:
using super = composed_state_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_state_base<detail::type_list<typed_mpi<detail::type_list<Xs...>,
detail::type_list<Ys...>>,
Ts...>,
States...>
: public composed_state_base<detail::type_list<Ts...>, States...> {
public:
using super = composed_state_base<detail::type_list<Ts...>, States...>;
using super::operator();
virtual result<Ys...> operator()(handler_input_t<Xs>...) override = 0;
};
template <class... Ts>
class composed_state
: public composed_state_base<typename detail::tl_intersect<
typename Ts::signatures...
>::type,
Ts...> {
private:
using super =
composed_state_base<typename detail::tl_intersect<
typename Ts::signatures...
>::type,
Ts...>;
public:
using signatures =
typename detail::tl_union<typename Ts::signatures...>::type;
using handle_type =
typename detail::tl_apply<
signatures,
typed_actor
>::type;
using behavior_type = typename handle_type::behavior_type;
using combined_type = composed_state;
using actor_base = typename handle_type::base;
using self_pointer =
typename detail::tl_apply<
signatures,
typed_actor_pointer
>::type;
composed_state() : self(nullptr) {
// nop
}
template <class SelfPtr>
void init_selfptr(SelfPtr ptr) {
self = ptr;
super::init_selfptr(ptr);
}
using super::operator();
void init_behavior(behavior& x) override {
signatures token;
init_behavior_impl(this, token, x);
}
protected:
self_pointer self;
};
} // namespace caf
#endif // CAF_COMPOSED_STATE_HPP
......@@ -151,7 +151,7 @@ public:
case rt_delegated:
(*this)();
return true;
case rt_skip_message:
default:
return false;
}
}
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_HANDLER_INPUT_HPP
#define CAF_HANDLER_INPUT_HPP
#include <type_traits>
#include "caf/atom.hpp"
namespace caf {
/// Defines `type` as `const T&` unless `T` is an arithmetic type. In the
/// latter case, `type` is an alias for `T`.
template <class T, bool IsArithmetic = std::is_arithmetic<T>::value>
struct handler_input {
using type = const T&;
};
template <class T>
struct handler_input<T, true> {
using type = T;
};
template <atom_value X>
struct handler_input<atom_constant<X>, false> {
using type = atom_constant<X>;
};
template <class T>
using handler_input_t = typename handler_input<T>::type;
} // namespace caf
#endif // CAF_HANDLER_INPUT_HPP
......@@ -88,19 +88,6 @@ struct make_response_promise_helper<response_promise> {
/// Base class for actors running on this node, either
/// living in an own thread or cooperatively scheduled.
class local_actor : public monitorable_actor, public resumable {
private:
template <class... Ts>
typename detail::make_response_promise_helper<Ts...>::type
make_response_promise_impl() {
auto& ptr = current_element_;
if (! ptr)
return {};
auto& mid = ptr->mid;
if (mid.is_answered())
return {};
return {this, *ptr};
}
public:
using mailbox_type = detail::single_reader_queue<mailbox_element,
detail::disposer>;
......@@ -372,26 +359,34 @@ public:
/// Returns all joined groups.
std::vector<group> joined_groups() const;
/// Creates a `response_promise` to respond to a request later on.
inline response_promise make_response_promise() {
return make_response_promise_impl<response_promise>();
}
/// Creates a `typed_response_promise` to respond to a request later on.
/// `make_response_promise<typed_response_promise<int, int>>()`
/// is equivalent to `make_response_promise<int, int>()`.
template <class... Ts>
auto make_response_promise()
-> decltype(this->make_response_promise_impl<Ts...>()) {
return this->make_response_promise_impl<Ts...>();
typename detail::make_response_promise_helper<Ts...>::type
make_response_promise() {
auto& ptr = current_element_;
if (! ptr)
return {};
auto& mid = ptr->mid;
if (mid.is_answered())
return {};
return {this, *ptr};
}
/// Creates a `response_promise` to respond to a request later on.
inline response_promise make_response_promise() {
return make_response_promise<response_promise>();
}
/// Creates a `typed_response_promise` and responds immediately.
/// Return type is deduced from arguments.
/// Return value is implicitly convertible to untyped response promise.
template <class... Ts, class R =
template <class... Ts,
class R =
typename detail::make_response_promise_helper<
typename std::decay<Ts>::type...>::type>
typename std::decay<Ts>::type...
>::type>
R response(Ts&&... xs) {
auto promise = make_response_promise<R>();
promise.deliver(std::forward<Ts>(xs)...);
......
......@@ -23,6 +23,7 @@
#include "caf/none.hpp"
#include "caf/error.hpp"
#include "caf/message.hpp"
#include "caf/delegated.hpp"
#include "caf/skip_message.hpp"
namespace caf {
......@@ -41,6 +42,11 @@ public:
// nop
}
template <class U, class... Us>
result(U x, Us... xs) : flag(rt_value) {
init(std::move(x), std::move(xs)...);
}
template <class E,
class = typename std::enable_if<
std::is_same<
......@@ -64,6 +70,50 @@ public:
// nop
}
result_runtime_type flag;
message value;
error err;
private:
void init(Ts... xs) {
value = make_message(std::move(xs)...);
}
};
template <>
struct result<void> {
public:
result() : flag(rt_value) {
// nop
}
result(const unit_t&) : flag(rt_value) {
// nop
}
template <class E,
class = typename std::enable_if<
std::is_same<
decltype(make_error(std::declval<const E&>())),
error
>::value
>::type>
result(E x) : flag(rt_error), err(make_error(x)) {
// nop
}
result(error x) : flag(rt_error), err(std::move(x)) {
// nop
}
result(skip_message_t) : flag(rt_skip_message) {
// nop
}
result(delegated<void>) : flag(rt_delegated) {
// nop
}
result_runtime_type flag;
message value;
error err;
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_TYPED_ACTOR_POINTER_HPP
#define CAF_TYPED_ACTOR_POINTER_HPP
#include "caf/typed_actor_view.hpp"
#include "caf/detail/type_list.hpp"
namespace caf {
template <class... Sigs>
class typed_actor_pointer {
public:
template <class Supertype>
typed_actor_pointer(Supertype* selfptr) : view_(selfptr) {
using namespace caf::detail;
static_assert(tlf_is_subset(type_list<Sigs...>{},
typename Supertype::signatures{}),
"cannot create a pointer view to an unrelated actor type");
}
typed_actor_pointer(const nullptr_t&) : view_(nullptr) {
// nop
}
typed_actor_view<Sigs...>* operator->() {
return &view_;
}
private:
typed_actor_view<Sigs...> view_;
};
} // namespace caf
#endif // CAF_TYPED_ACTOR_POINTER_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_TYPED_ACTOR_VIEW_HPP
#define CAF_TYPED_ACTOR_VIEW_HPP
#include "caf/local_actor.hpp"
namespace caf {
template <class... Sigs>
class typed_actor_view {
public:
typed_actor_view(local_actor* selfptr) : self_(selfptr) {
// nop
}
/****************************************************************************
* spawn actors *
****************************************************************************/
template <class T, spawn_options Os = no_spawn_options, class... Ts>
typename infer_handle_from_class<T>::type
spawn(Ts&&... xs) {
return self_->spawn<T, Os>(std::forward<Ts>(xs)...);
}
template <spawn_options Os = no_spawn_options, class F, class... Ts>
typename infer_handle_from_fun<F>::type
spawn(F fun, Ts&&... xs) {
return self_->spawn<Os>(std::move(fun), std::forward<Ts>(xs)...);
}
/****************************************************************************
* send asynchronous messages *
****************************************************************************/
template <class... Ts>
void send(message_priority mp, const actor& dest, Ts&&... xs) {
self_->send(mp, dest, std::forward<Ts>(xs)...);
}
template <class... Ts>
void send(const actor& dest, Ts&&... xs) {
self_->send(dest, std::forward<Ts>(xs)...);
}
template <class... DestSigs, class... Ts>
void send(message_priority mp, const typed_actor<DestSigs...>& dest,
Ts&&... xs) {
detail::sender_signature_checker<
detail::type_list<Sigs...>,
detail::type_list<DestSigs...>,
detail::type_list<
typename detail::implicit_conversions<
typename std::decay<Ts>::type
>::type...
>
>::check();
self_->send(mp, dest, std::forward<Ts>(xs)...);
}
template <class... DestSigs, class... Ts>
void send(const typed_actor<DestSigs...>& dest, Ts&&... xs) {
detail::sender_signature_checker<
detail::type_list<Sigs...>,
detail::type_list<DestSigs...>,
detail::type_list<
typename detail::implicit_conversions<
typename std::decay<Ts>::type
>::type...
>
>::check();
self_->send(dest, std::forward<Ts>(xs)...);
}
template <class... Ts>
void delayed_send(message_priority mp, const actor& dest,
const duration& rtime, Ts&&... xs) {
self_->delayed_send(mp, dest, rtime, std::forward<Ts>(xs)...);
}
template <class... Ts>
void delayed_send(const actor& dest, const duration& rtime, Ts&&... xs) {
self_->delayed_send(dest, rtime, std::forward<Ts>(xs)...);
}
template <class... DestSigs, class... Ts>
void delayed_send(message_priority mp, const typed_actor<DestSigs...>& dest,
const duration& rtime, Ts&&... xs) {
detail::sender_signature_checker<
detail::type_list<Sigs...>,
detail::type_list<DestSigs...>,
detail::type_list<
typename detail::implicit_conversions<
typename std::decay<Ts>::type
>::type...
>
>::check();
self_->delayed_send(mp, dest, rtime, std::forward<Ts>(xs)...);
}
template <class... DestSigs, class... Ts>
void delayed_send(const typed_actor<DestSigs...>& dest,
const duration& rtime, Ts&&... xs) {
detail::sender_signature_checker<
detail::type_list<Sigs...>,
detail::type_list<DestSigs...>,
detail::type_list<
typename detail::implicit_conversions<
typename std::decay<Ts>::type
>::type...
>
>::check();
self_->delayed_send(dest, rtime, std::forward<Ts>(xs)...);
}
/****************************************************************************
* miscellaneous actor operations *
****************************************************************************/
actor_system& system() const {
return self_->system();
}
void quit(exit_reason reason = exit_reason::normal) {
self_->quit(reason);
}
template <class... Ts>
typename detail::make_response_promise_helper<Ts...>::type
make_response_promise() {
return self_->make_response_promise<Ts...>();
}
template <class T>
void monitor(const T& x) {
self_->monitor(x);
}
template <class T>
void demonitor(const T& x) {
self_->demonitor(x);
}
response_promise make_response_promise() {
return self_->make_response_promise();
}
template <class... Ts,
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)...);
}
private:
local_actor* self_;
};
} // namespace caf
#endif // CAF_TYPED_ACTOR_VIEW_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/abstract_composable_state.hpp"
namespace caf {
abstract_composable_state::~abstract_composable_state() {
// nop
}
} // namespace caf
......@@ -46,7 +46,7 @@ first_stage::behavior_type typed_first_stage() {
return [](int i) {
return std::make_tuple(i * 2.0, i * 4.0);
};
};
}
second_stage::behavior_type typed_second_stage() {
return [](double x, double y) {
......
This diff is collapsed.
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