Commit 578635de authored by Dominik Charousset's avatar Dominik Charousset

re-implemented typed spawn

parent c316456d
...@@ -13,6 +13,7 @@ cppa/anything.hpp ...@@ -13,6 +13,7 @@ cppa/anything.hpp
cppa/atom.hpp cppa/atom.hpp
cppa/attachable.hpp cppa/attachable.hpp
cppa/behavior.hpp cppa/behavior.hpp
cppa/behavior_policy.hpp
cppa/behavior_stack_based.hpp cppa/behavior_stack_based.hpp
cppa/binary_deserializer.hpp cppa/binary_deserializer.hpp
cppa/binary_serializer.hpp cppa/binary_serializer.hpp
...@@ -160,6 +161,7 @@ cppa/sb_actor.hpp ...@@ -160,6 +161,7 @@ cppa/sb_actor.hpp
cppa/scheduler.hpp cppa/scheduler.hpp
cppa/scoped_actor.hpp cppa/scoped_actor.hpp
cppa/serializer.hpp cppa/serializer.hpp
cppa/single_timeout.hpp
cppa/singletons.hpp cppa/singletons.hpp
cppa/spawn.hpp cppa/spawn.hpp
cppa/spawn_options.hpp cppa/spawn_options.hpp
...@@ -173,6 +175,8 @@ cppa/typed_actor.hpp ...@@ -173,6 +175,8 @@ cppa/typed_actor.hpp
cppa/typed_actor_base.hpp cppa/typed_actor_base.hpp
cppa/typed_actor_ptr.hpp cppa/typed_actor_ptr.hpp
cppa/typed_behavior.hpp cppa/typed_behavior.hpp
cppa/typed_behavior_stack_based.hpp
cppa/typed_event_based_actor.hpp
cppa/uniform_type_info.hpp cppa/uniform_type_info.hpp
cppa/unit.hpp cppa/unit.hpp
cppa/util/abstract_uniform_type_info.hpp cppa/util/abstract_uniform_type_info.hpp
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_BEHAVIOR_POLICY_HPP
#define CPPA_BEHAVIOR_POLICY_HPP
namespace cppa {
template<bool DiscardBehavior>
struct behavior_policy { static constexpr bool discard_old = DiscardBehavior; };
template<typename T>
struct is_behavior_policy : std::false_type { };
template<bool DiscardBehavior>
struct is_behavior_policy<behavior_policy<DiscardBehavior>> : std::true_type { };
typedef behavior_policy<false> keep_behavior_t;
typedef behavior_policy<true > discard_behavior_t;
/**
* @brief Policy tag that causes {@link event_based_actor::become} to
* discard the current behavior.
* @relates local_actor
*/
constexpr discard_behavior_t discard_behavior = discard_behavior_t{};
/**
* @brief Policy tag that causes {@link event_based_actor::become} to
* keep the current behavior available.
* @relates local_actor
*/
constexpr keep_behavior_t keep_behavior = keep_behavior_t{};
} // namespace cppa
#endif // CPPA_BEHAVIOR_POLICY_HPP
...@@ -32,61 +32,28 @@ ...@@ -32,61 +32,28 @@
#define CPPA_BEHAVIOR_STACK_BASED_HPP #define CPPA_BEHAVIOR_STACK_BASED_HPP
#include "cppa/message_id.hpp" #include "cppa/message_id.hpp"
#include "cppa/system_messages.hpp" #include "cppa/single_timeout.hpp"
#include "cppa/behavior_policy.hpp"
#include "cppa/detail/behavior_stack.hpp" #include "cppa/detail/behavior_stack.hpp"
namespace cppa { namespace cppa {
#ifdef CPPA_DOCUMENTATION
/**
* @brief Policy tag that causes {@link event_based_actor::become} to
* discard the current behavior.
* @relates local_actor
*/
constexpr auto discard_behavior;
/** /**
* @brief Policy tag that causes {@link event_based_actor::become} to * @brief Mixin for actors using a stack-based message processing.
* keep the current behavior available. * @note This mixin implicitly includes {@link single_timeout}.
* @relates local_actor
*/ */
constexpr auto keep_behavior;
#else
template<bool DiscardBehavior>
struct behavior_policy { static constexpr bool discard_old = DiscardBehavior; };
template<typename T>
struct is_behavior_policy : std::false_type { };
template<bool DiscardBehavior>
struct is_behavior_policy<behavior_policy<DiscardBehavior>> : std::true_type { };
typedef behavior_policy<false> keep_behavior_t;
typedef behavior_policy<true > discard_behavior_t;
constexpr discard_behavior_t discard_behavior = discard_behavior_t{};
constexpr keep_behavior_t keep_behavior = keep_behavior_t{};
#endif
template<class Base, class Subtype> template<class Base, class Subtype>
class behavior_stack_based : public Base { class behavior_stack_based : public single_timeout<Base, Subtype> {
typedef Base super; typedef single_timeout<Base, Subtype> super;
public: public:
typedef behavior_stack_based combined_type; typedef behavior_stack_based combined_type;
template <typename... Ts> template <typename... Ts>
behavior_stack_based(Ts&&... args) behavior_stack_based(Ts&&... args) : super(std::forward<Ts>(args)...) { }
: super(std::forward<Ts>(args)...), m_has_timeout(false)
, m_timeout_id(0) { }
inline void unbecome() { inline void unbecome() {
m_bhvr_stack.pop_async_back(); m_bhvr_stack.pop_async_back();
...@@ -158,51 +125,11 @@ class behavior_stack_based : public Base { ...@@ -158,51 +125,11 @@ class behavior_stack_based : public Base {
this->m_bhvr_stack.push_back(std::move(bhvr)); this->m_bhvr_stack.push_back(std::move(bhvr));
} }
// timeout handling
void request_timeout(const util::duration& d) {
if (d.valid()) {
m_has_timeout = true;
auto tid = ++m_timeout_id;
auto msg = make_any_tuple(timeout_msg{tid});
if (d.is_zero()) {
// immediately enqueue timeout message if duration == 0s
this->enqueue({this->address(), this}, std::move(msg));
//auto e = this->new_mailbox_element(this, std::move(msg));
//this->m_mailbox.enqueue(e);
}
else this->delayed_send_tuple(this, d, std::move(msg));
}
else m_has_timeout = false;
}
inline bool waits_for_timeout(std::uint32_t timeout_id) const {
return m_has_timeout && m_timeout_id == timeout_id;
}
inline bool is_active_timeout(std::uint32_t tid) const {
return waits_for_timeout(tid);
}
inline void reset_timeout() {
m_has_timeout = false;
}
inline void handle_timeout(behavior& bhvr, std::uint32_t timeout_id) {
if (timeout_id == m_timeout_id) {
m_has_timeout = false;
bhvr.handle_timeout();
}
}
protected: protected:
// allows actors to keep previous behaviors and enables unbecome() // allows actors to keep previous behaviors and enables unbecome()
detail::behavior_stack m_bhvr_stack; detail::behavior_stack m_bhvr_stack;
bool m_has_timeout;
std::uint32_t m_timeout_id;
}; };
} // namespace cppa } // namespace cppa
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_SINGLE_TIMEOUT_HPP
#define CPPA_SINGLE_TIMEOUT_HPP
#include "cppa/any_tuple.hpp"
#include "cppa/system_messages.hpp"
#include "cppa/util/duration.hpp"
namespace cppa {
/**
* @brief Mixin for actors using a non-nestable message processing.
*/
template<class Base, class Subtype>
class single_timeout : public Base {
typedef Base super;
public:
typedef single_timeout combined_type;
template <typename... Ts>
single_timeout(Ts&&... args)
: super(std::forward<Ts>(args)...), m_has_timeout(false)
, m_timeout_id(0) { }
void request_timeout(const util::duration& d) {
if (d.valid()) {
m_has_timeout = true;
auto tid = ++m_timeout_id;
auto msg = make_any_tuple(timeout_msg{tid});
if (d.is_zero()) {
// immediately enqueue timeout message if duration == 0s
this->enqueue({this->address(), this}, std::move(msg));
//auto e = this->new_mailbox_element(this, std::move(msg));
//this->m_mailbox.enqueue(e);
}
else this->delayed_send_tuple(this, d, std::move(msg));
}
else m_has_timeout = false;
}
inline bool waits_for_timeout(std::uint32_t timeout_id) const {
return m_has_timeout && m_timeout_id == timeout_id;
}
inline bool is_active_timeout(std::uint32_t tid) const {
return waits_for_timeout(tid);
}
inline void reset_timeout() {
m_has_timeout = false;
}
inline void handle_timeout(behavior& bhvr, std::uint32_t timeout_id) {
if (timeout_id == m_timeout_id) {
m_has_timeout = false;
bhvr.handle_timeout();
}
}
protected:
bool m_has_timeout;
std::uint32_t m_timeout_id;
};
} // namespace cppa
#endif // CPPA_SINGLE_TIMEOUT_HPP
...@@ -39,10 +39,13 @@ ...@@ -39,10 +39,13 @@
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
#include "cppa/typed_actor.hpp" #include "cppa/typed_actor.hpp"
#include "cppa/spawn_options.hpp" #include "cppa/spawn_options.hpp"
#include "cppa/typed_event_based_actor.hpp"
#include "cppa/util/fiber.hpp" #include "cppa/util/fiber.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/detail/proper_actor.hpp" #include "cppa/detail/proper_actor.hpp"
#include "cppa/detail/typed_actor_util.hpp"
#include "cppa/detail/functor_based_actor.hpp" #include "cppa/detail/functor_based_actor.hpp"
#include "cppa/detail/implicit_conversions.hpp" #include "cppa/detail/implicit_conversions.hpp"
#include "cppa/detail/functor_based_blocking_actor.hpp" #include "cppa/detail/functor_based_blocking_actor.hpp"
...@@ -52,12 +55,10 @@ namespace cppa { ...@@ -52,12 +55,10 @@ namespace cppa {
namespace detail { namespace detail {
template<class Impl, spawn_options Opts, typename BeforeLaunch, typename... Ts> template<class Impl, spawn_options Opts, typename BeforeLaunch, typename... Ts>
actor spawn_impl(BeforeLaunch before_launch_fun, Ts&&... args) { intrusive_ptr<Impl> spawn_impl(BeforeLaunch before_launch_fun, Ts&&... args) {
static_assert(std::is_base_of<event_based_actor, Impl>::value || static_assert(!std::is_base_of<blocking_actor, Impl>::value ||
(std::is_base_of<blocking_actor, Impl>::value && has_blocking_api_flag(Opts),
has_blocking_api_flag(Opts)), "Impl is derived type of blocking_actor but "
"Impl is not a derived type of event_based_actor or "
"is a derived type of blocking_actor but "
"blocking_api_flag is missing"); "blocking_api_flag is missing");
static_assert(is_unbound(Opts), static_assert(is_unbound(Opts),
"top-level spawns cannot have monitor or link flag"); "top-level spawns cannot have monitor or link flag");
...@@ -132,7 +133,7 @@ struct spawn_fwd<scoped_actor> { ...@@ -132,7 +133,7 @@ struct spawn_fwd<scoped_actor> {
// forwards the arguments to spawn_impl, replacing pointers // forwards the arguments to spawn_impl, replacing pointers
// to actors with instances of 'actor' // to actors with instances of 'actor'
template<class Impl, spawn_options Opts, typename BeforeLaunch, typename... Ts> template<class Impl, spawn_options Opts, typename BeforeLaunch, typename... Ts>
actor spawn_fwd_args(BeforeLaunch before_launch_fun, Ts&&... args) { intrusive_ptr<Impl> spawn_fwd_args(BeforeLaunch before_launch_fun, Ts&&... args) {
return spawn_impl<Impl, Opts>( return spawn_impl<Impl, Opts>(
before_launch_fun, before_launch_fun,
spawn_fwd<typename util::rm_const_and_ref<Ts>::type>::fwd( spawn_fwd<typename util::rm_const_and_ref<Ts>::type>::fwd(
...@@ -214,6 +215,71 @@ actor spawn_in_group(const group& grp, Ts&&... args) { ...@@ -214,6 +215,71 @@ actor spawn_in_group(const group& grp, Ts&&... args) {
std::forward<Ts>(args)...); std::forward<Ts>(args)...);
} }
namespace detail {
template<typename... Sigs>
class functor_based_typed_actor : public typed_event_based_actor<Sigs...> {
typedef typed_event_based_actor<Sigs...> super;
public:
typedef functor_based_typed_actor* pointer;
typedef typename super::behavior_type behavior_type;
typedef std::function<typed_behavior<Sigs...> ()> no_arg_fun;
typedef std::function<typed_behavior<Sigs...> (pointer)> one_arg_fun;
functor_based_typed_actor(one_arg_fun fun) : m_fun(std::move(fun)) { }
functor_based_typed_actor(no_arg_fun fun) {
m_fun = [fun](pointer) { return fun(); };
}
protected:
behavior_type make_behavior() override {
return m_fun(this);
}
private:
one_arg_fun m_fun;
};
template<typename TypedBehavior>
struct actor_type_from_typed_behavior;
template<typename... Signatures>
struct actor_type_from_typed_behavior<typed_behavior<Signatures...>> {
typedef functor_based_typed_actor<Signatures...> type;
};
template<typename TypedBehavior>
struct actor_handle_from_typed_behavior;
template<typename... Signatures>
struct actor_handle_from_typed_behavior<typed_behavior<Signatures...>> {
typedef typed_actor<Signatures...> type;
};
} // namespace detail
template<spawn_options Options = no_spawn_options, typename F>
typename detail::actor_handle_from_typed_behavior<
typename util::get_callable_trait<F>::result_type
>::type
spawn_typed(F fun) {
typedef typename detail::actor_type_from_typed_behavior<
typename util::get_callable_trait<F>::result_type
>::type
impl;
return detail::spawn_fwd_args<impl, Options>(
[&](impl*) { },
std::move(fun));
}
/* /*
template<class Impl, spawn_options Opts = no_spawn_options, typename... Ts> template<class Impl, spawn_options Opts = no_spawn_options, typename... Ts>
typename Impl::typed_pointer_type spawn_typed(Ts&&... args) { typename Impl::typed_pointer_type spawn_typed(Ts&&... args) {
......
...@@ -31,24 +31,65 @@ ...@@ -31,24 +31,65 @@
#ifndef CPPA_TYPED_ACTOR_HPP #ifndef CPPA_TYPED_ACTOR_HPP
#define CPPA_TYPED_ACTOR_HPP #define CPPA_TYPED_ACTOR_HPP
#include "cppa/replies_to.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/abstract_actor.hpp" #include "cppa/abstract_actor.hpp"
#include "cppa/typed_event_based_actor.hpp"
namespace cppa { namespace cppa {
class local_actor; template<typename... Signatures>
/**
* @brief Identifies an untyped actor.
*/
template<typename Interface>
class typed_actor { class typed_actor {
friend class local_actor; public:
typedef typed_event_based_actor<Signatures...> actor_type;
typedef util::type_list<Signatures...> signatures;
typed_actor() = default;
typed_actor(typed_actor&&) = default;
typed_actor(const typed_actor&) = default;
typed_actor& operator=(typed_actor&&) = default;
typed_actor& operator=(const typed_actor&) = default;
template<typename... OtherSignatures>
typed_actor(const typed_actor<OtherSignatures...>& other) {
set(std::move(other));
}
template<typename... OtherSignatures>
typed_actor& operator=(const typed_actor<OtherSignatures...>& other) {
set(std::move(other));
return *this;
}
template<template<typename...> class Impl, typename... OtherSignatures>
typed_actor(intrusive_ptr<Impl<OtherSignatures...>> other) {
set(other);
}
private: private:
intrusive_ptr<abstract_actor> m_ptr; template<class ListA, class ListB>
inline void check_signatures() {
static_assert(util::tl_is_strict_subset<ListA, ListB>::value,
"'this' must be a strict subset of 'other'");
}
template<typename... OtherSignatures>
inline void set(const typed_actor<OtherSignatures...>& other) {
check_signatures<signatures, util::type_list<OtherSignatures...>>();
m_ptr = other.m_ptr;
}
template<template<typename...> class Impl, typename... OtherSignatures>
inline void set(intrusive_ptr<Impl<OtherSignatures...>>& other) {
check_signatures<signatures, util::type_list<OtherSignatures...>>();
m_ptr = std::move(other);
}
abstract_actor_ptr m_ptr;
}; };
......
...@@ -38,6 +38,9 @@ ...@@ -38,6 +38,9 @@
namespace cppa { namespace cppa {
template<class, typename...>
class typed_behavior_stack_based;
template<typename... Signatures> template<typename... Signatures>
class typed_actor; class typed_actor;
...@@ -47,6 +50,9 @@ class typed_behavior { ...@@ -47,6 +50,9 @@ class typed_behavior {
template<typename... OtherSignatures> template<typename... OtherSignatures>
friend class typed_actor; friend class typed_actor;
template<class, typename...>
friend class typed_behavior_stack_based;
typed_behavior() = delete; typed_behavior() = delete;
public: public:
...@@ -60,19 +66,55 @@ class typed_behavior { ...@@ -60,19 +66,55 @@ class typed_behavior {
template<typename... Cs> template<typename... Cs>
typed_behavior(match_expr<Cs...> expr) { typed_behavior(match_expr<Cs...> expr) {
static_asserts(expr);
set(std::move(expr)); set(std::move(expr));
} }
template<typename... Cs> template<typename... Cs>
typed_behavior& operator=(match_expr<Cs...> expr) { typed_behavior& operator=(match_expr<Cs...> expr) {
static_asserts(expr);
set(std::move(expr)); set(std::move(expr));
return *this; return *this;
} }
explicit operator bool() const {
return static_cast<bool>(m_bhvr);
}
/**
* @brief Invokes the timeout callback.
*/
inline void handle_timeout() {
m_bhvr.handle_timeout();
}
/**
* @brief Returns the duration after which receives using
* this behavior should time out.
*/
inline const util::duration& timeout() const {
return m_bhvr.timeout();
}
private: private:
behavior& unbox() { return m_bhvr; } behavior& unbox() { return m_bhvr; }
template<typename... Cs>
void static_asserts(const match_expr<Cs...>&) {
static_assert(util::conjunction<
detail::match_expr_has_no_guard<Cs>::value...
>::value,
"typed actors are not allowed to use guard expressions");
static_assert(util::tl_is_distinct<
util::type_list<
typename detail::deduce_signature<Cs>::arg_types...
>
>::value,
"typed actors are not allowed to define "
"multiple patterns with identical signature");
}
template<typename... Cs> template<typename... Cs>
void set(match_expr<Cs...>&& expr) { void set(match_expr<Cs...>&& expr) {
m_bhvr = std::move(expr); m_bhvr = std::move(expr);
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_TYPED_BEHAVIOR_STACK_BASED_HPP
#define CPPA_TYPED_BEHAVIOR_STACK_BASED_HPP
#include <utility>
#include "cppa/single_timeout.hpp"
#include "cppa/behavior_policy.hpp"
#include "cppa/typed_event_based_actor.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/detail/behavior_stack.hpp"
namespace cppa {
/**
* @brief Mixin for actors using a typed stack-based message processing.
* @note This mixin implicitly includes {@link single_timeout}.
* @note Subtype must provide a typedef for @p behavior_type.
*/
template<class Base, typename... Signatures>
class typed_behavior_stack_based : public extend<Base>::template
with<single_timeout> {
public:
typedef typed_behavior<Signatures...> behavior_type;
/**
* @brief Sets the actor's behavior and discards the previous behavior
* unless {@link keep_behavior} is given as first argument.
*/
void become(behavior_type bhvr) {
do_become(std::move(bhvr), true);
}
template<bool Discard>
void become(behavior_policy<Discard>, behavior_type bhvr) {
do_become(std::move(bhvr), Discard);
}
template<typename T, typename... Ts>
inline typename std::enable_if<
!is_behavior_policy<typename util::rm_const_and_ref<T>::type>::value,
void
>::type
become(T&& arg, Ts&&... args) {
do_become(behavior_type{std::forward<T>(arg),
std::forward<Ts>(args)...},
true);
}
template<bool Discard, typename... Ts>
void become(behavior_policy<Discard>, Ts&&... args) {
do_become(behavior_type{std::forward<Ts>(args)...}, Discard);
}
inline void unbecome() {
m_bhvr_stack.pop_async_back();
}
inline bool has_behavior() const {
return m_bhvr_stack.empty() == false;
}
inline behavior& get_behavior() {
CPPA_REQUIRE(m_bhvr_stack.empty() == false);
return m_bhvr_stack.back();
}
inline detail::behavior_stack& bhvr_stack() {
return m_bhvr_stack;
}
inline optional<behavior&> sync_handler(message_id msg_id) {
return m_bhvr_stack.sync_handler(msg_id);
}
inline void remove_handler(message_id mid) {
m_bhvr_stack.erase(mid);
}
private:
void do_become(behavior_type bhvr, bool discard_old) {
if (discard_old) this->m_bhvr_stack.pop_async_back();
this->reset_timeout();
if (bhvr.timeout().valid()) {
this->request_timeout(bhvr.timeout());
}
this->m_bhvr_stack.push_back(std::move(bhvr.unbox()));
}
// allows actors to keep previous behaviors and enables unbecome()
detail::behavior_stack m_bhvr_stack;
};
} // namespace cppa
#endif // CPPA_TYPED_BEHAVIOR_STACK_BASED_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_TYPED_EVENT_BASED_ACTOR_HPP
#define CPPA_TYPED_EVENT_BASED_ACTOR_HPP
#include "cppa/replies_to.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/mailbox_based.hpp"
#include "cppa/typed_behavior.hpp"
#include "cppa/typed_behavior_stack_based.hpp"
namespace cppa {
template<typename... Signatures>
class typed_event_based_actor : public typed_behavior_stack_based<
extend<local_actor>::template
with<mailbox_based>,
Signatures...> {
public:
typedef util::type_list<Signatures...> signatures;
typedef typed_behavior<Signatures...> behavior_type;
protected:
virtual behavior_type make_behavior() = 0;
};
} // namespace cppa
#endif // CPPA_TYPED_EVENT_BASED_ACTOR_HPP
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