Commit 064ea792 authored by Dominik Charousset's avatar Dominik Charousset

more consistent behavior impl

parent 4fb2eb2e
...@@ -49,9 +49,9 @@ namespace cppa { ...@@ -49,9 +49,9 @@ namespace cppa {
/** /**
* @brief Describes the behavior of an actor. * @brief Describes the behavior of an actor.
*/ */
class behavior { class behavior : public partial_function {
friend behavior operator,(partial_function&& lhs, behavior&& rhs); typedef partial_function super;
public: public:
...@@ -61,57 +61,60 @@ class behavior { ...@@ -61,57 +61,60 @@ class behavior {
behavior& operator=(behavior&&) = default; behavior& operator=(behavior&&) = default;
behavior& operator=(const behavior&) = default; behavior& operator=(const behavior&) = default;
inline behavior(partial_function&& fun) : m_fun(std::move(fun)) { } inline behavior(partial_function fun) : super(std::move(fun)) { }
template<typename... Cases> inline behavior(partial_function::impl_ptr ptr) : super(std::move(ptr)) { }
behavior(const match_expr<Cases...>& me) : m_fun(me) { }
inline behavior(util::duration tout, std::function<void()>&& handler) template<typename F>
: m_timeout(tout), m_timeout_handler(std::move(handler)) { behavior(const timeout_definition<F>& arg)
: super(new default_behavior_impl<dummy_match_expr, F>(dummy_match_expr{},
arg.timeout,
arg.handler)) {
} }
inline void handle_timeout() const { template<typename F>
m_timeout_handler(); behavior(util::duration d, F f)
: super(new default_behavior_impl<dummy_match_expr, F>(dummy_match_expr{},
d, f)) {
} }
inline const util::duration& timeout() const { template<typename... Cases, typename... Args>
return m_timeout; behavior(const match_expr<Cases...>& arg0, const Args&... args)
} : super(match_expr_concat(arg0, args...)) { }
inline partial_function& get_partial_function() {
return m_fun;
}
inline bool operator()(any_tuple& value) { inline void handle_timeout() {
return m_fun(value); m_impl->handle_timeout();
} }
inline bool operator()(const any_tuple& value) { inline const util::duration& timeout() const {
return m_fun(value); return m_impl->timeout();
}
inline bool operator()(any_tuple&& value) {
return m_fun(std::move(value));
} }
inline bool undefined() const { inline bool undefined() const {
return m_fun.undefined() && m_timeout.valid() == false; return m_impl == nullptr && m_impl->timeout().valid();
} }
private: };
partial_function m_fun; template<typename Arg0, typename... Args>
util::duration m_timeout; typename util::if_else<
std::function<void()> m_timeout_handler; util::disjunction<
is_timeout_definition<Arg0>,
is_timeout_definition<Args>...>,
behavior,
util::wrapped<partial_function> >::type
match_expr_convert(const Arg0& arg0, const Args&... args) {
return {match_expr_concat(arg0, args...)};
}
}; /*
/** / *
* @brief Concatenates a match expression and a timeout specification * @brief Concatenates a match expression and a timeout specification
* represented by an rvalue behavior object. * represented by an rvalue behavior object.
*/ * /
template<typename... Lhs> template<typename F, typename... Lhs>
behavior operator,(const match_expr<Lhs...>& lhs, behavior&& rhs) { behavior operator,(const match_expr<Lhs...>& lhs, timeout_definition<F>&& rhs) {
CPPA_REQUIRE(rhs.get_partial_function().undefined()); CPPA_REQUIRE(rhs.get_partial_function().undefined());
rhs.get_partial_function() = lhs; rhs.get_partial_function() = lhs;
return std::move(rhs); return std::move(rhs);
...@@ -173,6 +176,8 @@ struct select_bhvr { ...@@ -173,6 +176,8 @@ struct select_bhvr {
} // namespace detail } // namespace detail
*/
} // namespace cppa } // namespace cppa
#endif // CPPA_BEHAVIOR_HPP #endif // CPPA_BEHAVIOR_HPP
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <memory> #include <memory>
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/detail/disablable_delete.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -49,19 +48,16 @@ class behavior_stack ...@@ -49,19 +48,16 @@ class behavior_stack
behavior_stack() = default; behavior_stack() = default;
typedef detail::disablable_delete<behavior> deleter;
typedef std::unique_ptr<behavior, deleter> value_type;
inline bool empty() const { return m_elements.empty(); } inline bool empty() const { return m_elements.empty(); }
inline behavior& back() { return *m_elements.back(); } inline behavior& back() { return m_elements.back(); }
// executes the behavior stack // executes the behavior stack
void exec(); void exec();
void pop_back(); void pop_back();
void push_back(behavior* what, bool has_ownership); void push_back(behavior&& what);
void cleanup(); void cleanup();
...@@ -69,8 +65,8 @@ class behavior_stack ...@@ -69,8 +65,8 @@ class behavior_stack
private: private:
std::vector<value_type> m_elements; std::vector<behavior> m_elements;
std::vector<value_type> m_erased_elements; std::vector<behavior> m_erased_elements;
}; };
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "cppa/self.hpp" #include "cppa/self.hpp"
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
...@@ -62,8 +63,9 @@ struct receive_while_helper { ...@@ -62,8 +63,9 @@ struct receive_while_helper {
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
void operator()(Arg0&& arg0, Args&&... args) { void operator()(Arg0&& arg0, Args&&... args) {
auto tmp = match_expr_concat(std::forward<Arg0>(arg0), auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...); (*this)(tmp); std::forward<Args>(args)...);
(*this)(tmp);
} }
...@@ -91,8 +93,9 @@ class receive_for_helper { ...@@ -91,8 +93,9 @@ class receive_for_helper {
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
void operator()(Arg0&& arg0, Args&&... args) { void operator()(Arg0&& arg0, Args&&... args) {
auto tmp = match_expr_concat(std::forward<Arg0>(arg0), auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...); (*this)(tmp); std::forward<Args>(args)...);
(*this)(tmp);
} }
}; };
...@@ -122,8 +125,9 @@ class do_receive_helper { ...@@ -122,8 +125,9 @@ class do_receive_helper {
while (stmt() == false); while (stmt() == false);
} }
else { else {
partial_function& pfun = m_bhvr;
do { do {
sptr->dequeue(m_bhvr.get_partial_function()); sptr->dequeue(pfun);
} }
while (stmt() == false); while (stmt() == false);
} }
......
...@@ -126,7 +126,7 @@ class receive_policy { ...@@ -126,7 +126,7 @@ class receive_policy {
template<class Client> template<class Client>
void receive(Client* client, behavior& bhvr) { void receive(Client* client, behavior& bhvr) {
auto& fun = bhvr.get_partial_function(); partial_function& fun = bhvr;
if (bhvr.timeout().valid() == false) { if (bhvr.timeout().valid() == false) {
receive(client, fun); receive(client, fun);
} }
......
...@@ -47,7 +47,7 @@ struct scheduled_actor_dummy : abstract_scheduled_actor { ...@@ -47,7 +47,7 @@ struct scheduled_actor_dummy : abstract_scheduled_actor {
void detach(const attachable::token&); void detach(const attachable::token&);
bool attach(attachable*); bool attach(attachable*);
void unbecome(); void unbecome();
void do_become(behavior*, bool, bool); void do_become(behavior&&, bool);
bool has_behavior(); bool has_behavior();
scheduled_actor_type impl_type(); scheduled_actor_type impl_type();
}; };
......
...@@ -77,14 +77,14 @@ class stacked_actor_mixin : public Base { ...@@ -77,14 +77,14 @@ class stacked_actor_mixin : public Base {
stacked_actor_mixin(std::function<void()> f) : m_behavior(std::move(f)) { } stacked_actor_mixin(std::function<void()> f) : m_behavior(std::move(f)) { }
virtual void do_become(behavior* bhvr, bool owns_bhvr, bool discard_old) { virtual void do_become(behavior&& bhvr, bool discard_old) {
if (m_bhvr_stack_ptr) { if (m_bhvr_stack_ptr) {
if (discard_old) m_bhvr_stack_ptr->pop_back(); if (discard_old) m_bhvr_stack_ptr->pop_back();
m_bhvr_stack_ptr->push_back(bhvr, owns_bhvr); m_bhvr_stack_ptr->push_back(std::move(bhvr));
} }
else { else {
m_bhvr_stack_ptr.reset(new behavior_stack); m_bhvr_stack_ptr.reset(new behavior_stack);
m_bhvr_stack_ptr->push_back(bhvr, owns_bhvr); m_bhvr_stack_ptr->push_back(std::move(bhvr));
if (this->initialized()) { if (this->initialized()) {
m_bhvr_stack_ptr->exec(); m_bhvr_stack_ptr->exec();
m_bhvr_stack_ptr.reset(); m_bhvr_stack_ptr.reset();
......
...@@ -127,7 +127,7 @@ class event_based_actor : public detail::abstract_scheduled_actor { ...@@ -127,7 +127,7 @@ class event_based_actor : public detail::abstract_scheduled_actor {
receive(std::forward<Args>(args)...); receive(std::forward<Args>(args)...);
} }
void do_become(behavior* bhvr, bool owns_bhvr, bool discard_old); void do_become(behavior&& bhvr, bool discard_old);
private: private:
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/exit_reason.hpp" #include "cppa/exit_reason.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
#include "cppa/intrusive/single_reader_queue.hpp" #include "cppa/intrusive/single_reader_queue.hpp"
...@@ -202,14 +203,14 @@ class local_actor : public actor { ...@@ -202,14 +203,14 @@ class local_actor : public actor {
* the actor terminates. * the actor terminates.
*/ */
inline void become(discard_behavior_t, behavior* bhvr) { inline void become(discard_behavior_t, behavior* bhvr) {
do_become(bhvr, false, true); do_become(*bhvr, true);
} }
/** /**
* @brief Sets the actor's behavior. * @brief Sets the actor's behavior.
*/ */
inline void become(discard_behavior_t, behavior&& bhvr) { inline void become(discard_behavior_t, behavior bhvr) {
do_become(new behavior(std::move(bhvr)), true, true); do_become(std::move(bhvr), true);
} }
/** /**
...@@ -222,20 +223,20 @@ class local_actor : public actor { ...@@ -222,20 +223,20 @@ class local_actor : public actor {
* the actor terminates. * the actor terminates.
*/ */
inline void become(keep_behavior_t, behavior* bhvr) { inline void become(keep_behavior_t, behavior* bhvr) {
do_become(bhvr, false, false); do_become(*bhvr, false);
} }
/** /**
* @brief Sets the actor's behavior. * @brief Sets the actor's behavior.
*/ */
inline void become(keep_behavior_t, behavior&& bhvr) { inline void become(keep_behavior_t, behavior bhvr) {
do_become(new behavior(std::move(bhvr)), true, false); do_become(std::move(bhvr), false);
} }
/** /**
* @brief Sets the actor's behavior. * @brief Sets the actor's behavior.
*/ */
inline void become(behavior&& bhvr) { inline void become(behavior bhvr) {
become(discard_behavior, std::move(bhvr)); become(discard_behavior, std::move(bhvr));
} }
...@@ -243,7 +244,7 @@ class local_actor : public actor { ...@@ -243,7 +244,7 @@ class local_actor : public actor {
* @brief Equal to <tt>become(discard_old, bhvr)</tt>. * @brief Equal to <tt>become(discard_old, bhvr)</tt>.
*/ */
inline void become(behavior* bhvr) { inline void become(behavior* bhvr) {
become(discard_behavior, bhvr); become(discard_behavior, *bhvr);
} }
/** /**
...@@ -251,7 +252,7 @@ class local_actor : public actor { ...@@ -251,7 +252,7 @@ class local_actor : public actor {
*/ */
template<typename... Cases, typename... Args> template<typename... Cases, typename... Args>
inline void become(discard_behavior_t, match_expr<Cases...>&& arg0, Args&&... args) { inline void become(discard_behavior_t, match_expr<Cases...>&& arg0, Args&&... args) {
become(discard_behavior, match_expr_concat(std::move(arg0), std::forward<Args>(args)...)); become(discard_behavior, match_expr_convert(std::move(arg0), std::forward<Args>(args)...));
} }
/** /**
...@@ -259,7 +260,7 @@ class local_actor : public actor { ...@@ -259,7 +260,7 @@ class local_actor : public actor {
*/ */
template<typename... Cases, typename... Args> template<typename... Cases, typename... Args>
inline void become(keep_behavior_t, match_expr<Cases...>&& arg0, Args&&... args) { inline void become(keep_behavior_t, match_expr<Cases...>&& arg0, Args&&... args) {
become(keep_behavior, match_expr_concat(std::move(arg0), std::forward<Args>(args)...)); become(keep_behavior, match_expr_convert(std::move(arg0), std::forward<Args>(args)...));
} }
/** /**
...@@ -267,7 +268,7 @@ class local_actor : public actor { ...@@ -267,7 +268,7 @@ class local_actor : public actor {
*/ */
template<typename... Cases, typename... Args> template<typename... Cases, typename... Args>
inline void become(match_expr<Cases...> arg0, Args&&... args) { inline void become(match_expr<Cases...> arg0, Args&&... args) {
become(discard_behavior, match_expr_concat(std::move(arg0), std::forward<Args>(args)...)); become(discard_behavior, match_expr_convert(std::move(arg0), std::forward<Args>(args)...));
} }
/** /**
...@@ -333,7 +334,12 @@ class local_actor : public actor { ...@@ -333,7 +334,12 @@ class local_actor : public actor {
protected: protected:
virtual void do_become(behavior* bhvr, bool owns_ptr, bool discard_old) = 0; virtual void do_become(behavior&& bhvr, bool discard_old) = 0;
inline void do_become(const behavior& bhvr, bool discard_old) {
behavior copy{bhvr};
do_become(std::move(copy), discard_old);
}
}; };
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#ifndef CPPA_MATCH_HPP #ifndef CPPA_MATCH_HPP
#define CPPA_MATCH_HPP #define CPPA_MATCH_HPP
#include <type_traits>
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
...@@ -50,8 +52,10 @@ struct match_helper { ...@@ -50,8 +52,10 @@ struct match_helper {
*/ */
template<class Arg0, class... Args> template<class Arg0, class... Args>
void operator()(Arg0&& arg0, Args&&... args) { void operator()(Arg0&& arg0, Args&&... args) {
auto tmp = mexpr_concat(std::forward<Arg0>(arg0), auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...); std::forward<Args>(args)...);
static_assert(std::is_same<partial_function, decltype(tmp)>::value,
"match statement contains timeout");
tmp(tup); tmp(tup);
} }
}; };
...@@ -71,8 +75,9 @@ struct match_each_helper { ...@@ -71,8 +75,9 @@ struct match_each_helper {
} }
} }
template<class Arg0, class... Args> template<class Arg0, class... Args>
void operator()(Arg0&& arg0, Args&&... args) { (*this)(mexpr_concat_convert(std::forward<Arg0>(arg0), void operator()(Arg0&& arg0, Args&&... args) {
std::forward<Args>(args)...)); (*this)(match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...));
} }
}; };
...@@ -90,8 +95,9 @@ struct copying_match_each_helper { ...@@ -90,8 +95,9 @@ struct copying_match_each_helper {
} }
} }
template<class Arg0, class... Args> template<class Arg0, class... Args>
void operator()(Arg0&& arg0, Args&&... args) { (*this)(mexpr_concat_convert(std::forward<Arg0>(arg0), void operator()(Arg0&& arg0, Args&&... args) {
std::forward<Args>(args)...)); (*this)(match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...));
} }
}; };
...@@ -114,8 +120,9 @@ struct pmatch_each_helper { ...@@ -114,8 +120,9 @@ struct pmatch_each_helper {
} }
} }
template<class Arg0, class... Args> template<class Arg0, class... Args>
void operator()(Arg0&& arg0, Args&&... args) { (*this)(mexpr_concat_convert(std::forward<Arg0>(arg0), void operator()(Arg0&& arg0, Args&&... args) {
std::forward<Args>(args)...)); (*this)(match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...));
} }
}; };
......
...@@ -702,7 +702,7 @@ class match_expr { ...@@ -702,7 +702,7 @@ class match_expr {
return m_cases; return m_cases;
} }
struct pfun_impl : partial_function::impl { struct pfun_impl : behavior_impl {
match_expr pfun; match_expr pfun;
template<typename Arg> template<typename Arg>
pfun_impl(const Arg& from) : pfun(from) { } pfun_impl(const Arg& from) : pfun(from) { }
...@@ -717,6 +717,8 @@ class match_expr { ...@@ -717,6 +717,8 @@ class match_expr {
} }
}; };
inline partial_function as_partial_function() const { inline partial_function as_partial_function() const {
return {partial_function::impl_ptr{new pfun_impl(*this)}}; return {partial_function::impl_ptr{new pfun_impl(*this)}};
} }
...@@ -861,6 +863,7 @@ inline match_expr<Lhs..., Rhs...> operator,(const match_expr<Lhs...>& lhs, ...@@ -861,6 +863,7 @@ inline match_expr<Lhs..., Rhs...> operator,(const match_expr<Lhs...>& lhs,
return lhs.or_else(rhs); return lhs.or_else(rhs);
} }
/*
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
typename match_expr_from_type_list< typename match_expr_from_type_list<
typename util::tl_concat< typename util::tl_concat<
...@@ -882,29 +885,94 @@ mexpr_concat(const Arg0& arg0, const Args&... args) { ...@@ -882,29 +885,94 @@ mexpr_concat(const Arg0& arg0, const Args&... args) {
detail::collect_tdata(all_cases, arg0.cases(), args.cases()...); detail::collect_tdata(all_cases, arg0.cases(), args.cases()...);
return {all_cases}; return {all_cases};
} }
*/
template<typename Arg0, typename... Args> template<bool HasTimeout>
partial_function mexpr_concat_convert(const Arg0& arg0, const Args&... args) { struct match_expr_concat_impl {
typename detail::tdata_from_type_list< template<typename Arg0, typename... Args>
typename util::tl_map< static behavior_impl* _(const Arg0& arg0, const Args&... args) {
typename util::tl_concat< typename detail::tdata_from_type_list<
typename Arg0::cases_list, typename util::tl_map<
typename Args::cases_list...
>::type,
gref_wrapped
>::type
>::type
all_cases;
typedef typename match_expr_from_type_list<
typename util::tl_concat< typename util::tl_concat<
typename Arg0::cases_list, typename Arg0::cases_list,
typename Args::cases_list... typename Args::cases_list...
>::type,
gref_wrapped
>::type
>::type
all_cases;
typedef typename match_expr_from_type_list<
typename util::tl_concat<
typename Arg0::cases_list,
typename Args::cases_list...
>::type
>::type
combined_type;
auto lvoid = []() { };
typedef default_behavior_impl<combined_type, decltype(lvoid)> impl_type;
detail::collect_tdata(all_cases, arg0.cases(), args.cases()...);
return new impl_type(all_cases, util::duration{}, lvoid);
}
};
template<>
struct match_expr_concat_impl<true> {
template<class TData, typename Cases, typename F>
static behavior_impl* __(const TData& data, Cases, const timeout_definition<F>& arg0) {
typedef typename match_expr_from_type_list<Cases>::type combined_type;
typedef default_behavior_impl<combined_type, F> impl_type;
return new impl_type(data, arg0);
}
template<class TData, typename Token, typename... Cases, typename... Args>
static behavior_impl* __(const TData& data, Token, const match_expr<Cases...>& arg0, const Args&... args) {
typedef typename util::tl_concat<
Token,
util::type_list<Cases...>
>::type
next_token_type;
typename detail::tdata_from_type_list<
typename util::tl_map<
next_token_type,
gref_wrapped
>::type >::type
>::type >::type
combined_type; next_data;
typedef typename combined_type::pfun_impl impl_type; next_token_type next_token;
detail::collect_tdata(all_cases, arg0.cases(), args.cases()...); detail::collect_tdata(next_data, data, arg0.cases());
return {partial_function::impl_ptr{new impl_type(all_cases)}}; return __(next_data, next_token, args...);
}
template<typename F>
static behavior_impl* _(const timeout_definition<F>& arg0) {
typedef default_behavior_impl<dummy_match_expr, F> impl_type;
return new impl_type(dummy_match_expr{}, arg0);
}
template<typename... Cases, typename... Args>
static behavior_impl* _(const match_expr<Cases...>& arg0, const Args&... args) {
util::type_list<Cases...> token;
typename detail::tdata_from_type_list<
typename util::tl_map<
util::type_list<Cases...>,
gref_wrapped
>::type
>::type
wrapper;
detail::collect_tdata(wrapper, arg0.cases());
return __(wrapper, token, args...);
}
};
template<typename Arg0, typename... Args>
intrusive_ptr<behavior_impl> match_expr_concat(const Arg0& arg0,
const Args&... args) {
constexpr bool has_timeout = util::disjunction<
is_timeout_definition<Arg0>,
is_timeout_definition<Args>...>::value;
return {match_expr_concat_impl<has_timeout>::_(arg0, args...)};
} }
} // namespace cppa } // namespace cppa
......
...@@ -99,8 +99,8 @@ class behavior_rvalue_builder { ...@@ -99,8 +99,8 @@ class behavior_rvalue_builder {
} }
template<typename F> template<typename F>
behavior operator>>(F&& f) { timeout_definition<F> operator>>(F&& f) {
return {m_timeout, std::function<void()>{std::forward<F>(f)}}; return {m_timeout, std::forward<F>(f)};
} }
}; };
......
...@@ -36,13 +36,86 @@ ...@@ -36,13 +36,86 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "cppa/any_tuple.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/intrusive/singly_linked_list.hpp" #include "cppa/util/duration.hpp"
namespace cppa { namespace cppa {
class behavior; class behavior_impl : public ref_counted {
public:
behavior_impl() = default;
behavior_impl(util::duration tout);
virtual bool invoke(any_tuple&) = 0;
virtual bool invoke(const any_tuple&) = 0;
virtual bool defined_at(const any_tuple&) = 0;
virtual void handle_timeout();
inline const util::duration& timeout() const {
return m_timeout;
}
private:
util::duration m_timeout;
};
template<typename F>
struct timeout_definition {
util::duration timeout;
F handler;
};
template<typename T>
struct is_timeout_definition : std::false_type { };
template<typename F>
struct is_timeout_definition<timeout_definition<F> > : std::true_type { };
struct dummy_match_expr {
inline bool invoke(const any_tuple&) { return false; }
inline bool can_invoke(const any_tuple&) { return false; }
};
template<class MatchExpr, typename F>
class default_behavior_impl : public behavior_impl {
typedef behavior_impl super;
public:
template<typename Expr>
default_behavior_impl(Expr&& expr, const timeout_definition<F>& d)
: super(d.timeout), m_expr(std::forward<Expr>(expr)), m_fun(d.handler) { }
template<typename Expr>
default_behavior_impl(Expr&& expr, util::duration tout, F f)
: super(tout), m_expr(std::forward<Expr>(expr)), m_fun(f) { }
bool invoke(any_tuple& tup) {
return m_expr.invoke(tup);
}
bool invoke(const any_tuple& tup) {
return m_expr.invoke(tup);
}
bool defined_at(const any_tuple& tup) {
return m_expr.can_invoke(tup);
}
void handle_timeout() { m_fun(); }
private:
MatchExpr m_expr;
F m_fun;
};
/** /**
* @brief A partial function implementation * @brief A partial function implementation
...@@ -52,13 +125,7 @@ class partial_function { ...@@ -52,13 +125,7 @@ class partial_function {
public: public:
struct impl : ref_counted { typedef intrusive_ptr<behavior_impl> impl_ptr;
virtual bool invoke(any_tuple&) = 0;
virtual bool invoke(const any_tuple&) = 0;
virtual bool defined_at(const any_tuple&) = 0;
};
typedef intrusive_ptr<impl> impl_ptr;
partial_function() = default; partial_function() = default;
partial_function(partial_function&&) = default; partial_function(partial_function&&) = default;
...@@ -66,7 +133,11 @@ class partial_function { ...@@ -66,7 +133,11 @@ class partial_function {
partial_function& operator=(partial_function&&) = default; partial_function& operator=(partial_function&&) = default;
partial_function& operator=(const partial_function&) = default; partial_function& operator=(const partial_function&) = default;
partial_function(impl_ptr&& ptr); partial_function(impl_ptr ptr);
inline bool undefined() const {
return m_impl == nullptr;
}
inline bool defined_at(const any_tuple& value) { inline bool defined_at(const any_tuple& value) {
return (m_impl) && m_impl->defined_at(value); return (m_impl) && m_impl->defined_at(value);
...@@ -85,13 +156,9 @@ class partial_function { ...@@ -85,13 +156,9 @@ class partial_function {
return (*this)(cpy); return (*this)(cpy);
} }
inline bool undefined() const { protected:
return m_impl == nullptr;
}
private:
impl_ptr m_impl; intrusive_ptr<behavior_impl> m_impl;
}; };
......
...@@ -123,8 +123,8 @@ inline void receive(partial_function& fun) { self->dequeue(fun); } ...@@ -123,8 +123,8 @@ inline void receive(partial_function& fun) { self->dequeue(fun); }
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
void receive(Arg0&& arg0, Args&&... args) { void receive(Arg0&& arg0, Args&&... args) {
auto tmp = match_expr_concat(std::forward<Arg0>(arg0), auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...); std::forward<Args>(args)...);
receive(tmp); receive(tmp);
} }
...@@ -134,8 +134,8 @@ void receive_loop(partial_function& rules); ...@@ -134,8 +134,8 @@ void receive_loop(partial_function& rules);
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
void receive_loop(Arg0&& arg0, Args&&... args) { void receive_loop(Arg0&& arg0, Args&&... args) {
auto tmp = match_expr_concat(std::forward<Arg0>(arg0), auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...); std::forward<Args>(args)...);
receive_loop(tmp); receive_loop(tmp);
} }
......
...@@ -50,7 +50,7 @@ class sb_actor : public event_based_actor { ...@@ -50,7 +50,7 @@ class sb_actor : public event_based_actor {
* @brief Overrides {@link event_based_actor::init()} and sets * @brief Overrides {@link event_based_actor::init()} and sets
* the initial actor behavior to <tt>Derived::init_state</tt>. * the initial actor behavior to <tt>Derived::init_state</tt>.
*/ */
void init() { become(&(static_cast<Derived*>(this)->init_state)); } void init() { become(static_cast<Derived*>(this)->init_state); }
}; };
......
...@@ -24,7 +24,7 @@ struct chopstick : sb_actor<chopstick> { ...@@ -24,7 +24,7 @@ struct chopstick : sb_actor<chopstick> {
send(other, atom("busy"), this); send(other, atom("busy"), this);
}, },
on(atom("put"), philos) >> [=]() { on(atom("put"), philos) >> [=]() {
become(&available); become(available);
} }
); );
} }
...@@ -103,12 +103,12 @@ struct philosopher : sb_actor<philosopher> { ...@@ -103,12 +103,12 @@ struct philosopher : sb_actor<philosopher> {
cout << oss.str(); cout << oss.str();
// eat some time // eat some time
delayed_send(this, seconds(5), atom("think")); delayed_send(this, seconds(5), atom("think"));
become(&eating); become(eating);
}, },
on(atom("busy"), what) >> [=]() { on(atom("busy"), what) >> [=]() {
send((what == left) ? right : left, atom("put"), this); send((what == left) ? right : left, atom("put"), this);
send(this, atom("eat")); send(this, atom("eat"));
become(&thinking); become(thinking);
} }
); );
} }
...@@ -118,7 +118,7 @@ struct philosopher : sb_actor<philosopher> { ...@@ -118,7 +118,7 @@ struct philosopher : sb_actor<philosopher> {
// a philosopher that receives {eat} stops thinking and becomes hungry // a philosopher that receives {eat} stops thinking and becomes hungry
thinking = ( thinking = (
on(atom("eat")) >> [=]() { on(atom("eat")) >> [=]() {
become(&hungry); become(hungry);
send(left, atom("take"), this); send(left, atom("take"), this);
send(right, atom("take"), this); send(right, atom("take"), this);
} }
...@@ -132,7 +132,7 @@ struct philosopher : sb_actor<philosopher> { ...@@ -132,7 +132,7 @@ struct philosopher : sb_actor<philosopher> {
become(waiting_for(left)); become(waiting_for(left));
}, },
on<atom("busy"), actor_ptr>() >> [=]() { on<atom("busy"), actor_ptr>() >> [=]() {
become(&denied); become(denied);
} }
); );
// philosopher was not able to obtain the first chopstick // philosopher was not able to obtain the first chopstick
...@@ -140,11 +140,11 @@ struct philosopher : sb_actor<philosopher> { ...@@ -140,11 +140,11 @@ struct philosopher : sb_actor<philosopher> {
on<atom("taken"), actor_ptr>() >> [=](actor_ptr& ptr) { on<atom("taken"), actor_ptr>() >> [=](actor_ptr& ptr) {
send(ptr, atom("put"), this); send(ptr, atom("put"), this);
send(this, atom("eat")); send(this, atom("eat"));
become(&thinking); become(thinking);
}, },
on<atom("busy"), actor_ptr>() >> [=]() { on<atom("busy"), actor_ptr>() >> [=]() {
send(this, atom("eat")); send(this, atom("eat"));
become(&thinking); become(thinking);
} }
); );
// philosopher obtained both chopstick and eats (for five seconds) // philosopher obtained both chopstick and eats (for five seconds)
...@@ -155,7 +155,7 @@ struct philosopher : sb_actor<philosopher> { ...@@ -155,7 +155,7 @@ struct philosopher : sb_actor<philosopher> {
delayed_send(this, seconds(5), atom("eat")); delayed_send(this, seconds(5), atom("eat"));
cout << ( name cout << ( name
+ " puts down his chopsticks and starts to think\n"); + " puts down his chopsticks and starts to think\n");
become(&thinking); become(thinking);
} }
); );
// philosophers start to think after receiving {think} // philosophers start to think after receiving {think}
...@@ -163,7 +163,7 @@ struct philosopher : sb_actor<philosopher> { ...@@ -163,7 +163,7 @@ struct philosopher : sb_actor<philosopher> {
on(atom("think")) >> [=]() { on(atom("think")) >> [=]() {
cout << (name + " starts to think\n"); cout << (name + " starts to think\n");
delayed_send(this, seconds(5), atom("eat")); delayed_send(this, seconds(5), atom("eat"));
become(&thinking); become(thinking);
} }
); );
} }
......
...@@ -48,10 +48,8 @@ void behavior_stack::pop_back() { ...@@ -48,10 +48,8 @@ void behavior_stack::pop_back() {
} }
} }
void behavior_stack::push_back(behavior* what, bool has_ownership) { void behavior_stack::push_back(behavior&& what) {
value_type new_element{what}; m_elements.emplace_back(std::move(what));
if (!has_ownership) new_element.get_deleter().disable();
m_elements.push_back(std::move(new_element));
} }
void behavior_stack::clear() { void behavior_stack::clear() {
......
...@@ -99,11 +99,11 @@ bool event_based_actor::has_behavior() { ...@@ -99,11 +99,11 @@ bool event_based_actor::has_behavior() {
return m_bhvr_stack.empty() == false; return m_bhvr_stack.empty() == false;
} }
void event_based_actor::do_become(behavior* ptr, bool owner, bool discard_old) { void event_based_actor::do_become(behavior&& bhvr, bool discard_old) {
reset_timeout(); reset_timeout();
request_timeout(ptr->timeout()); request_timeout(bhvr.timeout());
if (discard_old) m_bhvr_stack.pop_back(); if (discard_old) m_bhvr_stack.pop_back();
m_bhvr_stack.push_back(ptr, owner); m_bhvr_stack.push_back(std::move(bhvr));
} }
void event_based_actor::quit(std::uint32_t reason) { void event_based_actor::quit(std::uint32_t reason) {
......
...@@ -36,6 +36,10 @@ ...@@ -36,6 +36,10 @@
namespace cppa { namespace cppa {
partial_function::partial_function(impl_ptr&& ptr) : m_impl(std::move(ptr)) { } partial_function::partial_function(impl_ptr ptr) : m_impl(std::move(ptr)) { }
behavior_impl::behavior_impl(util::duration tout) : m_timeout(tout) { }
void behavior_impl::handle_timeout() { }
} // namespace cppa } // namespace cppa
...@@ -40,7 +40,7 @@ void scheduled_actor_dummy::unlink_from(intrusive_ptr<actor>&) { } ...@@ -40,7 +40,7 @@ void scheduled_actor_dummy::unlink_from(intrusive_ptr<actor>&) { }
void scheduled_actor_dummy::detach(const attachable::token&) { } void scheduled_actor_dummy::detach(const attachable::token&) { }
bool scheduled_actor_dummy::attach(attachable*) { return false; } bool scheduled_actor_dummy::attach(attachable*) { return false; }
void scheduled_actor_dummy::unbecome() { } void scheduled_actor_dummy::unbecome() { }
void scheduled_actor_dummy::do_become(behavior*, bool, bool) { } void scheduled_actor_dummy::do_become(behavior&&, bool) { }
bool scheduled_actor_dummy::has_behavior() { return false; } bool scheduled_actor_dummy::has_behavior() { return false; }
resume_result scheduled_actor_dummy::resume(util::fiber*) { resume_result scheduled_actor_dummy::resume(util::fiber*) {
......
...@@ -60,7 +60,7 @@ struct event_testee : public fsm_actor<event_testee> { ...@@ -60,7 +60,7 @@ struct event_testee : public fsm_actor<event_testee> {
behavior wait4string = ( behavior wait4string = (
on<std::string>() >> [=]() { on<std::string>() >> [=]() {
become(&wait4int); become(wait4int);
}, },
on<atom("get_state")>() >> [=]() { on<atom("get_state")>() >> [=]() {
reply("wait4string"); reply("wait4string");
...@@ -69,7 +69,7 @@ struct event_testee : public fsm_actor<event_testee> { ...@@ -69,7 +69,7 @@ struct event_testee : public fsm_actor<event_testee> {
behavior wait4float = ( behavior wait4float = (
on<float>() >> [=]() { on<float>() >> [=]() {
become(&wait4string); become(wait4string);
}, },
on<atom("get_state")>() >> [=]() { on<atom("get_state")>() >> [=]() {
reply("wait4float"); reply("wait4float");
...@@ -78,7 +78,7 @@ struct event_testee : public fsm_actor<event_testee> { ...@@ -78,7 +78,7 @@ struct event_testee : public fsm_actor<event_testee> {
behavior wait4int = ( behavior wait4int = (
on<int>() >> [=]() { on<int>() >> [=]() {
become(&wait4float); become(wait4float);
}, },
on<atom("get_state")>() >> [=]() { on<atom("get_state")>() >> [=]() {
reply("wait4int"); reply("wait4int");
...@@ -106,7 +106,7 @@ class event_testee : public sb_actor<event_testee> { ...@@ -106,7 +106,7 @@ class event_testee : public sb_actor<event_testee> {
event_testee() : init_state(wait4int) { event_testee() : init_state(wait4int) {
wait4string = ( wait4string = (
on<std::string>() >> [=]() { on<std::string>() >> [=]() {
become(&wait4int); become(wait4int);
}, },
on<atom("get_state")>() >> [=]() { on<atom("get_state")>() >> [=]() {
reply("wait4string"); reply("wait4string");
...@@ -115,7 +115,7 @@ class event_testee : public sb_actor<event_testee> { ...@@ -115,7 +115,7 @@ class event_testee : public sb_actor<event_testee> {
wait4float = ( wait4float = (
on<float>() >> [=]() { on<float>() >> [=]() {
become(&wait4string); become(wait4string);
}, },
on<atom("get_state")>() >> [=]() { on<atom("get_state")>() >> [=]() {
reply("wait4float"); reply("wait4float");
...@@ -124,7 +124,7 @@ class event_testee : public sb_actor<event_testee> { ...@@ -124,7 +124,7 @@ class event_testee : public sb_actor<event_testee> {
wait4int = ( wait4int = (
on<int>() >> [=]() { on<int>() >> [=]() {
become(&wait4float); become(wait4float);
}, },
on<atom("get_state")>() >> [=]() { on<atom("get_state")>() >> [=]() {
reply("wait4int"); reply("wait4int");
...@@ -163,7 +163,7 @@ struct chopstick : public sb_actor<chopstick> { ...@@ -163,7 +163,7 @@ struct chopstick : public sb_actor<chopstick> {
reply(atom("busy")); reply(atom("busy"));
}, },
on(atom("put"), hakker) >> [=]() { on(atom("put"), hakker) >> [=]() {
become(&init_state); become(init_state);
}, },
on(atom("break")) >> [=]() { on(atom("break")) >> [=]() {
quit(); quit();
...@@ -316,7 +316,7 @@ class fixed_stack : public sb_actor<fixed_stack> { ...@@ -316,7 +316,7 @@ class fixed_stack : public sb_actor<fixed_stack> {
on(atom("pop")) >> [=]() { on(atom("pop")) >> [=]() {
reply(atom("ok"), data.back()); reply(atom("ok"), data.back());
data.pop_back(); data.pop_back();
become(&filled); become(filled);
} }
); );
...@@ -324,20 +324,20 @@ class fixed_stack : public sb_actor<fixed_stack> { ...@@ -324,20 +324,20 @@ class fixed_stack : public sb_actor<fixed_stack> {
on(atom("push"), arg_match) >> [=](int what) { on(atom("push"), arg_match) >> [=](int what) {
data.push_back(what); data.push_back(what);
if (data.size() == max_size) if (data.size() == max_size)
become(&full); become(full);
}, },
on(atom("pop")) >> [=]() { on(atom("pop")) >> [=]() {
reply(atom("ok"), data.back()); reply(atom("ok"), data.back());
data.pop_back(); data.pop_back();
if (data.empty()) if (data.empty())
become(&empty); become(empty);
} }
); );
behavior empty = ( behavior empty = (
on(atom("push"), arg_match) >> [=](int what) { on(atom("push"), arg_match) >> [=](int what) {
data.push_back(what); data.push_back(what);
become(&filled); become(filled);
}, },
on(atom("pop")) >> [=]() { on(atom("pop")) >> [=]() {
reply(atom("failure")); reply(atom("failure"));
...@@ -374,7 +374,7 @@ class fixed_stack : public sb_actor<fixed_stack> { ...@@ -374,7 +374,7 @@ class fixed_stack : public sb_actor<fixed_stack> {
on(atom("pop")) >> [=]() { on(atom("pop")) >> [=]() {
reply(atom("ok"), data.back()); reply(atom("ok"), data.back());
data.pop_back(); data.pop_back();
become(&filled); become(filled);
} }
); );
...@@ -382,20 +382,20 @@ class fixed_stack : public sb_actor<fixed_stack> { ...@@ -382,20 +382,20 @@ class fixed_stack : public sb_actor<fixed_stack> {
on(atom("push"), arg_match) >> [=](int what) { on(atom("push"), arg_match) >> [=](int what) {
data.push_back(what); data.push_back(what);
if (data.size() == max_size) if (data.size() == max_size)
become(&full); become(full);
}, },
on(atom("pop")) >> [=]() { on(atom("pop")) >> [=]() {
reply(atom("ok"), data.back()); reply(atom("ok"), data.back());
data.pop_back(); data.pop_back();
if (data.empty()) if (data.empty())
become(&empty); become(empty);
} }
); );
empty = ( empty = (
on(atom("push"), arg_match) >> [=](int what) { on(atom("push"), arg_match) >> [=](int what) {
data.push_back(what); data.push_back(what);
become(&filled); become(filled);
}, },
on(atom("pop")) >> [=]() { on(atom("pop")) >> [=]() {
reply(atom("failure")); reply(atom("failure"));
......
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