Permalink
Browse files

event-based actor factory

  • Loading branch information...
1 parent 85a4fc8 commit d90fc07876d602e28feb8e70c23cd3ba684ecb75 @Neverlord Neverlord committed Jun 25, 2012
View
@@ -27,6 +27,7 @@ set(LIBCPPA_SRC
src/empty_tuple.cpp
src/event_based_actor.cpp
src/exception.cpp
+ src/factory.cpp
src/fiber.cpp
src/group.cpp
src/group_manager.cpp
View
@@ -262,3 +262,6 @@ cppa/detail/receive_policy.hpp
cppa/detail/behavior_stack.hpp
src/behavior_stack.cpp
cppa/detail/stacked_actor_mixin.hpp
+cppa/detail/event_based_actor_factory.hpp
+cppa/factory.hpp
+src/factory.cpp
View
@@ -40,18 +40,19 @@
#include "cppa/on.hpp"
#include "cppa/atom.hpp"
#include "cppa/self.hpp"
-#include "cppa/cow_tuple.hpp"
#include "cppa/actor.hpp"
#include "cppa/channel.hpp"
#include "cppa/receive.hpp"
+#include "cppa/factory.hpp"
#include "cppa/behavior.hpp"
#include "cppa/announce.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/to_string.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/fsm_actor.hpp"
-#include "cppa/local_actor.hpp"
+#include "cppa/cow_tuple.hpp"
#include "cppa/exit_reason.hpp"
+#include "cppa/local_actor.hpp"
#include "cppa/scheduled_actor.hpp"
#include "cppa/scheduling_hint.hpp"
#include "cppa/event_based_actor.hpp"
@@ -123,17 +124,24 @@
* features.
*
* @namespace cppa
- * @brief This is the root namespace of libcppa.
- *
- * Thie @b cppa namespace contains all functions and classes to
- * implement Actor based applications.
+ * @brief Root namespace of libcppa.
*
* @namespace cppa::util
- * @brief This namespace contains utility classes and metaprogramming
+ * @brief Contains utility classes and metaprogramming
* utilities used by the libcppa implementation.
*
* @namespace cppa::intrusive
- * @brief This namespace contains intrusive container implementations.
+ * @brief Contains intrusive container implementations.
+ *
+ * @namespace cppa::factory
+ * @brief Contains factory functions to create actors from lambdas or
+ * other functors.
+ *
+ * @namespace cppa::exit_reason
+ * @brief Contains all predefined exit reasons.
+ *
+ * @namespace cppa::placeholders
+ * @brief Contains the guard placeholders @p _x1 to @p _x9.
*
* @defgroup CopyOnWrite Copy-on-write optimization.
* @p libcppa uses a copy-on-write optimization for its message
@@ -246,16 +254,13 @@
* to define patterns:
*
* @code
- * receive
- * (
- * on(atom("hello"), val<std::string>()) >> [](const std::string& msg)
- * {
+ * receive (
+ * on(atom("hello"), val<std::string>()) >> [](const std::string& msg) {
* cout << "received hello message: " << msg << endl;
* },
- * on(atom("compute"), val<int>(), val<int>(), val<int>()>() >> [](int i0, int i1, int i2)
- * {
+ * on(atom("compute"), val<int>(), val<int>()>() >> [](int i0, int i1) {
* // send our result back to the sender of this messages
- * reply(atom("result"), i0 + i1 + i2);
+ * reply(atom("result"), i0 + i1);
* }
* );
* @endcode
@@ -270,16 +275,12 @@
*
* Example actor:
* @code
- * void math_actor()
- * {
- * receive_loop
- * (
- * on<atom("plus"), int, int>() >> [](int a, int b)
- * {
+ * void math_actor() {
+ * receive_loop (
+ * on<atom("plus"), int, int>() >> [](int a, int b) {
* reply(atom("result"), a + b);
* },
- * on<atom("minus"), int, int>() >> [](int a, int b)
- * {
+ * on<atom("minus"), int, int>() >> [](int a, int b) {
* reply(atom("result"), a - b);
* }
* );
@@ -307,10 +308,8 @@
* @code
* // receive two integers
* vector<int> received_values;
- * receive_while([&]() { return received_values.size() < 2; })
- * (
- * on<int>() >> [](int value)
- * {
+ * receive_while([&]() { return received_values.size() < 2; }) (
+ * on<int>() >> [](int value) {
* received_values.push_back(value);
* }
* );
@@ -322,8 +321,7 @@
* @code
* std::vector<int> vec {1, 2, 3, 4};
* auto i = vec.begin();
- * receive_for(i, vec.end())
- * (
+ * receive_for(i, vec.end()) (
* on(atom("get")) >> [&]() { reply(atom("result"), *i); }
* );
* @endcode
@@ -335,10 +333,8 @@
* @code
* // receive ints until zero was received
* vector<int> received_values;
- * do_receive
- * (
- * on<int>() >> [](int value)
- * {
+ * do_receive (
+ * on<int>() >> [](int value) {
* received_values.push_back(value);
* }
* )
@@ -354,11 +350,9 @@
*
* @code
* delayed_send(self, std::chrono::seconds(1), atom("poll"));
- * receive_loop
- * (
+ * receive_loop (
* // ...
- * on<atom("poll")>() >> []()
- * {
+ * on<atom("poll")>() >> []() {
* // ... poll something ...
* // and do it again after 1sec
* delayed_send(self, std::chrono::seconds(1), atom("poll"));
@@ -392,8 +386,7 @@
* // x has the type cppa::tuple<std::string, std::string>
* auto x = make_cow_tuple("hello", "tuple");
*
- * receive
- * (
+ * receive (
* // equal to: on(std::string("hello actor!"))
* on("hello actor!") >> []() { }
* );
@@ -486,9 +479,11 @@ struct spawn_fwd_<self_type> {
*/
template<scheduling_hint Hint, typename F, typename Arg0, typename... Args>
inline actor_ptr spawn(F bhvr, Arg0&& arg0, Args&&... args) {
- return spawn<Hint>(std::bind(std::move(bhvr),
- spawn_fwd_<typename util::rm_ref<Arg0>::type>::_(arg0),
- spawn_fwd_<typename util::rm_ref<Args>::type>::_(args)...));
+ return spawn<Hint>(
+ std::bind(
+ std::move(bhvr),
+ spawn_fwd_<typename util::rm_ref<Arg0>::type>::_(arg0),
+ spawn_fwd_<typename util::rm_ref<Args>::type>::_(args)...));
}
/**
@@ -0,0 +1,142 @@
+/******************************************************************************\
+ * ___ __ *
+ * /\_ \ __/\ \ *
+ * \//\ \ /\_\ \ \____ ___ _____ _____ __ *
+ * \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
+ * \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
+ * /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
+ * \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
+ * \ \_\ \ \_\ *
+ * \/_/ \/_/ *
+ * *
+ * Copyright (C) 2011, 2012 *
+ * 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 3 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_EVENT_BASED_ACTOR_FACTORY_HPP
+#define CPPA_EVENT_BASED_ACTOR_FACTORY_HPP
+
+#include <type_traits>
+
+#include "cppa/scheduler.hpp"
+#include "cppa/event_based_actor.hpp"
+
+#include "cppa/detail/tdata.hpp"
+#include "cppa/util/type_list.hpp"
+
+namespace cppa { namespace detail {
+
+template<typename InitFun, typename CleanupFun, typename... Members>
+class event_based_actor_impl : public event_based_actor {
+
+ public:
+
+ template<typename... Args>
+ event_based_actor_impl(InitFun fun, CleanupFun cfun, Args&&... args)
+ : m_init(std::move(fun)), m_on_exit(std::move(cfun))
+ , m_members(std::forward<Args>(args)...) { }
+
+ void init() { apply(m_init); }
+
+ void on_exit() {
+ typedef typename util::get_arg_types<CleanupFun>::types arg_types;
+ std::integral_constant<size_t, arg_types::size> token;
+ on_exit_impl(m_on_exit, token);
+ }
+
+ private:
+
+ InitFun m_init;
+ CleanupFun m_on_exit;
+ tdata<Members...> m_members;
+
+ template<typename F>
+ void apply(F& f, typename std::add_pointer<Members>::type... args) {
+ f(args...);
+ }
+
+ template<typename F, typename... Args>
+ void apply(F& f, Args... args) {
+ apply(f, args..., &get_ref<sizeof...(Args)>(m_members));
+ }
+
+ typedef std::integral_constant<size_t, 0> zero_t;
+
+ template<typename OnExit, typename Token>
+ typename std::enable_if<std::is_same<Token, zero_t>::value>::type
+ on_exit_impl(OnExit& fun, Token) {
+ fun();
+ }
+
+ template<typename OnExit, typename Token>
+ typename std::enable_if<std::is_same<Token, zero_t>::value == false>::type
+ on_exit_impl(OnExit& fun, Token) {
+ apply(fun);
+ }
+
+};
+
+template<typename InitFun, typename CleanupFun, typename... Members>
+class event_based_actor_factory {
+
+ public:
+
+ typedef event_based_actor_impl<InitFun, CleanupFun, Members...> impl;
+
+ event_based_actor_factory(InitFun fun, CleanupFun cfun)
+ : m_init(std::move(fun)), m_on_exit(std::move(cfun)) { }
+
+ template<typename... Args>
+ actor_ptr spawn(Args&&... args) {
+ return get_scheduler()->spawn(new impl(m_init, m_on_exit,
+ std::forward<Args>(args)...));
+ }
+
+ private:
+
+ InitFun m_init;
+ CleanupFun m_on_exit;
+
+};
+
+// event-based actor factory from type list
+template<typename InitFun, typename CleanupFun, class TypeList>
+struct ebaf_from_type_list;
+
+template<typename InitFun, typename CleanupFun, typename... Ts>
+struct ebaf_from_type_list<InitFun, CleanupFun, util::type_list<Ts...> > {
+ typedef event_based_actor_factory<InitFun, CleanupFun, Ts...> type;
+};
+
+template<typename Init, typename Cleanup>
+struct ebaf_from_functor {
+ typedef typename util::get_arg_types<Init>::types arg_types;
+ typedef typename util::get_arg_types<Cleanup>::types arg_types2;
+ static_assert(util::tl_forall<arg_types, std::is_pointer>::value,
+ "First functor takes non-pointer arguments");
+ static_assert( std::is_same<arg_types, arg_types2>::value
+ || std::is_same<util::type_list<>, arg_types2>::value,
+ "Second functor must provide either the same signature "
+ " as the first one or must take zero arguments");
+ typedef typename util::tl_map<arg_types, std::remove_pointer>::type mems;
+ typedef typename ebaf_from_type_list<Init, Cleanup, mems>::type type;
+};
+
+} } // namespace cppa::detail
+
+#endif // CPPA_EVENT_BASED_ACTOR_FACTORY_HPP
@@ -48,6 +48,7 @@ struct scheduled_actor_dummy : abstract_scheduled_actor {
bool attach(attachable*);
void unbecome();
void do_become(behavior*, bool, bool);
+ bool has_behavior();
};
} } // namespace cppa::detail
@@ -92,6 +92,12 @@ class stacked_actor_mixin : public Base {
}
}
+ virtual bool has_behavior() {
+ return static_cast<bool>(m_behavior)
+ || ( static_cast<bool>(m_bhvr_stack_ptr)
+ && m_bhvr_stack_ptr->empty() == false);
+ }
+
private:
std::function<void()> m_behavior;
@@ -67,8 +67,7 @@ class thread_pool_scheduler : public scheduler {
scheduled_actor_dummy m_dummy;
std::thread m_supervisor;
- actor_ptr spawn_impl(scheduled_actor* what,
- bool push_to_queue = true);
+ actor_ptr spawn_impl(scheduled_actor_ptr what, bool push_to_queue = true);
static void worker_loop(worker*);
static void supervisor_loop(job_queue*, scheduled_actor*);
@@ -86,6 +86,10 @@ class event_based_actor : public detail::abstract_scheduled_actor {
event_based_actor();
+ bool has_behavior() {
+ return m_bhvr_stack.empty() == false;
+ }
+
// provoke compiler errors for usage of receive() and related functions
/**
View
@@ -33,11 +33,6 @@
#include <cstdint>
-/**
- * @namespace cppa::exit_reason
- * @brief This naemspace contains all predefined exit reasons.
- */
-
namespace cppa { namespace exit_reason {
/**
Oops, something went wrong.

0 comments on commit d90fc07

Please sign in to comment.