Commit 05d61a8d authored by Dominik Charousset's avatar Dominik Charousset

allow event-based actors to become detached

this patch extends the `spawn` function to allow `spawn<Impl,blocking_api>(...)`
and thereby allow users to detach event-based actors using a class;
this patch also removes some unneeded headers, renames
`detail::recursive_queue_node` to `mailbox_element`, combines the two classes
`ge_reference_wrapper` and `ge_mutable_reference_wrapper` to simply
`rebindable_reference`, and does some maintenance and documentation
parent 48a29c72
...@@ -124,6 +124,7 @@ set(LIBCPPA_SRC ...@@ -124,6 +124,7 @@ set(LIBCPPA_SRC
src/ipv4_io_stream.cpp src/ipv4_io_stream.cpp
src/local_actor.cpp src/local_actor.cpp
src/logging.cpp src/logging.cpp
src/mailbox_element.cpp
src/match.cpp src/match.cpp
src/memory.cpp src/memory.cpp
src/memory_managed.cpp src/memory_managed.cpp
...@@ -137,7 +138,6 @@ set(LIBCPPA_SRC ...@@ -137,7 +138,6 @@ set(LIBCPPA_SRC
src/primitive_variant.cpp src/primitive_variant.cpp
src/process_information.cpp src/process_information.cpp
src/protocol.cpp src/protocol.cpp
src/recursive_queue_node.cpp
src/ref_counted.cpp src/ref_counted.cpp
src/response_handle.cpp src/response_handle.cpp
src/ripemd_160.cpp src/ripemd_160.cpp
......
...@@ -24,7 +24,6 @@ cppa/detail/atom_val.hpp ...@@ -24,7 +24,6 @@ cppa/detail/atom_val.hpp
cppa/detail/behavior_impl.hpp cppa/detail/behavior_impl.hpp
cppa/detail/behavior_stack.hpp cppa/detail/behavior_stack.hpp
cppa/detail/boxed.hpp cppa/detail/boxed.hpp
cppa/detail/channel.hpp
cppa/detail/container_tuple_view.hpp cppa/detail/container_tuple_view.hpp
cppa/detail/decorated_names_map.hpp cppa/detail/decorated_names_map.hpp
cppa/detail/decorated_tuple.hpp cppa/detail/decorated_tuple.hpp
...@@ -48,7 +47,8 @@ cppa/detail/pseudo_tuple.hpp ...@@ -48,7 +47,8 @@ cppa/detail/pseudo_tuple.hpp
cppa/detail/ptype_to_type.hpp cppa/detail/ptype_to_type.hpp
cppa/detail/receive_loop_helper.hpp cppa/detail/receive_loop_helper.hpp
cppa/detail/receive_policy.hpp cppa/detail/receive_policy.hpp
cppa/detail/recursive_queue_node.hpp cppa/mailbox_element.hpp
cppa/mailbox_based.hpp
cppa/detail/scheduled_actor_dummy.hpp cppa/detail/scheduled_actor_dummy.hpp
cppa/detail/serialize_tuple.hpp cppa/detail/serialize_tuple.hpp
cppa/detail/singleton_manager.hpp cppa/detail/singleton_manager.hpp
...@@ -68,7 +68,6 @@ cppa/detail/unboxed.hpp ...@@ -68,7 +68,6 @@ cppa/detail/unboxed.hpp
cppa/detail/uniform_type_info_map.hpp cppa/detail/uniform_type_info_map.hpp
cppa/detail/value_guard.hpp cppa/detail/value_guard.hpp
cppa/detail/yield_interface.hpp cppa/detail/yield_interface.hpp
cppa/either.hpp
cppa/enable_weak_ptr.hpp cppa/enable_weak_ptr.hpp
cppa/event_based_actor.hpp cppa/event_based_actor.hpp
cppa/exception.hpp cppa/exception.hpp
...@@ -144,7 +143,6 @@ cppa/util/duration.hpp ...@@ -144,7 +143,6 @@ cppa/util/duration.hpp
cppa/util/element_at.hpp cppa/util/element_at.hpp
cppa/util/fiber.hpp cppa/util/fiber.hpp
cppa/util/fixed_vector.hpp cppa/util/fixed_vector.hpp
cppa/util/if_else.hpp
cppa/util/int_list.hpp cppa/util/int_list.hpp
cppa/util/is_array_of.hpp cppa/util/is_array_of.hpp
cppa/util/is_builtin.hpp cppa/util/is_builtin.hpp
...@@ -167,7 +165,6 @@ cppa/util/rm_ref.hpp ...@@ -167,7 +165,6 @@ cppa/util/rm_ref.hpp
cppa/util/scope_guard.hpp cppa/util/scope_guard.hpp
cppa/util/shared_lock_guard.hpp cppa/util/shared_lock_guard.hpp
cppa/util/shared_spinlock.hpp cppa/util/shared_spinlock.hpp
cppa/util/static_foreach.hpp
cppa/util/tbind.hpp cppa/util/tbind.hpp
cppa/util/type_list.hpp cppa/util/type_list.hpp
cppa/util/type_pair.hpp cppa/util/type_pair.hpp
...@@ -243,7 +240,7 @@ src/partial_function.cpp ...@@ -243,7 +240,7 @@ src/partial_function.cpp
src/primitive_variant.cpp src/primitive_variant.cpp
src/process_information.cpp src/process_information.cpp
src/protocol.cpp src/protocol.cpp
src/recursive_queue_node.cpp src/mailbox_element.cpp
src/ref_counted.cpp src/ref_counted.cpp
src/response_handle.cpp src/response_handle.cpp
src/ripemd_160.cpp src/ripemd_160.cpp
...@@ -289,3 +286,8 @@ cppa/extend.hpp ...@@ -289,3 +286,8 @@ cppa/extend.hpp
cppa/detail/sync_request_bouncer.hpp cppa/detail/sync_request_bouncer.hpp
cppa/memory_cached.hpp cppa/memory_cached.hpp
cppa/singletons.hpp cppa/singletons.hpp
cppa/threaded.hpp
cppa/util/dptr.hpp
cppa/util/is_callable.hpp
cppa/util/get_result_type.hpp
cppa/util/rebindable_reference.hpp
...@@ -110,7 +110,7 @@ class actor : public channel { ...@@ -110,7 +110,7 @@ class actor : public channel {
* otherwise (actor already exited) @p false. * otherwise (actor already exited) @p false.
* @warning The actor takes ownership of @p ptr. * @warning The actor takes ownership of @p ptr.
*/ */
virtual bool attach(attachable_ptr ptr); bool attach(attachable_ptr ptr);
/** /**
* @brief Convenience function that attaches the functor * @brief Convenience function that attaches the functor
...@@ -129,7 +129,7 @@ class actor : public channel { ...@@ -129,7 +129,7 @@ class actor : public channel {
/** /**
* @brief Detaches the first attached object that matches @p what. * @brief Detaches the first attached object that matches @p what.
*/ */
virtual void detach(const attachable::token& what); void detach(const attachable::token& what);
/** /**
* @brief Links this actor to @p other. * @brief Links this actor to @p other.
......
...@@ -59,10 +59,10 @@ class actor_companion_mixin : public Base { ...@@ -59,10 +59,10 @@ class actor_companion_mixin : public Base {
public: public:
typedef std::unique_ptr<detail::recursive_queue_node,detail::disposer> message_pointer; typedef std::unique_ptr<mailbox_element,detail::disposer> message_pointer;
template<typename... Args> template<typename... Ts>
actor_companion_mixin(Args&&... args) : super(std::forward<Args>(args)...) { actor_companion_mixin(Ts&&... args) : super(std::forward<Ts>(args)...) {
m_self.reset(detail::memory::create<companion>(this)); m_self.reset(detail::memory::create<companion>(this));
} }
...@@ -89,9 +89,9 @@ class actor_companion_mixin : public Base { ...@@ -89,9 +89,9 @@ class actor_companion_mixin : public Base {
* @note While the message handler is invoked, @p self will point * @note While the message handler is invoked, @p self will point
* to the companion object to enable send() and reply(). * to the companion object to enable send() and reply().
*/ */
template<typename... Args> template<typename... Ts>
void set_message_handler(Args&&... matchExpressions) { void set_message_handler(Ts&&... args) {
m_message_handler = match_expr_convert(std::forward<Args>(matchExpressions)...); m_message_handler = match_expr_convert(std::forward<Ts>(args)...);
} }
/** /**
...@@ -112,8 +112,8 @@ class actor_companion_mixin : public Base { ...@@ -112,8 +112,8 @@ class actor_companion_mixin : public Base {
class companion : public local_actor { class companion : public local_actor {
friend class actor_companion_mixin; friend class actor_companion_mixin;
typedef util::shared_spinlock lock_type; typedef util::shared_spinlock lock_type;
typedef std::unique_ptr<detail::recursive_queue_node,detail::disposer> node_ptr;
public: public:
...@@ -129,26 +129,22 @@ class actor_companion_mixin : public Base { ...@@ -129,26 +129,22 @@ class actor_companion_mixin : public Base {
void enqueue(const actor_ptr& sender, any_tuple msg) { void enqueue(const actor_ptr& sender, any_tuple msg) {
util::shared_lock_guard<lock_type> guard(m_lock); util::shared_lock_guard<lock_type> guard(m_lock);
if (m_parent) { if (m_parent) push_message(sender, std::move(msg));
m_parent->new_message(new_node_ptr(sender, std::move(msg)));
}
} }
void sync_enqueue(const actor_ptr& sender, void sync_enqueue(const actor_ptr& sender,
message_id id, message_id id,
any_tuple msg) { any_tuple msg) {
util::shared_lock_guard<lock_type> guard(m_lock); util::shared_lock_guard<lock_type> guard(m_lock);
if (m_parent) { if (m_parent) push_message(sender, std::move(msg), id);
m_parent->new_message(new_node_ptr(sender, std::move(msg), id));
}
} }
bool initialized() const { return true; } bool initialized() const { return true; }
void quit(std::uint32_t) { void quit(std::uint32_t) {
throw std::runtime_error("ActorWidgetMixin::Gateway::exit " throw std::runtime_error("Using actor_companion_mixin::quit "
"is forbidden, use Qt's widget " "is prohibited; use Qt's widget "
"management instead!"); "management instead.");
} }
void dequeue(behavior&) { void dequeue(behavior&) {
...@@ -169,9 +165,11 @@ class actor_companion_mixin : public Base { ...@@ -169,9 +165,11 @@ class actor_companion_mixin : public Base {
private: private:
template<typename... Args> template<typename... Ts>
node_ptr new_node_ptr(Args&&... args) { void push_message(Ts&&... args) {
return node_ptr(detail::memory::create<detail::recursive_queue_node>(std::forward<Args>(args)...)); message_pointer ptr;
ptr.reset(detail::memory::create<mailbox_element>(std::forward<Ts>(args)...));
m_parent->new_message(std::move(ptr));
} }
void throw_no_become() { void throw_no_become() {
...@@ -186,12 +184,18 @@ class actor_companion_mixin : public Base { ...@@ -186,12 +184,18 @@ class actor_companion_mixin : public Base {
"receive() API"); "receive() API");
} }
// guards access to m_parent
lock_type m_lock; lock_type m_lock;
// set to nullptr if this companion became detached
actor_companion_mixin* m_parent; actor_companion_mixin* m_parent;
}; };
// used as 'self' before calling message handler
intrusive_ptr<companion> m_self; intrusive_ptr<companion> m_self;
// user-defined message handler for incoming messages
partial_function m_message_handler; partial_function m_message_handler;
}; };
......
...@@ -46,7 +46,7 @@ class actor_proxy_cache; ...@@ -46,7 +46,7 @@ class actor_proxy_cache;
* @brief Represents a remote actor. * @brief Represents a remote actor.
* @extends actor * @extends actor
*/ */
class actor_proxy : public extend<actor,actor_proxy>::with<enable_weak_ptr> { class actor_proxy : public extend<actor>::with<enable_weak_ptr> {
typedef combined_type super; typedef combined_type super;
......
...@@ -108,9 +108,9 @@ bool announce(const std::type_info& tinfo, uniform_type_info* utype); ...@@ -108,9 +108,9 @@ bool announce(const std::type_info& tinfo, uniform_type_info* utype);
* @see {@link announce_4.cpp announce example 4} * @see {@link announce_4.cpp announce example 4}
* @returns A pair of @p c_ptr and the created meta informations. * @returns A pair of @p c_ptr and the created meta informations.
*/ */
template<class C, class Parent, typename... Args> template<class C, class Parent, typename... Ts>
std::pair<C Parent::*, util::abstract_uniform_type_info<C>*> std::pair<C Parent::*, util::abstract_uniform_type_info<C>*>
compound_member(C Parent::*c_ptr, const Args&... args) { compound_member(C Parent::*c_ptr, const Ts&... args) {
return {c_ptr, new detail::default_uniform_type_info_impl<C>(args...)}; return {c_ptr, new detail::default_uniform_type_info_impl<C>(args...)};
} }
...@@ -123,9 +123,9 @@ compound_member(C Parent::*c_ptr, const Args&... args) { ...@@ -123,9 +123,9 @@ compound_member(C Parent::*c_ptr, const Args&... args) {
* @see {@link announce_4.cpp announce example 4} * @see {@link announce_4.cpp announce example 4}
* @returns A pair of @p c_ptr and the created meta informations. * @returns A pair of @p c_ptr and the created meta informations.
*/ */
template<class C, class Parent, typename... Args> template<class C, class Parent, typename... Ts>
std::pair<C& (Parent::*)(), util::abstract_uniform_type_info<C>*> std::pair<C& (Parent::*)(), util::abstract_uniform_type_info<C>*>
compound_member(C& (Parent::*getter)(), const Args&... args) { compound_member(C& (Parent::*getter)(), const Ts&... args) {
return {getter, new detail::default_uniform_type_info_impl<C>(args...)}; return {getter, new detail::default_uniform_type_info_impl<C>(args...)};
} }
...@@ -140,12 +140,12 @@ compound_member(C& (Parent::*getter)(), const Args&... args) { ...@@ -140,12 +140,12 @@ compound_member(C& (Parent::*getter)(), const Args&... args) {
* @returns A pair of @p c_ptr and the created meta informations. * @returns A pair of @p c_ptr and the created meta informations.
*/ */
template<class Parent, typename GRes, template<class Parent, typename GRes,
typename SRes, typename SArg, typename... Args> typename SRes, typename SArg, typename... Ts>
std::pair<std::pair<GRes (Parent::*)() const, SRes (Parent::*)(SArg)>, std::pair<std::pair<GRes (Parent::*)() const, SRes (Parent::*)(SArg)>,
util::abstract_uniform_type_info<typename util::rm_ref<GRes>::type>*> util::abstract_uniform_type_info<typename util::rm_ref<GRes>::type>*>
compound_member(const std::pair<GRes (Parent::*)() const, compound_member(const std::pair<GRes (Parent::*)() const,
SRes (Parent::*)(SArg) >& gspair, SRes (Parent::*)(SArg) >& gspair,
const Args&... args) { const Ts&... args) {
typedef typename util::rm_ref<GRes>::type mtype; typedef typename util::rm_ref<GRes>::type mtype;
return {gspair, new detail::default_uniform_type_info_impl<mtype>(args...)}; return {gspair, new detail::default_uniform_type_info_impl<mtype>(args...)};
} }
...@@ -157,10 +157,9 @@ compound_member(const std::pair<GRes (Parent::*)() const, ...@@ -157,10 +157,9 @@ compound_member(const std::pair<GRes (Parent::*)() const,
* @returns @c true if @p T was added to the libcppa type system, * @returns @c true if @p T was added to the libcppa type system,
* @c false otherwise. * @c false otherwise.
*/ */
template<typename T, typename... Args> template<typename T, typename... Ts>
inline bool announce(const Args&... args) { inline bool announce(const Ts&... args) {
return announce(typeid(T), return announce(typeid(T), new detail::default_uniform_type_info_impl<T>(args...));
new detail::default_uniform_type_info_impl<T>(args...));
} }
/** /**
......
...@@ -74,14 +74,14 @@ class any_tuple { ...@@ -74,14 +74,14 @@ class any_tuple {
/** /**
* @brief Creates a tuple from @p t. * @brief Creates a tuple from @p t.
*/ */
template<typename... Args> template<typename... Ts>
any_tuple(const cow_tuple<Args...>& t) : m_vals(t.vals()) { } any_tuple(const cow_tuple<Ts...>& arg) : m_vals(arg.vals()) { }
/** /**
* @brief Creates a tuple and moves the content from @p t. * @brief Creates a tuple and moves the content from @p t.
*/ */
template<typename... Args> template<typename... Ts>
any_tuple(cow_tuple<Args...>&& t) : m_vals(std::move(t.m_vals)) { } any_tuple(cow_tuple<Ts...>&& arg) : m_vals(std::move(arg.m_vals)) { }
/** /**
* @brief Move constructor. * @brief Move constructor.
...@@ -181,10 +181,13 @@ class any_tuple { ...@@ -181,10 +181,13 @@ class any_tuple {
inline const std::type_info* type_token() const; inline const std::type_info* type_token() const;
/** /**
* @brief Checks whether this * @brief Checks whether this tuple is dynamically typed, i.e.,
* its types were not known during compile time.
*/ */
inline bool dynamically_typed() const; inline bool dynamically_typed() const;
/** @cond PRIVATE */
template<typename T> template<typename T>
static inline any_tuple view(T&& value); static inline any_tuple view(T&& value);
...@@ -194,6 +197,8 @@ class any_tuple { ...@@ -194,6 +197,8 @@ class any_tuple {
explicit any_tuple(detail::abstract_tuple*); explicit any_tuple(detail::abstract_tuple*);
/** @endcond */
private: private:
data_ptr m_vals; data_ptr m_vals;
...@@ -244,9 +249,9 @@ inline bool operator!=(const any_tuple& lhs, const any_tuple& rhs) { ...@@ -244,9 +249,9 @@ inline bool operator!=(const any_tuple& lhs, const any_tuple& rhs) {
* @brief Creates an {@link any_tuple} containing the elements @p args. * @brief Creates an {@link any_tuple} containing the elements @p args.
* @param args Values to initialize the tuple elements. * @param args Values to initialize the tuple elements.
*/ */
template<typename... Args> template<typename... Ts>
inline any_tuple make_any_tuple(Args&&... args) { inline any_tuple make_any_tuple(Ts&&... args) {
return make_cow_tuple(std::forward<Args>(args)...); return make_cow_tuple(std::forward<Ts>(args)...);
} }
/****************************************************************************** /******************************************************************************
......
...@@ -40,7 +40,11 @@ namespace cppa { ...@@ -40,7 +40,11 @@ namespace cppa {
/** /**
* @brief The value type of atoms. * @brief The value type of atoms.
*/ */
enum class atom_value : std::uint64_t { dirty_little_hack = 37337 }; enum class atom_value : std::uint64_t {
/** @cond PRIVATE */
dirty_little_hack = 37337
/** @endcond */
};
/** /**
* @brief Returns @p what as a string representation. * @brief Returns @p what as a string representation.
......
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
#include "cppa/util/tbind.hpp" #include "cppa/util/tbind.hpp"
#include "cppa/util/rm_ref.hpp" #include "cppa/util/rm_ref.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <stack> #include <stack>
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/either.hpp"
#include "cppa/extend.hpp" #include "cppa/extend.hpp"
#include "cppa/stacked.hpp" #include "cppa/stacked.hpp"
#include "cppa/scheduled_actor.hpp" #include "cppa/scheduled_actor.hpp"
...@@ -64,22 +63,22 @@ class context_switching_actor : public extend<scheduled_actor,context_switching_ ...@@ -64,22 +63,22 @@ class context_switching_actor : public extend<scheduled_actor,context_switching_
*/ */
context_switching_actor(std::function<void()> fun); context_switching_actor(std::function<void()> fun);
resume_result resume(util::fiber* from, actor_ptr& next_job); //override resume_result resume(util::fiber* from, actor_ptr& next_job);
scheduled_actor_type impl_type(); scheduled_actor_type impl_type();
protected: protected:
typedef std::chrono::high_resolution_clock::time_point timeout_type;
timeout_type init_timeout(const util::duration& rel_time); timeout_type init_timeout(const util::duration& rel_time);
detail::recursive_queue_node* await_message(); mailbox_element* await_message();
detail::recursive_queue_node* await_message(const timeout_type& abs_time); mailbox_element* await_message(const timeout_type& abs_time);
private: private:
detail::recursive_queue_node* receive_node();
// required by util::fiber // required by util::fiber
static void trampoline(void* _this); static void trampoline(void* _this);
......
...@@ -86,6 +86,7 @@ class cow_tuple<Head, Tail...> { ...@@ -86,6 +86,7 @@ class cow_tuple<Head, Tail...> {
public: public:
typedef util::type_list<Head, Tail...> types; typedef util::type_list<Head, Tail...> types;
typedef cow_ptr<detail::abstract_tuple> cow_ptr_type; typedef cow_ptr<detail::abstract_tuple> cow_ptr_type;
static constexpr size_t num_elements = sizeof...(Tail) + 1; static constexpr size_t num_elements = sizeof...(Tail) + 1;
...@@ -96,33 +97,24 @@ class cow_tuple<Head, Tail...> { ...@@ -96,33 +97,24 @@ class cow_tuple<Head, Tail...> {
* @brief Initializes the cow_tuple with @p args. * @brief Initializes the cow_tuple with @p args.
* @param args Initialization values. * @param args Initialization values.
*/ */
template<typename... Args> template<typename... Ts>
cow_tuple(const Head& arg0, Args&&... args) cow_tuple(const Head& arg, Ts&&... args)
: m_vals(new data_type(arg0, std::forward<Args>(args)...)) { } : m_vals(new data_type(arg, std::forward<Ts>(args)...)) { }
/** /**
* @brief Initializes the cow_tuple with @p args. * @brief Initializes the cow_tuple with @p args.
* @param args Initialization values. * @param args Initialization values.
*/ */
template<typename... Args> template<typename... Ts>
cow_tuple(Head&& arg0, Args&&... args) cow_tuple(Head&& arg, Ts&&... args)
: m_vals(new data_type(std::move(arg0), std::forward<Args>(args)...)) { } : m_vals(new data_type(std::move(arg), std::forward<Ts>(args)...)) { }
cow_tuple(cow_tuple&&) = default; cow_tuple(cow_tuple&&) = default;
cow_tuple(const cow_tuple&) = default; cow_tuple(const cow_tuple&) = default;
cow_tuple& operator=(cow_tuple&&) = default; cow_tuple& operator=(cow_tuple&&) = default;
cow_tuple& operator=(const cow_tuple&) = default; cow_tuple& operator=(const cow_tuple&) = default;
inline static cow_tuple from(cow_ptr_type ptr) { static cow_tuple offset_subtuple(cow_ptr_type ptr, size_t offset) {
return {priv_ctor{}, std::move(ptr)};
}
inline static cow_tuple from(cow_ptr_type ptr,
const util::fixed_vector<size_t, num_elements>& mv) {
return {priv_ctor{}, decorated_type::create(std::move(ptr), mv)};
}
inline static cow_tuple offset_subtuple(cow_ptr_type ptr, size_t offset) {
CPPA_REQUIRE(offset > 0); CPPA_REQUIRE(offset > 0);
return {priv_ctor{}, decorated_type::create(std::move(ptr), offset)}; return {priv_ctor{}, decorated_type::create(std::move(ptr), offset)};
} }
...@@ -156,10 +148,23 @@ class cow_tuple<Head, Tail...> { ...@@ -156,10 +148,23 @@ class cow_tuple<Head, Tail...> {
return m_vals->type_at(p); return m_vals->type_at(p);
} }
/** @cond PRIVATE */
static cow_tuple from(cow_ptr_type ptr) {
return {priv_ctor{}, std::move(ptr)};
}
static cow_tuple from(cow_ptr_type ptr,
const util::fixed_vector<size_t, num_elements>& mv) {
return {priv_ctor{}, decorated_type::create(std::move(ptr), mv)};
}
inline const cow_ptr<detail::abstract_tuple>& vals() const { inline const cow_ptr<detail::abstract_tuple>& vals() const {
return m_vals; return m_vals;
} }
/** @endcond */
}; };
template<typename TypeList> template<typename TypeList>
...@@ -206,10 +211,10 @@ typename util::at<N, Ts...>::type& get_ref(cow_tuple<Ts...>& tup) { ...@@ -206,10 +211,10 @@ typename util::at<N, Ts...>::type& get_ref(cow_tuple<Ts...>& tup) {
* @returns A cow_tuple object containing the values @p args. * @returns A cow_tuple object containing the values @p args.
* @relates cow_tuple * @relates cow_tuple
*/ */
template<typename... Args> template<typename... Ts>
cow_tuple<typename detail::strip_and_convert<Args>::type...> cow_tuple<typename detail::strip_and_convert<Ts>::type...>
make_cow_tuple(Args&&... args) { make_cow_tuple(Ts&&... args) {
return {std::forward<Args>(args)...}; return {std::forward<Ts>(args)...};
} }
/** /**
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
#include "cppa/sb_actor.hpp" #include "cppa/sb_actor.hpp"
#include "cppa/threaded.hpp"
#include "cppa/scheduler.hpp" #include "cppa/scheduler.hpp"
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
...@@ -741,7 +742,14 @@ actor_ptr spawn(Ts&&... args) { ...@@ -741,7 +742,14 @@ actor_ptr spawn(Ts&&... args) {
*/ */
template<class Impl, spawn_options Options = no_spawn_options, typename... Ts> template<class Impl, spawn_options Options = no_spawn_options, typename... Ts>
actor_ptr spawn(Ts&&... args) { actor_ptr spawn(Ts&&... args) {
auto rawptr = detail::memory::create<Impl>(std::forward<Ts>(args)...); static_assert(std::is_base_of<event_based_actor,Impl>::value,
"Impl is not a derived type of event_based_actor");
scheduled_actor* rawptr;
if (has_detach_flag(Options)) {
typedef typename extend<Impl>::template with<threaded> derived;
rawptr = detail::memory::create<derived>(std::forward<Ts>(args)...);
}
else rawptr = detail::memory::create<Impl>(std::forward<Ts>(args)...);
return eval_sopts(Options, get_scheduler()->exec(Options, rawptr)); return eval_sopts(Options, get_scheduler()->exec(Options, rawptr));
} }
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/message_id.hpp" #include "cppa/message_id.hpp"
#include "cppa/detail/recursive_queue_node.hpp" #include "cppa/mailbox_element.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -90,7 +90,7 @@ class behavior_stack ...@@ -90,7 +90,7 @@ class behavior_stack
} }
template<class Policy, class Client> template<class Policy, class Client>
bool invoke(Policy& policy, Client* client, recursive_queue_node* node) { bool invoke(Policy& policy, Client* client, mailbox_element* node) {
CPPA_REQUIRE(!empty()); CPPA_REQUIRE(!empty());
CPPA_REQUIRE(client != nullptr); CPPA_REQUIRE(client != nullptr);
CPPA_REQUIRE(node != nullptr); CPPA_REQUIRE(node != nullptr);
...@@ -122,7 +122,7 @@ class behavior_stack ...@@ -122,7 +122,7 @@ class behavior_stack
template<class Policy, class Client> template<class Policy, class Client>
void exec(Policy& policy, Client* client) { void exec(Policy& policy, Client* client) {
while (!empty()) { while (!empty()) {
invoke(policy, client, client->await_message()); invoke(policy, client, policy.fetch_message(client));
cleanup(); cleanup();
} }
} }
......
...@@ -434,44 +434,44 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T ...@@ -434,44 +434,44 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
// terminates recursion // terminates recursion
inline void push_back() { } inline void push_back() { }
template<typename R, class C, typename... Args> template<typename R, class C, typename... Ts>
void push_back(R C::* memptr, Args&&... args) { void push_back(R C::* memptr, Ts&&... args) {
m_members.push_back(new_member_tinfo(memptr)); m_members.push_back(new_member_tinfo(memptr));
push_back(std::forward<Args>(args)...); push_back(std::forward<Ts>(args)...);
} }
// pr.first = member pointer // pr.first = member pointer
// pr.second = meta object to handle pr.first // pr.second = meta object to handle pr.first
template<typename R, class C, typename... Args> template<typename R, class C, typename... Ts>
void push_back(const std::pair<R C::*, util::abstract_uniform_type_info<R>*>& pr, void push_back(const std::pair<R C::*, util::abstract_uniform_type_info<R>*>& pr,
Args&&... args) { Ts&&... args) {
m_members.push_back(new_member_tinfo(pr.first, unique_uti(pr.second))); m_members.push_back(new_member_tinfo(pr.first, unique_uti(pr.second)));
push_back(std::forward<Args>(args)...); push_back(std::forward<Ts>(args)...);
} }
// pr.first = getter / setter pair // pr.first = getter / setter pair
// pr.second = meta object to handle pr.first // pr.second = meta object to handle pr.first
template<typename GRes, typename SRes, typename SArg, typename C, typename... Args> template<typename GRes, typename SRes, typename SArg, typename C, typename... Ts>
void push_back(const std::pair<GRes (C::*)() const, SRes (C::*)(SArg)>& pr, void push_back(const std::pair<GRes (C::*)() const, SRes (C::*)(SArg)>& pr,
Args&&... args) { Ts&&... args) {
m_members.push_back(new_member_tinfo(pr.first, pr.second)); m_members.push_back(new_member_tinfo(pr.first, pr.second));
push_back(std::forward<Args>(args)...); push_back(std::forward<Ts>(args)...);
} }
// pr.first = getter / setter pair // pr.first = getter / setter pair
// pr.second = meta object to handle pr.first // pr.second = meta object to handle pr.first
template<typename GRes, typename SRes, typename SArg, typename C, typename... Args> template<typename GRes, typename SRes, typename SArg, typename C, typename... Ts>
void push_back(const std::pair<std::pair<GRes (C::*)() const, SRes (C::*)(SArg)>, util::abstract_uniform_type_info<typename util::rm_ref<GRes>::type>*>& pr, void push_back(const std::pair<std::pair<GRes (C::*)() const, SRes (C::*)(SArg)>, util::abstract_uniform_type_info<typename util::rm_ref<GRes>::type>*>& pr,
Args&&... args) { Ts&&... args) {
m_members.push_back(new_member_tinfo(pr.first.first, pr.first.second, unique_uti(pr.second))); m_members.push_back(new_member_tinfo(pr.first.first, pr.first.second, unique_uti(pr.second)));
push_back(std::forward<Args>(args)...); push_back(std::forward<Ts>(args)...);
} }
public: public:
template<typename... Args> template<typename... Ts>
default_uniform_type_info_impl(Args&&... args) { default_uniform_type_info_impl(Ts&&... args) {
push_back(std::forward<Args>(args)...); push_back(std::forward<Ts>(args)...);
} }
default_uniform_type_info_impl() { default_uniform_type_info_impl() {
......
...@@ -59,8 +59,8 @@ class empty_tuple : public singleton_mixin<empty_tuple,abstract_tuple> { ...@@ -59,8 +59,8 @@ class empty_tuple : public singleton_mixin<empty_tuple,abstract_tuple> {
empty_tuple(); empty_tuple();
inline void initialize() /*override*/ { ref(); } inline void initialize() { ref(); }
inline void destroy() /*override*/ { deref(); } inline void destroy() { deref(); }
}; };
......
...@@ -47,10 +47,10 @@ class event_based_actor_impl : public event_based_actor { ...@@ -47,10 +47,10 @@ class event_based_actor_impl : public event_based_actor {
public: public:
template<typename... Args> template<typename... Ts>
event_based_actor_impl(InitFun fun, CleanupFun cfun, Args&&... args) event_based_actor_impl(InitFun fun, CleanupFun cfun, Ts&&... args)
: m_init(std::move(fun)), m_on_exit(std::move(cfun)) : m_init(std::move(fun)), m_on_exit(std::move(cfun))
, m_members(std::forward<Args>(args)...) { } , m_members(std::forward<Ts>(args)...) { }
void init() { apply(m_init); } void init() { apply(m_init); }
...@@ -71,9 +71,9 @@ class event_based_actor_impl : public event_based_actor { ...@@ -71,9 +71,9 @@ class event_based_actor_impl : public event_based_actor {
f(args...); f(args...);
} }
template<typename F, typename... Args> template<typename F, typename... Ts>
void apply(F& f, Args... args) { void apply(F& f, Ts... args) {
apply(f, args..., &get_ref<sizeof...(Args)>(m_members)); apply(f, args..., &get_ref<sizeof...(Ts)>(m_members));
} }
typedef std::integral_constant<size_t, 0> zero_t; typedef std::integral_constant<size_t, 0> zero_t;
...@@ -102,11 +102,9 @@ class event_based_actor_factory { ...@@ -102,11 +102,9 @@ class event_based_actor_factory {
event_based_actor_factory(InitFun fun, CleanupFun cfun) event_based_actor_factory(InitFun fun, CleanupFun cfun)
: m_init(std::move(fun)), m_on_exit(std::move(cfun)) { } : m_init(std::move(fun)), m_on_exit(std::move(cfun)) { }
template<typename... Args> template<typename... Ts>
actor_ptr spawn(Args&&... args) { actor_ptr spawn(Ts&&... args) {
auto ptr = memory::create<impl>(m_init, auto ptr = memory::create<impl>(m_init, m_on_exit, std::forward<Ts>(args)...);
m_on_exit,
std::forward<Args>(args)...);
return get_scheduler()->exec(no_spawn_options, ptr); return get_scheduler()->exec(no_spawn_options, ptr);
} }
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
// default: <true, false, F> // default: <true, false, F>
template<bool IsFunctionPtr, bool HasArguments, typename F, typename... Args> template<bool IsFunctionPtr, bool HasArguments, typename F, typename... Ts>
class ftor_behavior : public scheduled_actor { class ftor_behavior : public scheduled_actor {
F m_fun; F m_fun;
...@@ -56,15 +56,15 @@ class ftor_behavior : public scheduled_actor { ...@@ -56,15 +56,15 @@ class ftor_behavior : public scheduled_actor {
}; };
template<typename F, typename... Args> template<typename F, typename... Ts>
class ftor_behavior<true, true, F, Args...> : public scheduled_actor { class ftor_behavior<true, true, F, Ts...> : public scheduled_actor {
static_assert(sizeof...(Args) > 0, "sizeof...(Args) == 0"); static_assert(sizeof...(Ts) > 0, "sizeof...(Ts) == 0");
F m_fun; F m_fun;
typedef typename tdata_from_type_list< typedef typename tdata_from_type_list<
typename util::tl_map<util::type_list<Args...>, typename util::tl_map<util::type_list<Ts...>,
implicit_conversions>::type>::type implicit_conversions>::type>::type
tdata_type; tdata_type;
...@@ -72,7 +72,7 @@ class ftor_behavior<true, true, F, Args...> : public scheduled_actor { ...@@ -72,7 +72,7 @@ class ftor_behavior<true, true, F, Args...> : public scheduled_actor {
public: public:
ftor_behavior(F ptr, const Args&... args) : m_fun(ptr), m_args(args...) { } ftor_behavior(F ptr, const Ts&... args) : m_fun(ptr), m_args(args...) { }
virtual void act() { virtual void act() {
util::apply_args(m_fun, m_args, util::get_indices(m_args)); util::apply_args(m_fun, m_args, util::get_indices(m_args));
...@@ -95,15 +95,15 @@ class ftor_behavior<false, false, F> : public scheduled_actor { ...@@ -95,15 +95,15 @@ class ftor_behavior<false, false, F> : public scheduled_actor {
}; };
template<typename F, typename... Args> template<typename F, typename... Ts>
class ftor_behavior<false, true, F, Args...> : public scheduled_actor { class ftor_behavior<false, true, F, Ts...> : public scheduled_actor {
static_assert(sizeof...(Args) > 0, "sizeof...(Args) == 0"); static_assert(sizeof...(Ts) > 0, "sizeof...(Ts) == 0");
F m_fun; F m_fun;
typedef typename tdata_from_type_list< typedef typename tdata_from_type_list<
typename util::tl_map<util::type_list<Args...>, typename util::tl_map<util::type_list<Ts...>,
implicit_conversions>::type>::type implicit_conversions>::type>::type
tdata_type; tdata_type;
...@@ -111,10 +111,10 @@ class ftor_behavior<false, true, F, Args...> : public scheduled_actor { ...@@ -111,10 +111,10 @@ class ftor_behavior<false, true, F, Args...> : public scheduled_actor {
public: public:
ftor_behavior(const F& f, const Args&... args) : m_fun(f), m_args(args...) { ftor_behavior(const F& f, const Ts&... args) : m_fun(f), m_args(args...) {
} }
ftor_behavior(F&& f,const Args&... args) : m_fun(std::move(f)) ftor_behavior(F&& f,const Ts&... args) : m_fun(std::move(f))
, m_args(args...) { , m_args(args...) {
} }
...@@ -143,31 +143,25 @@ scheduled_actor* get_behavior(std::integral_constant<bool,false>, F&& ftor) { ...@@ -143,31 +143,25 @@ scheduled_actor* get_behavior(std::integral_constant<bool,false>, F&& ftor) {
return new ftor_behavior<false, false, ftype>(std::forward<F>(ftor)); return new ftor_behavior<false, false, ftype>(std::forward<F>(ftor));
} }
template<typename F, typename Arg0, typename... Args> template<typename F, typename T, typename... Ts>
scheduled_actor* get_behavior(std::integral_constant<bool,true>, scheduled_actor* get_behavior(std::true_type, F fptr, const T& arg, const Ts&... args) {
F fptr, static_assert(std::is_convertible<decltype(fptr(arg, args...)), scheduled_actor*>::value == false,
const Arg0& arg0,
const Args&... args) {
static_assert(std::is_convertible<decltype(fptr(arg0, args...)), scheduled_actor*>::value == false,
"Spawning a function returning an actor_behavior? " "Spawning a function returning an actor_behavior? "
"Are you sure that you do not want to spawn the behavior " "Are you sure that you do not want to spawn the behavior "
"returned by that function?"); "returned by that function?");
typedef ftor_behavior<true, true, F, Arg0, Args...> impl; typedef ftor_behavior<true, true, F, T, Ts...> impl;
return new impl(fptr, arg0, args...); return new impl(fptr, arg, args...);
} }
template<typename F, typename Arg0, typename... Args> template<typename F, typename T, typename... Ts>
scheduled_actor* get_behavior(std::integral_constant<bool,false>, scheduled_actor* get_behavior(std::false_type, F ftor, const T& arg, const Ts&... args) {
F ftor, static_assert(std::is_convertible<decltype(ftor(arg, args...)), scheduled_actor*>::value == false,
const Arg0& arg0,
const Args&... args) {
static_assert(std::is_convertible<decltype(ftor(arg0, args...)), scheduled_actor*>::value == false,
"Spawning a functor returning an actor_behavior? " "Spawning a functor returning an actor_behavior? "
"Are you sure that you do not want to spawn the behavior " "Are you sure that you do not want to spawn the behavior "
"returned by that functor?"); "returned by that functor?");
typedef typename util::rm_ref<F>::type ftype; typedef typename util::rm_ref<F>::type ftype;
typedef ftor_behavior<false, true, ftype, Arg0, Args...> impl; typedef ftor_behavior<false, true, ftype, T, Ts...> impl;
return new impl(std::forward<F>(ftor), arg0, args...); return new impl(std::forward<F>(ftor), arg, args...);
} }
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <new> #include <new>
#include <vector> #include <vector>
#include <memory>
#include <utility> #include <utility>
#include <typeinfo> #include <typeinfo>
#include <iostream> #include <iostream>
...@@ -40,6 +41,8 @@ ...@@ -40,6 +41,8 @@
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
namespace cppa { class mailbox_element; }
namespace cppa { namespace detail { namespace cppa { namespace detail {
namespace { namespace {
...@@ -49,8 +52,6 @@ constexpr size_t s_cache_size = 10240; // cache about 10kb per thread ...@@ -49,8 +52,6 @@ constexpr size_t s_cache_size = 10240; // cache about 10kb per thread
} // namespace <anonymous> } // namespace <anonymous>
class recursive_queue_node;
class instance_wrapper { class instance_wrapper {
public: public:
...@@ -158,6 +159,12 @@ class basic_memory_cache : public memory_cache { ...@@ -158,6 +159,12 @@ class basic_memory_cache : public memory_cache {
}; };
struct disposer {
inline void operator()(memory_managed* ptr) const {
ptr->request_deletion();
}
};
class memory { class memory {
memory() = delete; memory() = delete;
...@@ -171,11 +178,11 @@ class memory { ...@@ -171,11 +178,11 @@ class memory {
* @brief Allocates storage, initializes a new object, and returns * @brief Allocates storage, initializes a new object, and returns
* the new instance. * the new instance.
*/ */
template<typename T, typename... Args> template<typename T, typename... Ts>
static inline T* create(Args&&... args) { static T* create(Ts&&... args) {
auto mc = get_or_set_cache_map_entry<T>(); auto mc = get_or_set_cache_map_entry<T>();
auto p = mc->new_instance(); auto p = mc->new_instance();
auto result = new (p.second) T (std::forward<Args>(args)...); auto result = new (p.second) T (std::forward<Ts>(args)...);
result->outer_memory = p.first; result->outer_memory = p.first;
return result; return result;
} }
...@@ -198,12 +205,6 @@ class memory { ...@@ -198,12 +205,6 @@ class memory {
}; };
struct disposer {
inline void operator()(memory_managed* ptr) const {
ptr->request_deletion();
}
};
} } // namespace cppa::detail } } // namespace cppa::detail
#endif // CPPA_MEMORY_HPP #endif // CPPA_MEMORY_HPP
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/apply_args.hpp" #include "cppa/util/apply_args.hpp"
#include "cppa/util/left_or_right.hpp" #include "cppa/util/left_or_right.hpp"
#include "cppa/util/get_result_type.hpp"
#include "cppa/detail/tdata.hpp" #include "cppa/detail/tdata.hpp"
...@@ -49,7 +50,7 @@ inline bool is_defined_at(Fun& f, Tuple& tup, util::int_list<Is...>) { ...@@ -49,7 +50,7 @@ inline bool is_defined_at(Fun& f, Tuple& tup, util::int_list<Is...>) {
return f.defined_at(get_cv_aware<Is>(tup)...); return f.defined_at(get_cv_aware<Is>(tup)...);
} }
template<typename ProjectionFuns, typename... Args> template<typename ProjectionFuns, typename... Ts>
struct collected_args_tuple { struct collected_args_tuple {
typedef typename tdata_from_type_list< typedef typename tdata_from_type_list<
typename util::tl_zip< typename util::tl_zip<
...@@ -59,7 +60,7 @@ struct collected_args_tuple { ...@@ -59,7 +60,7 @@ struct collected_args_tuple {
util::rm_option util::rm_option
>::type, >::type,
typename util::tl_map< typename util::tl_map<
util::type_list<Args...>, util::type_list<Ts...>,
mutable_gref_wrapped mutable_gref_wrapped
>::type, >::type,
util::left_or_right util::left_or_right
...@@ -71,7 +72,7 @@ struct collected_args_tuple { ...@@ -71,7 +72,7 @@ struct collected_args_tuple {
/** /**
* @brief Projection implemented by a set of functors. * @brief Projection implemented by a set of functors.
*/ */
template<class ProjectionFuns, typename... Args> template<class ProjectionFuns, typename... Ts>
class projection { class projection {
public: public:
...@@ -90,10 +91,10 @@ class projection { ...@@ -90,10 +91,10 @@ class projection {
* @brief Invokes @p fun with a projection of <tt>args...</tt> and stores * @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
* the result of @p fun in @p result. * the result of @p fun in @p result.
*/ */
template<class PartialFun> template<class PartFun>
bool invoke(PartialFun& fun, typename PartialFun::result_type& result, Args... args) const { bool invoke(PartFun& fun, typename PartFun::result_type& result, Ts... args) const {
typename collected_args_tuple<ProjectionFuns,Args...>::type pargs; typename collected_args_tuple<ProjectionFuns,Ts...>::type pargs;
if (collect(pargs, m_funs, std::forward<Args>(args)...)) { if (collect(pargs, m_funs, std::forward<Ts>(args)...)) {
auto indices = util::get_indices(pargs); auto indices = util::get_indices(pargs);
if (is_defined_at(fun, pargs, indices)) { if (is_defined_at(fun, pargs, indices)) {
result = util::apply_args(fun, pargs, indices); result = util::apply_args(fun, pargs, indices);
...@@ -106,11 +107,11 @@ class projection { ...@@ -106,11 +107,11 @@ class projection {
/** /**
* @brief Invokes @p fun with a projection of <tt>args...</tt>. * @brief Invokes @p fun with a projection of <tt>args...</tt>.
*/ */
template<class PartialFun> template<class PartFun>
bool operator()(PartialFun& fun, Args... args) const { bool operator()(PartFun& fun, Ts... args) const {
typename collected_args_tuple<ProjectionFuns,Args...>::type pargs; typename collected_args_tuple<ProjectionFuns,Ts...>::type pargs;
auto indices = util::get_indices(pargs); auto indices = util::get_indices(pargs);
if (collect(pargs, m_funs, std::forward<Args>(args)...)) { if (collect(pargs, m_funs, std::forward<Ts>(args)...)) {
if (is_defined_at(fun, pargs, indices)) { if (is_defined_at(fun, pargs, indices)) {
util::apply_args(fun, pargs, indices); util::apply_args(fun, pargs, indices);
return true; return true;
...@@ -123,13 +124,13 @@ class projection { ...@@ -123,13 +124,13 @@ class projection {
* @brief Invokes @p fun with a projection of <tt>args...</tt> and stores * @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
* the result of @p fun in @p result. * the result of @p fun in @p result.
*/ */
template<class PartialFun> template<class PartFun>
inline bool operator()(PartialFun& fun, typename PartialFun::result_type& result, Args... args) const { inline bool operator()(PartFun& fun, typename PartFun::result_type& result, Ts... args) const {
return invoke(fun, result, args...); return invoke(fun, result, args...);
} }
template<class PartialFun> template<class PartFun>
inline bool operator()(PartialFun& fun, const util::void_type&, Args... args) const { inline bool operator()(PartFun& fun, const util::void_type&, Ts... args) const {
return (*this)(fun, args...); return (*this)(fun, args...);
} }
...@@ -166,11 +167,11 @@ class projection { ...@@ -166,11 +167,11 @@ class projection {
return true; return true;
} }
template<class TData, class Trans, typename T0, typename... Ts> template<class TData, class Trans, typename U, typename... Us>
static inline bool collect(TData& td, const Trans& tr, static inline bool collect(TData& td, const Trans& tr,
T0&& arg0, Ts&&... args) { U&& arg, Us&&... args) {
return store(td.head, fetch(tr.head, std::forward<T0>(arg0))) return store(td.head, fetch(tr.head, std::forward<U>(arg)))
&& collect(td.tail(), tr.tail(), std::forward<Ts>(args)...); && collect(td.tail(), tr.tail(), std::forward<Us>(args)...);
} }
fun_container m_funs; fun_container m_funs;
...@@ -186,8 +187,8 @@ class projection<util::empty_type_list> { ...@@ -186,8 +187,8 @@ class projection<util::empty_type_list> {
projection(const tdata<>&) { } projection(const tdata<>&) { }
projection(const projection&) = default; projection(const projection&) = default;
template<class PartialFun> template<class PartFun>
bool operator()(PartialFun& fun) const { bool operator()(PartFun& fun) const {
if (fun.defined_at()) { if (fun.defined_at()) {
fun(); fun();
return true; return true;
...@@ -195,8 +196,8 @@ class projection<util::empty_type_list> { ...@@ -195,8 +196,8 @@ class projection<util::empty_type_list> {
return false; return false;
} }
template<class PartialFun> template<class PartFun>
bool operator()(PartialFun& fun, const util::void_type&) const { bool operator()(PartFun& fun, const util::void_type&) const {
if (fun.defined_at()) { if (fun.defined_at()) {
fun(); fun();
return true; return true;
...@@ -204,8 +205,8 @@ class projection<util::empty_type_list> { ...@@ -204,8 +205,8 @@ class projection<util::empty_type_list> {
return false; return false;
} }
template<class PartialFun> template<class PartFun>
bool operator()(PartialFun& fun, typename PartialFun::result_type& res) const { bool operator()(PartFun& fun, typename PartFun::result_type& res) const {
if (fun.defined_at()) { if (fun.defined_at()) {
res = fun(); res = fun();
return true; return true;
...@@ -218,9 +219,9 @@ class projection<util::empty_type_list> { ...@@ -218,9 +219,9 @@ class projection<util::empty_type_list> {
template<class ProjectionFuns, class List> template<class ProjectionFuns, class List>
struct projection_from_type_list; struct projection_from_type_list;
template<class ProjectionFuns, typename... Args> template<class ProjectionFuns, typename... Ts>
struct projection_from_type_list<ProjectionFuns, util::type_list<Args...> > { struct projection_from_type_list<ProjectionFuns, util::type_list<Ts...> > {
typedef projection<ProjectionFuns, Args...> type; typedef projection<ProjectionFuns, Ts...> type;
}; };
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -35,35 +35,33 @@ ...@@ -35,35 +35,33 @@
#include "cppa/primitive_type.hpp" #include "cppa/primitive_type.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/wrapped.hpp" #include "cppa/util/wrapped.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
// maps the primitive_type PT to the corresponding type // maps the primitive_type PT to the corresponding type
template<primitive_type PT> template<primitive_type PT>
struct ptype_to_type : struct ptype_to_type : util::wrapped<void> { };
// signed integers
util::if_else_c<PT == pt_int8, std::int8_t, // integer types
util::if_else_c<PT == pt_int16, std::int16_t, template<> struct ptype_to_type<pt_int8 > : util::wrapped<std::int8_t > { };
util::if_else_c<PT == pt_int32, std::int32_t, template<> struct ptype_to_type<pt_uint8 > : util::wrapped<std::uint8_t > { };
util::if_else_c<PT == pt_int64, std::int64_t, template<> struct ptype_to_type<pt_int16 > : util::wrapped<std::int16_t > { };
util::if_else_c<PT == pt_uint8, std::uint8_t, template<> struct ptype_to_type<pt_uint16> : util::wrapped<std::uint16_t> { };
// unsigned integers template<> struct ptype_to_type<pt_int32 > : util::wrapped<std::int32_t > { };
util::if_else_c<PT == pt_uint16, std::uint16_t, template<> struct ptype_to_type<pt_uint32> : util::wrapped<std::uint32_t> { };
util::if_else_c<PT == pt_uint32, std::uint32_t, template<> struct ptype_to_type<pt_int64 > : util::wrapped<std::int64_t > { };
util::if_else_c<PT == pt_uint64, std::uint64_t, template<> struct ptype_to_type<pt_uint64> : util::wrapped<std::uint64_t> { };
// floating points
util::if_else_c<PT == pt_float, float, // floating points
util::if_else_c<PT == pt_double, double, template<> struct ptype_to_type<pt_float> : util::wrapped<float> { };
util::if_else_c<PT == pt_long_double, long double, template<> struct ptype_to_type<pt_double> : util::wrapped<double> { };
// strings template<> struct ptype_to_type<pt_long_double> : util::wrapped<long double> { };
util::if_else_c<PT == pt_u8string, std::string,
util::if_else_c<PT == pt_u16string, std::u16string, // strings
util::if_else_c<PT == pt_u32string, std::u32string, template<> struct ptype_to_type<pt_u8string > : util::wrapped<std::string > { };
// default case template<> struct ptype_to_type<pt_u16string> : util::wrapped<std::u16string> { };
void > > > > > > > > > > > > > > { template<> struct ptype_to_type<pt_u32string> : util::wrapped<std::u32string> { };
};
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -41,10 +41,10 @@ ...@@ -41,10 +41,10 @@
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/message_id.hpp" #include "cppa/message_id.hpp"
#include "cppa/exit_reason.hpp" #include "cppa/exit_reason.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
#include "cppa/detail/memory.hpp" #include "cppa/detail/memory.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -62,8 +62,8 @@ class receive_policy { ...@@ -62,8 +62,8 @@ class receive_policy {
public: public:
typedef recursive_queue_node* pointer; typedef mailbox_element* pointer;
typedef std::unique_ptr<recursive_queue_node,disposer> smart_pointer; typedef std::unique_ptr<mailbox_element,disposer> smart_pointer;
enum handle_message_result { enum handle_message_result {
hm_timeout_msg, hm_timeout_msg,
...@@ -195,12 +195,17 @@ class receive_policy { ...@@ -195,12 +195,17 @@ class receive_policy {
} }
} }
template<class Client>
mailbox_element* fetch_message(Client* client) {
return client->await_message();
}
private: private:
typedef typename rp_flag<rp_nestable>::type nestable; typedef typename rp_flag<rp_nestable>::type nestable;
typedef typename rp_flag<rp_sequential>::type sequential; typedef typename rp_flag<rp_sequential>::type sequential;
std::list<std::unique_ptr<recursive_queue_node,disposer> > m_cache; std::list<std::unique_ptr<mailbox_element,disposer> > m_cache;
template<class Client> template<class Client>
inline void handle_timeout(Client* client, behavior& bhvr) { inline void handle_timeout(Client* client, behavior& bhvr) {
......
...@@ -50,8 +50,8 @@ class singleton_mixin : public Base { ...@@ -50,8 +50,8 @@ class singleton_mixin : public Base {
protected: protected:
template<typename... Args> template<typename... Ts>
singleton_mixin(Args&&... args) : Base(std::forward<Args>(args)...) { } singleton_mixin(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
virtual ~singleton_mixin() { } virtual ~singleton_mixin() { }
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/message_id.hpp" #include "cppa/message_id.hpp"
#include "cppa/exit_reason.hpp" #include "cppa/exit_reason.hpp"
#include "cppa/detail/recursive_queue_node.hpp" #include "cppa/mailbox_element.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -54,7 +54,7 @@ struct sync_request_bouncer { ...@@ -54,7 +54,7 @@ struct sync_request_bouncer {
make_any_tuple(atom("EXITED"), rsn)); make_any_tuple(atom("EXITED"), rsn));
} }
} }
inline void operator()(const recursive_queue_node& e) const { inline void operator()(const mailbox_element& e) const {
(*this)(e.sender.get(), e.mid); (*this)(e.sender.get(), e.mid);
} }
}; };
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "cppa/util/wrapped.hpp" #include "cppa/util/wrapped.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/arg_match_t.hpp" #include "cppa/util/arg_match_t.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/boxed.hpp" #include "cppa/detail/boxed.hpp"
#include "cppa/detail/types_array.hpp" #include "cppa/detail/types_array.hpp"
...@@ -113,6 +114,11 @@ struct unbox_ref<std::reference_wrapper<T> > { ...@@ -113,6 +114,11 @@ struct unbox_ref<std::reference_wrapper<T> > {
typedef typename std::remove_const<T>::type type; typedef typename std::remove_const<T>::type type;
}; };
template<typename T>
struct unbox_ref<util::rebindable_reference<T> > {
typedef typename std::remove_const<T>::type type;
};
/* /*
* "enhanced" std::tuple * "enhanced" std::tuple
*/ */
...@@ -136,9 +142,9 @@ struct tdata<> { ...@@ -136,9 +142,9 @@ struct tdata<> {
constexpr tdata() { } constexpr tdata() { }
// swallow any number of additional boxed or void_type arguments silently // swallow any number of additional boxed or void_type arguments silently
template<typename... Args> template<typename... Ts>
tdata(Args&&...) { tdata(Ts&&...) {
typedef util::type_list<typename util::rm_ref<Args>::type...> incoming; typedef util::type_list<typename util::rm_ref<Ts>::type...> incoming;
typedef typename util::tl_filter_not_type<incoming, tdata>::type iargs; typedef typename util::tl_filter_not_type<incoming, tdata>::type iargs;
static_assert(util::tl_forall<iargs, boxed_or_void>::value, static_assert(util::tl_forall<iargs, boxed_or_void>::value,
"Additional unboxed arguments provided"); "Additional unboxed arguments provided");
...@@ -239,9 +245,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> { ...@@ -239,9 +245,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
typedef Head head_type; typedef Head head_type;
typedef tdata<Tail...> tail_type; typedef tdata<Tail...> tail_type;
typedef typename util::if_else_c< (sizeof...(Tail) > 0), typedef typename std::conditional<
(sizeof...(Tail) > 0),
typename tdata<Tail...>::back_type, typename tdata<Tail...>::back_type,
util::wrapped<Head> Head
>::type >::type
back_type; back_type;
...@@ -252,10 +259,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> { ...@@ -252,10 +259,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
tdata(const Head& arg) : super(), head(arg) { } tdata(const Head& arg) : super(), head(arg) { }
tdata(Head&& arg) : super(), head(std::move(arg)) { } tdata(Head&& arg) : super(), head(std::move(arg)) { }
template<typename Arg0, typename Arg1, typename... Args> template<typename T0, typename T1, typename... Ts>
tdata(Arg0&& arg0, Arg1&& arg1, Args&&... args) tdata(T0&& arg0, T1&& arg1, Ts&&... args)
: super(std::forward<Arg1>(arg1), std::forward<Args>(args)...) : super(std::forward<T1>(arg1), std::forward<Ts>(args)...)
, head(td_filter<Head>(std::forward<Arg0>(arg0))) { , head(td_filter<Head>(std::forward<T0>(arg0))) {
} }
tdata(const tdata&) = default; tdata(const tdata&) = default;
...@@ -285,10 +292,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> { ...@@ -285,10 +292,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
return *this; return *this;
} }
template<typename Arg0, typename... Args> template<typename T, typename... Ts>
inline void set(Arg0&& arg0, Args&&... args) { inline void set(T&& arg, Ts&&... args) {
head = std::forward<Arg0>(arg0); head = std::forward<T>(arg);
super::set(std::forward<Args>(args)...); super::set(std::forward<Ts>(args)...);
} }
inline size_t size() const { return num_elements; } inline size_t size() const { return num_elements; }
...@@ -317,10 +324,8 @@ struct tdata<Head, Tail...> : tdata<Tail...> { ...@@ -317,10 +324,8 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
case 2: return ptr_to(super::super::head); case 2: return ptr_to(super::super::head);
case 3: return ptr_to(super::super::super::head); case 3: return ptr_to(super::super::super::head);
case 4: return ptr_to(super::super::super::super::head); case 4: return ptr_to(super::super::super::super::head);
case 5: return ptr_to(super::super::super::super::super::head); default: return super::super::super::super::super::at(p - 5);
default: return super::at(p - 1);
} }
//return (p == 0) ? ptr_to(head) : super::at(p - 1);
} }
inline void* mutable_at(size_t p) { inline void* mutable_at(size_t p) {
...@@ -335,40 +340,47 @@ struct tdata<Head, Tail...> : tdata<Tail...> { ...@@ -335,40 +340,47 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
# else # else
return const_cast<void*>(at(p)); return const_cast<void*>(at(p));
# endif # endif
} }
inline const uniform_type_info* type_at(size_t p) const { inline const uniform_type_info* type_at(size_t p) const {
return (p == 0) ? utype_of(head) : super::type_at(p-1); CPPA_REQUIRE(p < num_elements);
switch (p) {
case 0: return utype_of(head);
case 1: return utype_of(super::head);
case 2: return utype_of(super::super::head);
case 3: return utype_of(super::super::super::head);
case 4: return utype_of(super::super::super::super::head);
default: return super::super::super::super::super::type_at(p - 5);
}
} }
Head& _back(std::integral_constant<size_t, 0>) { Head& _back(std::integral_constant<size_t,0>) {
return head; return head;
} }
template<size_t Pos> template<size_t Pos>
back_type& _back(std::integral_constant<size_t, Pos>) { back_type& _back(std::integral_constant<size_t,Pos>) {
std::integral_constant<size_t, Pos - 1> token; std::integral_constant<size_t,Pos-1> token;
return super::_back(token); return super::_back(token);
} }
back_type& back() { back_type& back() {
std::integral_constant<size_t, sizeof...(Tail)> token; std::integral_constant<size_t,sizeof...(Tail)> token;
return _back(token); return _back(token);
} }
const Head& _back(std::integral_constant<size_t, 0>) const { const Head& _back(std::integral_constant<size_t,0>) const {
return head; return head;
} }
template<size_t Pos> template<size_t Pos>
const back_type& _back(std::integral_constant<size_t, Pos>) const { const back_type& _back(std::integral_constant<size_t,Pos>) const {
std::integral_constant<size_t, Pos - 1> token; std::integral_constant<size_t,Pos-1> token;
return super::_back(token); return super::_back(token);
} }
const back_type& back() const { const back_type& back() const {
std::integral_constant<size_t, sizeof...(Tail)> token; std::integral_constant<size_t,sizeof...(Tail)> token;
return _back(token); return _back(token);
} }
}; };
...@@ -398,35 +410,39 @@ struct tdata_upcast_helper<0, Head, Tail...> { ...@@ -398,35 +410,39 @@ struct tdata_upcast_helper<0, Head, Tail...> {
template<typename T> template<typename T>
struct tdata_from_type_list; struct tdata_from_type_list;
template<typename... T> template<typename... Ts>
struct tdata_from_type_list<util::type_list<T...>> { struct tdata_from_type_list<util::type_list<Ts...>> {
typedef tdata<T...> type; typedef tdata<Ts...> type;
}; };
template<typename... T> template<typename T, typename U>
inline void collect_tdata(tdata<T...>&) { } inline void rebind_value(T& lhs, U& rhs) {
lhs = rhs;
}
template<typename Storage, typename... Args> template<typename T, typename U>
void collect_tdata(Storage& storage, const tdata<>&, const Args&... args) { inline void rebind_value(util::rebindable_reference<T>& lhs, U& rhs) {
collect_tdata(storage, args...); lhs.rebind(rhs);
} }
template<typename Storage, typename Arg0, typename... Args> template<typename... Ts>
void collect_tdata(Storage& storage, const Arg0& arg0, const Args&... args) { inline void rebind_tdata(tdata<Ts...>&) { }
storage.head = arg0.head;
collect_tdata(storage.tail(), arg0.tail(), args...); template<typename... Ts, typename... Vs>
void rebind_tdata(tdata<Ts...>& td, const tdata<>&, const Vs&... args) {
rebind_tdata(td, args...);
}
template<typename... Ts, typename... Us, typename... Vs>
void rebind_tdata(tdata<Ts...>& td, const tdata<Us...>& arg, const Vs&... args) {
rebind_value(td.head, arg.head);
rebind_tdata(td.tail(), arg.tail(), args...);
} }
} } // namespace cppa::detail } } // namespace cppa::detail
namespace cppa { namespace cppa {
template<typename... Args>
detail::tdata<typename detail::implicit_conversions<typename util::rm_ref<Args>::type>::type...>
mk_tdata(Args&&... args) {
return {std::forward<Args>(args)...};
}
template<size_t N, typename... Ts> template<size_t N, typename... Ts>
const typename util::at<N, Ts...>::type& get(const detail::tdata<Ts...>& tv) { const typename util::at<N, Ts...>::type& get(const detail::tdata<Ts...>& tv) {
static_assert(N < sizeof...(Ts), "N >= tv.size()"); static_assert(N < sizeof...(Ts), "N >= tv.size()");
......
...@@ -58,9 +58,8 @@ class tuple_vals : public abstract_tuple { ...@@ -58,9 +58,8 @@ class tuple_vals : public abstract_tuple {
tuple_vals(const tuple_vals&) = default; tuple_vals(const tuple_vals&) = default;
template<typename... Args> template<typename... Us>
tuple_vals(Args&&... args) : super(false) tuple_vals(Us&&... args) : super(false), m_data(std::forward<Us>(args)...) { }
, m_data(std::forward<Args>(args)...) { }
const void* native_data() const { const void* native_data() const {
return &m_data; return &m_data;
......
...@@ -31,7 +31,9 @@ ...@@ -31,7 +31,9 @@
#ifndef CPPA_TUPLE_VIEW_HPP #ifndef CPPA_TUPLE_VIEW_HPP
#define CPPA_TUPLE_VIEW_HPP #define CPPA_TUPLE_VIEW_HPP
#include "cppa/util/static_foreach.hpp" #include "cppa/guard_expr.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/tuple_vals.hpp" #include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/abstract_tuple.hpp" #include "cppa/detail/abstract_tuple.hpp"
...@@ -58,7 +60,7 @@ class tuple_view : public abstract_tuple { ...@@ -58,7 +60,7 @@ class tuple_view : public abstract_tuple {
public: public:
typedef tdata<Ts*...> data_type; typedef tdata<util::rebindable_reference<Ts>...> data_type;
typedef types_array<Ts...> element_types; typedef types_array<Ts...> element_types;
...@@ -83,20 +85,17 @@ class tuple_view : public abstract_tuple { ...@@ -83,20 +85,17 @@ class tuple_view : public abstract_tuple {
} }
abstract_tuple* copy() const { abstract_tuple* copy() const {
auto result = new tuple_vals<Ts...>; return new tuple_vals<Ts...>{m_data};
tuple_view_copy_helper f{result};
util::static_foreach<0, sizeof...(Ts)>::_(m_data, f);
return result;
} }
const void* at(size_t pos) const { const void* at(size_t pos) const {
CPPA_REQUIRE(pos < size()); CPPA_REQUIRE(pos < size());
return m_data.at(pos); return m_data.at(pos).get_ptr();
} }
void* mutable_at(size_t pos) { void* mutable_at(size_t pos) {
CPPA_REQUIRE(pos < size()); CPPA_REQUIRE(pos < size());
return m_data.mutable_at(pos); return m_data.mutable_at(pos).get_ptr();
} }
const uniform_type_info* type_at(size_t pos) const { const uniform_type_info* type_at(size_t pos) const {
...@@ -114,6 +113,8 @@ class tuple_view : public abstract_tuple { ...@@ -114,6 +113,8 @@ class tuple_view : public abstract_tuple {
static types_array<Ts...> m_types; static types_array<Ts...> m_types;
tuple_view(const data_type& data) : m_data(data) { }
}; };
template<typename... Ts> template<typename... Ts>
......
...@@ -37,59 +37,43 @@ ...@@ -37,59 +37,43 @@
#include "cppa/primitive_type.hpp" #include "cppa/primitive_type.hpp"
namespace cppa { namespace detail { #include "cppa/util/rm_ref.hpp"
// if (IfStmt == true) ptype = PT; else ptype = Else::ptype;
template<bool IfStmt, primitive_type PT, class Else>
struct if_else_ptype_c {
static const primitive_type ptype = PT;
};
template<primitive_type PT, class Else> namespace cppa { namespace detail {
struct if_else_ptype_c<false, PT, Else> {
static const primitive_type ptype = Else::ptype;
};
// if (Stmt::value == true) ptype = FT; else ptype = Else::ptype;
template<class Stmt, primitive_type PT, class Else>
struct if_else_ptype : if_else_ptype_c<Stmt::value, PT, Else> { };
template<primitive_type PT> template<primitive_type PT>
struct wrapped_ptype { static const primitive_type ptype = PT; }; struct wrapped_ptype { static const primitive_type ptype = PT; };
// maps type T the the corresponding fundamental_type // maps type T the the corresponding fundamental_type
template<typename T> template<typename T>
struct type_to_ptype_impl : struct type_to_ptype_impl {
// signed integers static constexpr primitive_type ptype =
if_else_ptype<std::is_same<T, std::int8_t>, pt_int8, std::is_convertible<T,std::string>::value
if_else_ptype<std::is_same<T, std::int16_t>, pt_int16, ? pt_u8string
if_else_ptype<std::is_same<T, std::int32_t>, pt_int32, : (std::is_convertible<T,std::u16string>::value
if_else_ptype<std::is_same<T, std::int64_t>, pt_int64, ? pt_u16string
// unsigned integers : (std::is_convertible<T,std::u32string>::value
if_else_ptype<std::is_same<T, std::uint8_t>, pt_uint8, ? pt_u32string
if_else_ptype<std::is_same<T, std::uint16_t>, pt_uint16, : pt_null));
if_else_ptype<std::is_same<T, std::uint32_t>, pt_uint32,
if_else_ptype<std::is_same<T, std::uint64_t>, pt_uint64,
// floating points
if_else_ptype<std::is_same<T, float>, pt_float,
if_else_ptype<std::is_same<T, double>, pt_double,
if_else_ptype<std::is_same<T, long double>, pt_long_double,
// strings
if_else_ptype<std::is_convertible<T, std::string>, pt_u8string,
if_else_ptype<std::is_convertible<T, std::u16string>, pt_u16string,
if_else_ptype<std::is_convertible<T, std::u32string>, pt_u32string,
// default case
wrapped_ptype<pt_null> > > > > > > > > > > > > > > {
}; };
template<typename T> // integers
struct type_to_ptype { template<> struct type_to_ptype_impl<std::int8_t > : wrapped_ptype<pt_int8 > { };
template<> struct type_to_ptype_impl<std::uint8_t > : wrapped_ptype<pt_uint8 > { };
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type; template<> struct type_to_ptype_impl<std::int16_t > : wrapped_ptype<pt_int16 > { };
template<> struct type_to_ptype_impl<std::uint16_t> : wrapped_ptype<pt_uint16> { };
static const primitive_type ptype = type_to_ptype_impl<type>::ptype; template<> struct type_to_ptype_impl<std::int32_t > : wrapped_ptype<pt_int32 > { };
template<> struct type_to_ptype_impl<std::uint32_t> : wrapped_ptype<pt_uint32> { };
template<> struct type_to_ptype_impl<std::int64_t > : wrapped_ptype<pt_int64 > { };
template<> struct type_to_ptype_impl<std::uint64_t> : wrapped_ptype<pt_uint64> { };
// floating points
template<> struct type_to_ptype_impl<float> : wrapped_ptype<pt_float > { };
template<> struct type_to_ptype_impl<double> : wrapped_ptype<pt_double > { };
template<> struct type_to_ptype_impl<long double> : wrapped_ptype<pt_long_double> { };
}; template<typename T>
struct type_to_ptype : type_to_ptype_impl<typename util::rm_ref<T>::type> { };
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -42,30 +42,20 @@ ...@@ -42,30 +42,20 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<bool IsFun, typename T> // 'absorbs' callables and instances of `anything`
struct vg_fwd_ {
static inline const T& _(const T& arg) { return arg; }
static inline T&& _(T&& arg) { return std::move(arg); }
static inline T& _(T& arg) { return arg; }
};
template<typename T> template<typename T>
struct vg_fwd_<true, T> { const T& vg_fwd(const T& arg, typename std::enable_if<not util::is_callable<T>::value>::type* = 0) {
template<typename Arg> return arg;
static inline util::void_type _(Arg&&) { return {}; } }
};
template<> inline util::void_type vg_fwd(const anything&) {
struct vg_fwd_<false,anything> { return {};
static inline util::void_type _(const anything&) { return {}; } }
};
// absorbs callables and instances of `anything`
template<typename T> template<typename T>
struct vg_fwd util::void_type vg_fwd(const T&, typename std::enable_if<util::is_callable<T>::value>::type* = 0) {
: vg_fwd_<util::is_callable<typename util::rm_ref<T>::type>::value, return {};
typename util::rm_ref<T>::type> { }
};
template<typename T> template<typename T>
struct vg_cmp { struct vg_cmp {
...@@ -91,11 +81,11 @@ class value_guard { ...@@ -91,11 +81,11 @@ class value_guard {
value_guard() = default; value_guard() = default;
value_guard(const value_guard&) = default; value_guard(const value_guard&) = default;
template<typename... Args> template<typename... Ts>
value_guard(const Args&... args) : m_args(vg_fwd<Args>::_(args)...) { } value_guard(const Ts&... args) : m_args(vg_fwd(args)...) { }
template<typename... Args> template<typename... Ts>
inline bool operator()(const Args&... args) const { inline bool operator()(const Ts&... args) const {
return _eval(m_args.head, m_args.tail(), args...); return _eval(m_args.head, m_args.tail(), args...);
} }
...@@ -117,17 +107,17 @@ class value_guard { ...@@ -117,17 +107,17 @@ class value_guard {
return true; return true;
} }
template<typename T0, typename Arg0, typename... Args> template<typename T, typename U, typename... Us>
static inline bool _eval(const T0& head, const tdata<>&, static inline bool _eval(const T& head, const tdata<>&,
const Arg0& arg0, const Args&...) { const U& arg, const Us&...) {
return cmp(head, arg0); return cmp(head, arg);
} }
template<typename T0, typename T1, typename... Ts, template<typename T0, typename T1, typename... Ts,
typename Arg0, typename... Args> typename U, typename... Us>
static inline bool _eval(const T0& head, const tdata<T1,Ts...>& tail, static inline bool _eval(const T0& head, const tdata<T1,Ts...>& tail,
const Arg0& arg0, const Args&... args) { const U& arg, const Us&... args) {
return cmp(head, arg0) && _eval(tail.head, tail.tail(), args...); return cmp(head, arg) && _eval(tail.head, tail.tail(), args...);
} }
}; };
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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 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_EITHER_HPP
#define CPPA_EITHER_HPP
#include <new>
#include <utility>
#include <type_traits>
#include "cppa/config.hpp"
namespace cppa {
/**
* @brief Represents either a @p Left or a @p Right.
*/
template<class Left, class Right>
class either {
//static_assert( std::is_convertible<Left, Right>::value == false
// && std::is_convertible<Right, Left>::value == false,
// "Left is not allowed to be convertible to Right");
public:
typedef Left left_type;
typedef Right right_type;
/**
* @brief Default constructor, creates a @p Left.
*/
either() : m_is_left(true) { new (&m_left) left_type (); }
/**
* @brief Creates a @p Left from @p value.
*/
either(const left_type& value) : m_is_left(true) { cr_left(value); }
/**
* @brief Creates a @p Left from @p value.
*/
either(Left&& value) : m_is_left(true) { cr_left(std::move(value)); }
/**
* @brief Creates a @p Right from @p value.
*/
either(const right_type& value) : m_is_left(false) { cr_right(value); }
/**
* @brief Creates a @p Right from @p value.
*/
either(Right&& value) : m_is_left(false) { cr_right(std::move(value)); }
either(const either& other) : m_is_left(other.m_is_left) {
if (other.m_is_left) cr_left(other.m_left);
else cr_right(other.m_right);
}
either(either&& other) : m_is_left(other.m_is_left) {
if (other.m_is_left) cr_left(std::move(other.m_left));
else cr_right(std::move(other.m_right));
}
~either() { destroy(); }
either& operator=(const either& other) {
if (m_is_left == other.m_is_left) {
if (m_is_left) m_left = other.m_left;
else m_right = other.m_right;
}
else {
destroy();
m_is_left = other.m_is_left;
if (other.m_is_left) cr_left(other.m_left);
else cr_right(other.m_right);
}
return *this;
}
either& operator=(either&& other) {
if (m_is_left == other.m_is_left) {
if (m_is_left) m_left = std::move(other.m_left);
else m_right = std::move(other.m_right);
}
else {
destroy();
m_is_left = other.m_is_left;
if (other.m_is_left) cr_left(std::move(other.m_left));
else cr_right(std::move(other.m_right));
}
return *this;
}
/**
* @brief Returns @p true if this is a @p Left; otherwise @p false.
*/
inline bool is_left() const { return m_is_left; }
/**
* @brief Returns @p true if this is a @p Left; otherwise @p false.
*/
inline bool is_right() const { return !m_is_left; }
/**
* @brief Returns this @p either as a @p Left.
*/
inline Left& left() {
CPPA_REQUIRE(m_is_left);
return m_left;
}
/**
* @brief Returns this @p either as a @p Left.
*/
inline const left_type& left() const {
CPPA_REQUIRE(m_is_left);
return m_left;
}
/**
* @brief Returns this @p either as a @p Right.
*/
inline Right& right() {
CPPA_REQUIRE(!m_is_left);
return m_right;
}
/**
* @brief Returns this @p either as a @p Right.
*/
inline const right_type& right() const {
CPPA_REQUIRE(!m_is_left);
return m_right;
}
template<typename F>
void apply(const F& fun) {
if (is_left()) fun(left());
else fun(right());
}
template<typename F>
void apply(const F& fun) const {
if (is_left()) fun(left());
else fun(right());
}
template<typename Result, typename F>
Result inspect(const F& fun) {
if (is_left()) return fun(left());
else return fun(right());
}
template<typename Result, typename F>
Result inspect(const F& fun) const {
if (is_left()) return fun(left());
else return fun(right());
}
private:
bool m_is_left;
union {
left_type m_left;
right_type m_right;
};
void destroy() {
if (m_is_left) m_left.~Left();
else m_right.~Right();
}
template<typename L>
void cr_left(L&& value) {
new (&m_left) left_type (std::forward<L>(value));
}
template<typename R>
void cr_right(R&& value) {
new (&m_right) right_type (std::forward<R>(value));
}
};
/** @relates either */
template<typename Left, typename Right>
bool operator==(const either<Left, Right>& lhs, const either<Left, Right>& rhs) {
if (lhs.is_left() == rhs.is_left()) {
if (lhs.is_left()) return lhs.left() == rhs.left();
else return lhs.right() == rhs.right();
}
return false;
}
/** @relates either */
template<typename Left, typename Right>
bool operator==(const either<Left, Right>& lhs, const Left& rhs) {
return lhs.is_left() && lhs.left() == rhs;
}
/** @relates either */
template<typename Left, typename Right>
bool operator==(const Left& lhs, const either<Left, Right>& rhs) {
return rhs == lhs;
}
/** @relates either */
template<typename Left, typename Right>
bool operator==(const either<Left, Right>& lhs, const Right& rhs) {
return lhs.is_right() && lhs.right() == rhs;
}
/** @relates either */
template<typename Left, typename Right>
bool operator==(const Right& lhs, const either<Left, Right>& rhs) {
return rhs == lhs;
}
/** @relates either */
template<typename Left, typename Right>
bool operator!=(const either<Left, Right>& lhs, const either<Left, Right>& rhs) {
return !(lhs == rhs);
}
/** @relates either */
template<typename Left, typename Right>
bool operator!=(const either<Left, Right>& lhs, const Left& rhs) {
return !(lhs == rhs);
}
/** @relates either */
template<typename Left, typename Right>
bool operator!=(const Left& lhs, const either<Left, Right>& rhs) {
return !(rhs == lhs);
}
/** @relates either */
template<typename Left, typename Right>
bool operator!=(const either<Left, Right>& lhs, const Right& rhs) {
return !(lhs == rhs);
}
/** @relates either */
template<typename Left, typename Right>
bool operator!=(const Right& lhs, const either<Left, Right>& rhs) {
return !(rhs == lhs);
}
} // namespace cppa
#endif // CPPA_EITHER_HPP
...@@ -60,9 +60,9 @@ class enable_weak_ptr : public Base { ...@@ -60,9 +60,9 @@ class enable_weak_ptr : public Base {
typedef enable_weak_ptr combined_type; typedef enable_weak_ptr combined_type;
template<typename... Args> template<typename... Ts>
enable_weak_ptr(Args&&... args) enable_weak_ptr(Ts&&... args)
: Base(std::forward<Args>(args)...) : Base(std::forward<Ts>(args)...)
, m_anchor(new weak_ptr_anchor(this)) { } , m_anchor(new weak_ptr_anchor(this)) { }
void request_deletion() { void request_deletion() {
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <vector> #include <vector>
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/either.hpp"
#include "cppa/extend.hpp" #include "cppa/extend.hpp"
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/scheduled_actor.hpp" #include "cppa/scheduled_actor.hpp"
...@@ -60,14 +59,14 @@ class event_based_actor : public scheduled_actor { ...@@ -60,14 +59,14 @@ class event_based_actor : public scheduled_actor {
* @brief Finishes execution with exit reason * @brief Finishes execution with exit reason
* {@link exit_reason::unallowed_function_call unallowed_function_call}. * {@link exit_reason::unallowed_function_call unallowed_function_call}.
*/ */
void dequeue(behavior&); //override void dequeue(behavior&);
/** /**
* @copydoc dequeue(behavior&) * @copydoc dequeue(behavior&)
*/ */
void dequeue_response(behavior&, message_id); void dequeue_response(behavior&, message_id);
resume_result resume(util::fiber*, actor_ptr&); //override resume_result resume(util::fiber*, actor_ptr&);
/** /**
* @brief Initializes the actor. * @brief Initializes the actor.
...@@ -92,9 +91,10 @@ class event_based_actor : public scheduled_actor { ...@@ -92,9 +91,10 @@ class event_based_actor : public scheduled_actor {
* @brief Provokes a compiler error to ensure that an event-based actor * @brief Provokes a compiler error to ensure that an event-based actor
* does not accidently uses receive() instead of become(). * does not accidently uses receive() instead of become().
*/ */
template<typename... Args> template<typename... Ts>
void receive(Args&&...) { void receive(Ts&&...) {
static_assert((sizeof...(Args) + 1) < 1, // this asssertion always fails
static_assert((sizeof...(Ts) + 1) < 1,
"You shall not use receive in an event-based actor. " "You shall not use receive in an event-based actor. "
"Use become() instead."); "Use become() instead.");
} }
...@@ -102,31 +102,33 @@ class event_based_actor : public scheduled_actor { ...@@ -102,31 +102,33 @@ class event_based_actor : public scheduled_actor {
/** /**
* @brief Provokes a compiler error. * @brief Provokes a compiler error.
*/ */
template<typename... Args> template<typename... Ts>
void receive_loop(Args&&... args) { void receive_loop(Ts&&... args) {
receive(std::forward<Args>(args)...); receive(std::forward<Ts>(args)...);
} }
/** /**
* @brief Provokes a compiler error. * @brief Provokes a compiler error.
*/ */
template<typename... Args> template<typename... Ts>
void receive_while(Args&&... args) { void receive_while(Ts&&... args) {
receive(std::forward<Args>(args)...); receive(std::forward<Ts>(args)...);
} }
/** /**
* @brief Provokes a compiler error. * @brief Provokes a compiler error.
*/ */
template<typename... Args> template<typename... Ts>
void do_receive(Args&&... args) { void do_receive(Ts&&... args) {
receive(std::forward<Args>(args)...); receive(std::forward<Ts>(args)...);
} }
void do_become(behavior&& bhvr, bool discard_old); void do_become(behavior&& bhvr, bool discard_old);
void become_waiting_for(behavior bhvr, message_id mf); void become_waiting_for(behavior bhvr, message_id mf);
detail::receive_policy m_recv_policy;
private: private:
inline bool has_behavior() const { inline bool has_behavior() const {
...@@ -149,8 +151,6 @@ class event_based_actor : public scheduled_actor { ...@@ -149,8 +151,6 @@ class event_based_actor : public scheduled_actor {
} }
} }
detail::receive_policy m_policy;
}; };
} // namespace cppa } // namespace cppa
......
...@@ -56,12 +56,13 @@ struct extend_helper<B,D,M,Ms...> : extend_helper<B,M<D,B>,Ms...> { }; ...@@ -56,12 +56,13 @@ struct extend_helper<B,D,M,Ms...> : extend_helper<B,M<D,B>,Ms...> { };
* *
* Mixins in libcppa always have two template parameters: base type and * Mixins in libcppa always have two template parameters: base type and
* derived type. This allows mixins to make use of the curiously recurring * derived type. This allows mixins to make use of the curiously recurring
* template pattern (CRTP). * template pattern (CRTP). However, if none of the used mixins use CRTP,
* the second template argument can ignored (it is then set to Base).
*/ */
template<class Base, class Derived> template<class Base, class Derived = Base>
struct extend { struct extend {
/** /**
* @brief An alias for the result type. * @brief Identifies the combined type.
*/ */
template<template<class,class> class... Mixins> template<template<class,class> class... Mixins>
using with = typename detail::extend_helper<Derived,Base,Mixins...>::type; using with = typename detail::extend_helper<Derived,Base,Mixins...>::type;
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "cppa/util/rm_ref.hpp" #include "cppa/util/rm_ref.hpp"
#include "cppa/util/void_type.hpp" #include "cppa/util/void_type.hpp"
#include "cppa/util/apply_args.hpp" #include "cppa/util/apply_args.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/tdata.hpp" #include "cppa/detail/tdata.hpp"
...@@ -96,8 +97,8 @@ struct guard_expr { ...@@ -96,8 +97,8 @@ struct guard_expr {
guard_expr(const guard_expr&) = default; guard_expr(const guard_expr&) = default;
guard_expr(guard_expr&& other) : m_args(std::move(other.m_args)) { } guard_expr(guard_expr&& other) : m_args(std::move(other.m_args)) { }
template<typename... Args> template<typename... Ts>
bool operator()(const Args&... args) const; bool operator()(const Ts&... args) const;
}; };
...@@ -109,58 +110,16 @@ struct guard_expr { ...@@ -109,58 +110,16 @@ struct guard_expr {
SubMacro (greater_eq_op, >=) SubMacro (equal_op, ==) \ SubMacro (greater_eq_op, >=) SubMacro (equal_op, ==) \
SubMacro (not_equal_op, !=) SubMacro (not_equal_op, !=)
template<typename T>
struct ge_mutable_reference_wrapper {
T* value;
ge_mutable_reference_wrapper() : value(nullptr) { }
ge_mutable_reference_wrapper(T&&) = delete;
ge_mutable_reference_wrapper(T& vref) : value(&vref) { }
ge_mutable_reference_wrapper(const ge_mutable_reference_wrapper&) = default;
ge_mutable_reference_wrapper& operator=(T& vref) {
value = &vref;
return *this;
}
ge_mutable_reference_wrapper& operator=(const ge_mutable_reference_wrapper&) = default;
T& get() const { CPPA_REQUIRE(value != 0); return *value; }
operator T& () const { CPPA_REQUIRE(value != 0); return *value; }
};
template<typename T>
struct ge_reference_wrapper {
const T* value;
ge_reference_wrapper(T&&) = delete;
ge_reference_wrapper() : value(nullptr) { }
ge_reference_wrapper(const T& val_ref) : value(&val_ref) { }
ge_reference_wrapper(const ge_reference_wrapper&) = default;
ge_reference_wrapper& operator=(const T& vref) {
value = &vref;
return *this;
}
ge_reference_wrapper& operator=(const ge_reference_wrapper&) = default;
const T& get() const { CPPA_REQUIRE(value != 0); return *value; }
operator const T& () const { CPPA_REQUIRE(value != 0); return *value; }
};
// support use of gref(BooleanVariable) as receive loop 'guard'
template<>
struct ge_reference_wrapper<bool> {
const bool* value;
ge_reference_wrapper(bool&&) = delete;
ge_reference_wrapper(const bool& val_ref) : value(&val_ref) { }
ge_reference_wrapper(const ge_reference_wrapper&) = default;
ge_reference_wrapper& operator=(const ge_reference_wrapper&) = default;
const bool& get() const { CPPA_REQUIRE(value != 0); return *value; }
operator const bool& () const { CPPA_REQUIRE(value != 0); return *value; }
bool operator()() const { CPPA_REQUIRE(value != 0); return *value; }
};
/** /**
* @brief Creates a reference wrapper similar to std::reference_wrapper<const T> * @brief Creates a reference wrapper similar to std::reference_wrapper<const T>
* that could be used in guard expressions or to enforce lazy evaluation. * that could be used in guard expressions or to enforce lazy evaluation.
*/ */
template<typename T> template<typename T>
ge_reference_wrapper<T> gref(const T& value) { return {value}; } util::rebindable_reference<const T> gref(const T& value) {
return {value};
}
//ge_reference_wrapper<T> gref(const T& value) { return {value}; }
// bind utility for placeholders // bind utility for placeholders
...@@ -385,7 +344,7 @@ template<typename T, class Tuple> ...@@ -385,7 +344,7 @@ template<typename T, class Tuple>
struct ge_unbound { typedef T type; }; struct ge_unbound { typedef T type; };
template<typename T, class Tuple> template<typename T, class Tuple>
struct ge_unbound<ge_reference_wrapper<T>, Tuple> { typedef T type; }; struct ge_unbound<util::rebindable_reference<const T>, Tuple> { typedef T type; };
template<typename T, class Tuple> template<typename T, class Tuple>
struct ge_unbound<std::reference_wrapper<T>, Tuple> { typedef T type; }; struct ge_unbound<std::reference_wrapper<T>, Tuple> { typedef T type; };
...@@ -418,7 +377,7 @@ struct is_ge_type<guard_placeholder<X> > { ...@@ -418,7 +377,7 @@ struct is_ge_type<guard_placeholder<X> > {
}; };
template<typename T> template<typename T>
struct is_ge_type<ge_reference_wrapper<T> > { struct is_ge_type<util::rebindable_reference<T> > {
static constexpr bool value = true; static constexpr bool value = true;
}; };
...@@ -553,7 +512,7 @@ inline const T& ge_resolve(const Tuple&, const std::reference_wrapper<const T>& ...@@ -553,7 +512,7 @@ inline const T& ge_resolve(const Tuple&, const std::reference_wrapper<const T>&
} }
template<class Tuple, typename T> template<class Tuple, typename T>
inline const T& ge_resolve(const Tuple&, const ge_reference_wrapper<T>& value) { inline const T& ge_resolve(const Tuple&, const util::rebindable_reference<const T>& value) {
return value.get(); return value.get();
} }
...@@ -644,19 +603,19 @@ auto ge_resolve(const Tuple& tup, ...@@ -644,19 +603,19 @@ auto ge_resolve(const Tuple& tup,
return ge_eval<OP>(tup, ge.m_args.first, ge.m_args.second); return ge_eval<OP>(tup, ge.m_args.first, ge.m_args.second);
} }
template<operator_id OP, typename First, typename Second, typename... Args> template<operator_id OP, typename First, typename Second, typename... Ts>
auto ge_invoke_step2(const guard_expr<OP, First, Second>& ge, auto ge_invoke_step2(const guard_expr<OP, First, Second>& ge,
const detail::tdata<Args...>& tup) const detail::tdata<Ts...>& tup)
-> typename ge_result<OP, First, Second, detail::tdata<Args...>>::type { -> typename ge_result<OP, First, Second, detail::tdata<Ts...>>::type {
return ge_eval<OP>(tup, ge.m_args.first, ge.m_args.second); return ge_eval<OP>(tup, ge.m_args.first, ge.m_args.second);
} }
template<operator_id OP, typename First, typename Second, typename... Args> template<operator_id OP, typename First, typename Second, typename... Ts>
auto ge_invoke(const guard_expr<OP, First, Second>& ge, auto ge_invoke(const guard_expr<OP, First, Second>& ge,
const Args&... args) const Ts&... args)
-> typename ge_result<OP, First, Second, -> typename ge_result<OP, First, Second,
detail::tdata<std::reference_wrapper<const Args>...>>::type { detail::tdata<std::reference_wrapper<const Ts>...>>::type {
detail::tdata<std::reference_wrapper<const Args>...> tup{args...}; detail::tdata<std::reference_wrapper<const Ts>...> tup{args...};
return ge_invoke_step2(ge, tup); return ge_invoke_step2(ge, tup);
} }
...@@ -664,9 +623,9 @@ template<class GuardExpr> ...@@ -664,9 +623,9 @@ template<class GuardExpr>
struct ge_invoke_helper { struct ge_invoke_helper {
const GuardExpr& ge; const GuardExpr& ge;
ge_invoke_helper(const GuardExpr& arg) : ge(arg) { } ge_invoke_helper(const GuardExpr& arg) : ge(arg) { }
template<typename... Args> template<typename... Ts>
bool operator()(Args&&... args) const { bool operator()(Ts&&... args) const {
return ge_invoke(ge, std::forward<Args>(args)...); return ge_invoke(ge, std::forward<Ts>(args)...);
} }
}; };
...@@ -687,10 +646,10 @@ ge_invoke_any(const guard_expr<OP, First, Second>& ge, ...@@ -687,10 +646,10 @@ ge_invoke_any(const guard_expr<OP, First, Second>& ge,
>::type >::type
result_type; result_type;
using namespace util; using namespace util;
typename if_else< typename std::conditional<
std::is_same<typename TupleTypes::back, anything>, std::is_same<typename TupleTypes::back,anything>::value,
TupleTypes, TupleTypes,
wrapped<typename tl_push_back<TupleTypes, anything>::type> wrapped<typename tl_push_back<TupleTypes,anything>::type>
>::type >::type
cast_token; cast_token;
auto x = tuple_cast(tup, cast_token); auto x = tuple_cast(tup, cast_token);
...@@ -700,8 +659,8 @@ ge_invoke_any(const guard_expr<OP, First, Second>& ge, ...@@ -700,8 +659,8 @@ ge_invoke_any(const guard_expr<OP, First, Second>& ge,
} }
template<operator_id OP, typename First, typename Second> template<operator_id OP, typename First, typename Second>
template<typename... Args> template<typename... Ts>
bool guard_expr<OP, First, Second>::operator()(const Args&... args) const { bool guard_expr<OP, First, Second>::operator()(const Ts&... args) const {
static_assert(std::is_same<decltype(ge_invoke(*this, args...)), bool>::value, static_assert(std::is_same<decltype(ge_invoke(*this, args...)), bool>::value,
"guard expression does not return a boolean"); "guard expression does not return a boolean");
return ge_invoke(*this, args...); return ge_invoke(*this, args...);
...@@ -711,17 +670,17 @@ bool guard_expr<OP, First, Second>::operator()(const Args&... args) const { ...@@ -711,17 +670,17 @@ bool guard_expr<OP, First, Second>::operator()(const Args&... args) const {
template<typename T> template<typename T>
struct gref_wrapped { struct gref_wrapped {
typedef ge_reference_wrapper<typename util::rm_ref<T>::type> type; typedef util::rebindable_reference<const typename util::rm_ref<T>::type> type;
}; };
template<typename T> template<typename T>
struct mutable_gref_wrapped { struct mutable_gref_wrapped {
typedef ge_mutable_reference_wrapper<T> type; typedef util::rebindable_reference<T> type;
}; };
template<typename T> template<typename T>
struct mutable_gref_wrapped<T&> { struct mutable_gref_wrapped<T&> {
typedef ge_mutable_reference_wrapper<T> type; typedef util::rebindable_reference<T> type;
}; };
// finally ... // finally ...
......
...@@ -113,9 +113,9 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >, ...@@ -113,9 +113,9 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >,
set_ptr(new_value); set_ptr(new_value);
} }
template<typename... Args> template<typename... Ts>
void emplace(Args&&... args) { void emplace(Ts&&... args) {
reset(new T(std::forward<Args>(args)...)); reset(new T(std::forward<Ts>(args)...));
} }
intrusive_ptr& operator=(pointer ptr) { intrusive_ptr& operator=(pointer ptr) {
...@@ -207,9 +207,9 @@ inline bool operator!=(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs) ...@@ -207,9 +207,9 @@ inline bool operator!=(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs)
* @brief Constructs an object of type T which must be a derived type * @brief Constructs an object of type T which must be a derived type
* of {@link ref_counted} and wraps it in an {@link intrusive_ptr}. * of {@link ref_counted} and wraps it in an {@link intrusive_ptr}.
*/ */
template<typename T, typename... Args> template<typename T, typename... Ts>
intrusive_ptr<T> make_counted(Args&&... args) { intrusive_ptr<T> make_counted(Ts&&... args) {
return {new T(std::forward<Args>(args)...)}; return {new T(std::forward<Ts>(args)...)};
} }
} // namespace cppa } // namespace cppa
......
...@@ -43,13 +43,13 @@ ...@@ -43,13 +43,13 @@
#include "cppa/match_expr.hpp" #include "cppa/match_expr.hpp"
#include "cppa/exit_reason.hpp" #include "cppa/exit_reason.hpp"
#include "cppa/memory_cached.hpp" #include "cppa/memory_cached.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/response_handle.hpp" #include "cppa/response_handle.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
#include "cppa/detail/behavior_stack.hpp" #include "cppa/detail/behavior_stack.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
namespace cppa { namespace cppa {
...@@ -85,7 +85,7 @@ constexpr keep_behavior_t keep_behavior = keep_behavior_t{}; ...@@ -85,7 +85,7 @@ constexpr keep_behavior_t keep_behavior = keep_behavior_t{};
* @brief Base class for local running Actors. * @brief Base class for local running Actors.
* @extends actor * @extends actor
*/ */
class local_actor : public extend<actor,local_actor>::with<memory_cached> { class local_actor : public extend<actor>::with<memory_cached> {
typedef combined_type super; typedef combined_type super;
...@@ -329,11 +329,11 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> { ...@@ -329,11 +329,11 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
std::vector<message_id> m_pending_responses; std::vector<message_id> m_pending_responses;
// "default value" for m_current_node // "default value" for m_current_node
detail::recursive_queue_node m_dummy_node; mailbox_element m_dummy_node;
// points to m_dummy_node if no callback is currently invoked, // points to m_dummy_node if no callback is currently invoked,
// points to the node under processing otherwise // points to the node under processing otherwise
detail::recursive_queue_node* m_current_node; mailbox_element* m_current_node;
// {group => subscription} map of all joined groups // {group => subscription} map of all joined groups
std::map<group_ptr, group::subscription> m_subscriptions; std::map<group_ptr, group::subscription> m_subscriptions;
......
...@@ -33,10 +33,9 @@ ...@@ -33,10 +33,9 @@
#include <type_traits> #include <type_traits>
#include "cppa/mailbox_element.hpp"
#include "cppa/detail/sync_request_bouncer.hpp" #include "cppa/detail/sync_request_bouncer.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/intrusive/single_reader_queue.hpp" #include "cppa/intrusive/single_reader_queue.hpp"
#include "cppa/intrusive/blocking_single_reader_queue.hpp"
namespace cppa { namespace cppa {
...@@ -61,14 +60,7 @@ class mailbox_based : public Base { ...@@ -61,14 +60,7 @@ class mailbox_based : public Base {
typedef mailbox_based combined_type; typedef mailbox_based combined_type;
typedef detail::recursive_queue_node mailbox_element; typedef intrusive::single_reader_queue<mailbox_element,del> mailbox_type;
typedef typename std::conditional<
has_blocking_receive<Subtype>::value,
intrusive::blocking_single_reader_queue<mailbox_element,del>,
intrusive::single_reader_queue<mailbox_element,del>
>::type
mailbox_type;
template<typename... Ts> template<typename... Ts>
mailbox_based(Ts&&... args) : Base(std::forward<Ts>(args)...) { } mailbox_based(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
...@@ -86,10 +78,6 @@ class mailbox_based : public Base { ...@@ -86,10 +78,6 @@ class mailbox_based : public Base {
mailbox_type m_mailbox; mailbox_type m_mailbox;
private:
inline Subtype* dthis() { return static_cast<Subtype*>(this); }
}; };
} // namespace cppa } // namespace cppa
......
...@@ -34,24 +34,25 @@ ...@@ -34,24 +34,25 @@
#include <cstdint> #include <cstdint>
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/extend.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/message_id.hpp" #include "cppa/message_id.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/memory_cached.hpp" #include "cppa/memory_cached.hpp"
// needs access to constructor + destructor to initialize m_dummy_node // needs access to constructor + destructor to initialize m_dummy_node
namespace cppa { class local_actor; } namespace cppa {
namespace cppa { namespace detail { class local_actor;
class recursive_queue_node : public memory_cached<memory_managed,recursive_queue_node> { class mailbox_element : public extend<memory_managed>::with<memory_cached> {
friend class memory; friend class local_actor;
friend class ::cppa::local_actor; friend class detail::memory;
public: public:
typedef recursive_queue_node* pointer; typedef mailbox_element* pointer;
pointer next; // intrusive next pointer pointer next; // intrusive next pointer
bool marked; // denotes if this node is currently processed bool marked; // denotes if this node is currently processed
...@@ -59,26 +60,26 @@ class recursive_queue_node : public memory_cached<memory_managed,recursive_queue ...@@ -59,26 +60,26 @@ class recursive_queue_node : public memory_cached<memory_managed,recursive_queue
any_tuple msg; // 'content field' any_tuple msg; // 'content field'
message_id mid; message_id mid;
recursive_queue_node(recursive_queue_node&&) = delete; mailbox_element(mailbox_element&&) = delete;
recursive_queue_node(const recursive_queue_node&) = delete; mailbox_element(const mailbox_element&) = delete;
recursive_queue_node& operator=(recursive_queue_node&&) = delete; mailbox_element& operator=(mailbox_element&&) = delete;
recursive_queue_node& operator=(const recursive_queue_node&) = delete; mailbox_element& operator=(const mailbox_element&) = delete;
template<typename... Ts> template<typename... Ts>
inline static recursive_queue_node* create(Ts&&... args) { inline static mailbox_element* create(Ts&&... args) {
return memory::create<recursive_queue_node>(std::forward<Ts>(args)...); return detail::memory::create<mailbox_element>(std::forward<Ts>(args)...);
} }
private: private:
recursive_queue_node() = default; mailbox_element() = default;
recursive_queue_node(const actor_ptr& sptr, mailbox_element(const actor_ptr& sptr,
any_tuple data, any_tuple data,
message_id id = message_id{}); message_id id = message_id{});
}; };
} } // namespace cppa::detail } // namespace cppa
#endif // CPPA_RECURSIVE_QUEUE_NODE_HPP #endif // CPPA_RECURSIVE_QUEUE_NODE_HPP
...@@ -51,16 +51,10 @@ struct match_helper { ...@@ -51,16 +51,10 @@ struct match_helper {
any_tuple tup; any_tuple tup;
match_helper(any_tuple t) : tup(std::move(t)) { } match_helper(any_tuple t) : tup(std::move(t)) { }
match_helper(match_helper&&) = default; match_helper(match_helper&&) = default;
/* template<typename... Ts>
void operator()(partial_function&& arg) { bool operator()(Ts&&... args) {
partial_function tmp{std::move(arg)}; static_assert(sizeof...(Ts) > 0, "at least one argument required");
tmp(tup); auto tmp = match_expr_convert(std::forward<Ts>(args)...);
}
*/
template<class Arg0, class... Args>
bool operator()(Arg0&& arg0, Args&&... args) {
auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...);
static_assert(std::is_same<partial_function, decltype(tmp)>::value, static_assert(std::is_same<partial_function, decltype(tmp)>::value,
"match statement contains timeout"); "match statement contains timeout");
return tmp(tup); return tmp(tup);
...@@ -86,20 +80,15 @@ class match_each_helper { ...@@ -86,20 +80,15 @@ class match_each_helper {
match_each_helper(Iterator first, Iterator last, Projection proj) match_each_helper(Iterator first, Iterator last, Projection proj)
: i(first), e(last), p(proj) { } : i(first), e(last), p(proj) { }
template<typename... Cases> template<typename... Ts>
void operator()(match_expr<Cases...> expr) { void operator()(Ts&&... args) {
static_assert(sizeof...(Ts) > 0, "at least one argument required");
auto expr = match_expr_collect(std::forward<Ts>(args)...);
for (; i != e; ++i) { for (; i != e; ++i) {
expr(p(*i)); expr(p(*i));
} }
} }
template<class Arg0, class Arg1, class... Args>
void operator()(Arg0&& arg0, Arg1&& arg1, Args&&... args) {
(*this)(match_expr_collect(std::forward<Arg0>(arg0),
std::forward<Arg1>(arg1),
std::forward<Args>(args)...));
}
private: private:
Iterator i; Iterator i;
...@@ -126,20 +115,15 @@ class match_for_helper { ...@@ -126,20 +115,15 @@ class match_for_helper {
match_for_helper(Iterator first, Predicate p, Advance a = Advance(), Projection pj = Projection()) match_for_helper(Iterator first, Predicate p, Advance a = Advance(), Projection pj = Projection())
: i(first), adv(a), pred(p), proj(pj) { } : i(first), adv(a), pred(p), proj(pj) { }
template<typename... Cases> template<typename... Ts>
void operator()(match_expr<Cases...> expr) { void operator()(Ts&&... args) {
static_assert(sizeof...(Ts) > 0, "at least one argument required");
auto expr = match_expr_collect(std::forward<Ts>(args)...);
for (; pred(i); adv(i)) { for (; pred(i); adv(i)) {
expr(proj(*i)); expr(proj(*i));
} }
} }
template<class Arg0, class Arg1, class... Args>
void operator()(Arg0&& arg0, Arg1&& arg1, Args&&... args) {
(*this)(match_expr_collect(std::forward<Arg0>(arg0),
std::forward<Arg1>(arg1),
std::forward<Args>(args)...));
}
private: private:
Iterator i; Iterator i;
...@@ -199,8 +183,8 @@ struct unwind_and_call<Size, Size> { ...@@ -199,8 +183,8 @@ struct unwind_and_call<Size, Size> {
return target.first.invoke(target.second, sub_result, std::forward<Unwinded>(args)...); return target.first.invoke(target.second, sub_result, std::forward<Unwinded>(args)...);
} }
template<typename T, typename... Args> template<typename T, typename... Ts>
static inline bool _(std::vector<T>&, Args&&...) { return false; } static inline bool _(std::vector<T>&, Ts&&...) { return false; }
}; };
...@@ -272,34 +256,18 @@ class stream_matcher { ...@@ -272,34 +256,18 @@ class stream_matcher {
stream_matcher(iter first, iter last) : m_pos(first), m_end(last) { } stream_matcher(iter first, iter last) : m_pos(first), m_end(last) { }
template<typename... Cases> template<typename... Ts>
bool operator()(match_expr<Cases...>& expr) { bool operator()(Ts&&... args) {
auto expr = match_expr_collect(std::forward<Ts>(args)...);
typedef decltype(expr) expr_type;
while (m_pos != m_end) { while (m_pos != m_end) {
if (!unwind_and_call<0, util::tl_size<typename match_expr<Cases...>::cases_list>::value>::_(m_cache, m_pos, m_end, expr)) { if (!unwind_and_call<0, util::tl_size<typename expr_type::cases_list>::value>::_(m_cache, m_pos, m_end, expr)) {
return false; return false;
} }
} }
return true; return true;
} }
template<typename... Cases>
bool operator()(match_expr<Cases...>&& expr) {
auto tmp = std::move(expr);
return (*this)(tmp);
}
template<typename... Cases>
bool operator()(const match_expr<Cases...>& expr) {
auto tmp = expr;
return (*this)(tmp);
}
template<typename Arg0, typename... Args>
bool operator()(Arg0&& arg0, Args&&... args) {
return (*this)(match_expr_collect(std::forward<Arg0>(arg0),
std::forward<Args>(args)...));
}
private: private:
iter m_pos; iter m_pos;
......
...@@ -44,6 +44,8 @@ ...@@ -44,6 +44,8 @@
#include "cppa/util/disjunction.hpp" #include "cppa/util/disjunction.hpp"
#include "cppa/util/left_or_right.hpp" #include "cppa/util/left_or_right.hpp"
#include "cppa/util/deduce_ref_type.hpp" #include "cppa/util/deduce_ref_type.hpp"
#include "cppa/util/get_result_type.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/matches.hpp" #include "cppa/detail/matches.hpp"
#include "cppa/detail/projection.hpp" #include "cppa/detail/projection.hpp"
...@@ -197,10 +199,10 @@ struct invoke_policy_impl<wildcard_position::nil, ...@@ -197,10 +199,10 @@ struct invoke_policy_impl<wildcard_position::nil,
>::type* = 0) { >::type* = 0) {
if (arg_types == typeid(util::type_list<Ts...>)) { if (arg_types == typeid(util::type_list<Ts...>)) {
if (native_arg) { if (native_arg) {
typedef typename util::if_else_c< typedef typename std::conditional<
std::is_const<PtrType>::value, std::is_const<PtrType>::value,
const native_data_type*, const native_data_type*,
util::wrapped<native_data_type*> native_data_type*
>::type >::type
cast_type; cast_type;
auto arg = reinterpret_cast<cast_type>(native_arg); auto arg = reinterpret_cast<cast_type>(native_arg);
...@@ -356,9 +358,9 @@ struct invoke_policy ...@@ -356,9 +358,9 @@ struct invoke_policy
template<class Pattern, class Projection, class PartialFun> template<class Pattern, class Projection, class PartialFun>
struct projection_partial_function_pair : std::pair<Projection,PartialFun> { struct projection_partial_function_pair : std::pair<Projection,PartialFun> {
template<typename... Args> template<typename... Ts>
projection_partial_function_pair(Args&&... args) projection_partial_function_pair(Ts&&... args)
: std::pair<Projection,PartialFun>(std::forward<Args>(args)...) { } : std::pair<Projection,PartialFun>(std::forward<Ts>(args)...) { }
typedef Pattern pattern_type; typedef Pattern pattern_type;
}; };
...@@ -558,11 +560,6 @@ inline std::uint64_t calc_bitmask(PPFPs& fs, long_constant<N>, const std::type_i ...@@ -558,11 +560,6 @@ inline std::uint64_t calc_bitmask(PPFPs& fs, long_constant<N>, const std::type_i
return result | calc_bitmask(fs, long_constant<N-1l>(), tinf, tup); return result | calc_bitmask(fs, long_constant<N-1l>(), tinf, tup);
} }
template<typename T>
struct is_manipulator_case {
static constexpr bool value = T::second_type::manipulates_args;
};
template<bool IsManipulator, typename T0, typename T1> template<bool IsManipulator, typename T0, typename T1>
struct mexpr_fwd_ { struct mexpr_fwd_ {
typedef T1 type; typedef T1 type;
...@@ -620,29 +617,35 @@ inline const void* fetch_native_data(const Ptr& ptr, std::false_type) { ...@@ -620,29 +617,35 @@ inline const void* fetch_native_data(const Ptr& ptr, std::false_type) {
namespace cppa { namespace cppa {
template<class... Cases> /** @cond PRIVATE */
template<typename T>
struct is_manipulator_case {
static constexpr bool value = T::second_type::manipulates_args;
};
/** @endcond */
/**
* @brief A match expression encapsulating cases <tt>Cs...</tt>.
*/
template<class... Cs>
class match_expr { class match_expr {
static_assert(sizeof...(Cases) < 64, "too many functions"); static_assert(sizeof...(Cs) < 64, "too many functions");
public: public:
static constexpr bool may_have_timeout = false; static constexpr bool may_have_timeout = false;
typedef util::type_list<Cases...> cases_list; typedef util::type_list<Cs...> cases_list;
static constexpr size_t num_cases = sizeof...(Cases); static constexpr bool has_manipulator = util::tl_exists<cases_list,is_manipulator_case>::value;
static constexpr bool has_manipulator = typedef detail::long_constant<sizeof...(Cs)-1l> idx_token_type;
util::tl_exists<cases_list,detail::is_manipulator_case>::value;
typedef detail::long_constant<static_cast<long>(num_cases)-1l>
idx_token_type;
static constexpr idx_token_type idx_token = idx_token_type{}; static constexpr idx_token_type idx_token = idx_token_type{};
template<typename... Args> template<typename... Ts>
match_expr(Args&&... args) : m_cases(std::forward<Args>(args)...) { match_expr(Ts&&... args) : m_cases(std::forward<Ts>(args)...) {
init(); init();
} }
...@@ -692,31 +695,34 @@ class match_expr { ...@@ -692,31 +695,34 @@ class match_expr {
return invoke_impl(tmp); return invoke_impl(tmp);
} }
template<typename... Args> template<typename... Ts>
bool operator()(Args&&... args) { bool operator()(Ts&&... args) {
// wraps and applies implicit conversions to args
typedef detail::tdata< typedef detail::tdata<
typename detail::mexpr_fwd<has_manipulator,Args>::type...> typename detail::mexpr_fwd<
has_manipulator,
Ts
>::type...
>
tuple_type; tuple_type;
// applies implicit conversions etc tuple_type tup{std::forward<Ts>(args)...};
tuple_type tup{std::forward<Args>(args)...};
auto& type_token = typeid(typename tuple_type::types); auto& type_token = typeid(typename tuple_type::types);
auto bitmask = get_cache_entry(&type_token, tup); auto bitmask = get_cache_entry(&type_token, tup);
// ref_type keeps track of whether this match_expr is a mutator
typedef typename util::if_else_c< typedef typename std::conditional<
has_manipulator, has_manipulator,
tuple_type&, tuple_type&,
const util::wrapped<tuple_type&> const tuple_type&
>::type >::type
ref_type; ref_type;
// same here
typedef typename util::if_else_c< typedef typename std::conditional<
has_manipulator, has_manipulator,
void*, void*,
util::wrapped<const void*> const void*
>::type >::type
ptr_type; ptr_type;
// iterate over cases and return if any case was invoked
ptr_type ptr_arg = nullptr;
bool invoke_result = true; bool invoke_result = true;
bool unroll_result = unroll_expr(m_cases, bool unroll_result = unroll_expr(m_cases,
invoke_result, invoke_result,
...@@ -724,21 +730,20 @@ class match_expr { ...@@ -724,21 +730,20 @@ class match_expr {
idx_token, idx_token,
type_token, type_token,
false, // not dynamically_typed false, // not dynamically_typed
ptr_arg, static_cast<ptr_type>(nullptr),
static_cast<ref_type>(tup)); static_cast<ref_type>(tup));
return unroll_result && invoke_result; return unroll_result && invoke_result;
} }
template<class... OtherCases> template<class... Ds>
match_expr<Cases...,OtherCases...> match_expr<Cs...,Ds...> or_else(const match_expr<Ds...>& other) const {
or_else(const match_expr<OtherCases...>& other) const { detail::tdata<util::rebindable_reference<const Cs>...,
detail::tdata<ge_reference_wrapper<Cases>..., util::rebindable_reference<const Ds>... > all_cases;
ge_reference_wrapper<OtherCases>... > all_cases; rebind_tdata(all_cases, m_cases, other.cases());
collect_tdata(all_cases, m_cases, other.cases());
return {all_cases}; return {all_cases};
} }
inline const detail::tdata<Cases...>& cases() const { inline const detail::tdata<Cs...>& cases() const {
return m_cases; return m_cases;
} }
...@@ -770,7 +775,7 @@ class match_expr { ...@@ -770,7 +775,7 @@ class match_expr {
// structure: tdata< tdata<type_list<...>, ...>, // structure: tdata< tdata<type_list<...>, ...>,
// tdata<type_list<...>, ...>, // tdata<type_list<...>, ...>,
// ...> // ...>
detail::tdata<Cases...> m_cases; detail::tdata<Cs...> m_cases;
static constexpr size_t cache_size = 10; static constexpr size_t cache_size = 10;
...@@ -828,13 +833,14 @@ class match_expr { ...@@ -828,13 +833,14 @@ class match_expr {
bool invoke_impl(Tuple& tup) { bool invoke_impl(Tuple& tup) {
std::integral_constant<bool,has_manipulator> mutator_token; std::integral_constant<bool,has_manipulator> mutator_token;
// returns either a reference or a new object // returns either a reference or a new object
decltype(detail::detach_if_needed(tup, mutator_token)) tref = detail::detach_if_needed(tup, mutator_token); typedef decltype(detail::detach_if_needed(tup, mutator_token)) detached;
detached tref = detail::detach_if_needed(tup, mutator_token);
auto& vals = tref.vals(); auto& vals = tref.vals();
auto ndp = fetch_native_data(vals, mutator_token); auto ndp = fetch_native_data(vals, mutator_token);
auto token_ptr = vals->type_token(); auto token_ptr = vals->type_token();
auto bitmask = get_cache_entry(token_ptr, *vals); auto bitmask = get_cache_entry(token_ptr, *vals);
auto dynamically_typed = vals->dynamically_typed(); auto dynamically_typed = vals->dynamically_typed();
bool invoke_result = true; // maybe set to false by an invoked functor bool invoke_result = true; // may be set to false by an invoked functor
bool unroll_result = unroll_expr(m_cases, bool unroll_result = unroll_expr(m_cases,
invoke_result, invoke_result,
bitmask, bitmask,
...@@ -851,9 +857,9 @@ class match_expr { ...@@ -851,9 +857,9 @@ class match_expr {
template<class List> template<class List>
struct match_expr_from_type_list; struct match_expr_from_type_list;
template<typename... Args> template<typename... Ts>
struct match_expr_from_type_list<util::type_list<Args...> > { struct match_expr_from_type_list<util::type_list<Ts...> > {
typedef match_expr<Args...> type; typedef match_expr<Ts...> type;
}; };
template<typename... Lhs, typename... Rhs> template<typename... Lhs, typename... Rhs>
...@@ -862,32 +868,41 @@ inline match_expr<Lhs...,Rhs...> operator,(const match_expr<Lhs...>& lhs, ...@@ -862,32 +868,41 @@ 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... Cs>
match_expr<Cs...>& match_expr_collect(match_expr<Cs...>& arg) {
return arg;
}
template<typename... Cs>
match_expr<Cs...>&& match_expr_collect(match_expr<Cs...>&& arg) {
return std::move(arg);
}
template<typename... Cs>
const match_expr<Cs...>& match_expr_collect(const match_expr<Cs...>& arg) {
return arg;
}
template<typename T, typename... Ts>
typename match_expr_from_type_list< typename match_expr_from_type_list<
typename util::tl_concat< typename util::tl_concat<
typename Arg0::cases_list, typename T::cases_list,
typename Args::cases_list... typename Ts::cases_list...
>::type
>::type
match_expr_collect(const Arg0& arg0, const Args&... args) {
typedef typename match_expr_from_type_list<
typename util::tl_concat<
typename Arg0::cases_list,
typename Args::cases_list...
>::type >::type
>::type >::type
combined_type; match_expr_collect(const T& arg, const Ts&... args) {
typename detail::tdata_from_type_list< typename detail::tdata_from_type_list<
typename util::tl_map< typename util::tl_map<
typename util::tl_concat< typename util::tl_concat<
typename Arg0::cases_list, typename T::cases_list,
typename Args::cases_list... typename Ts::cases_list...
>::type, >::type,
gref_wrapped gref_wrapped
>::type >::type
>::type >::type
all_cases; all_cases;
detail::collect_tdata(all_cases, arg0.cases(), args.cases()...); detail::rebind_tdata(all_cases, arg.cases(), args.cases()...);
return {all_cases}; return {all_cases};
} }
...@@ -921,7 +936,7 @@ behavior_impl* concat_rec(const Data& data, Token, const T& arg, const Ts&... ar ...@@ -921,7 +936,7 @@ behavior_impl* concat_rec(const Data& data, Token, const T& arg, const Ts&... ar
>::type >::type
next_data; next_data;
next_token_type next_token; next_token_type next_token;
collect_tdata(next_data, data, arg.cases()); rebind_tdata(next_data, data, arg.cases());
return concat_rec(next_data, next_token, args...); return concat_rec(next_data, next_token, args...);
} }
...@@ -940,7 +955,7 @@ behavior_impl* concat_expr(with_timeout, const T& arg, const Ts&... args) { ...@@ -940,7 +955,7 @@ behavior_impl* concat_expr(with_timeout, const T& arg, const Ts&... args) {
>::type >::type
>::type >::type
wrapper; wrapper;
detail::collect_tdata(wrapper, arg.cases()); detail::rebind_tdata(wrapper, arg.cases());
return concat_rec(wrapper, typename T::cases_list{}, args...); return concat_rec(wrapper, typename T::cases_list{}, args...);
} }
...@@ -967,7 +982,7 @@ behavior_impl* concat_expr(without_timeout, const T& arg, const Ts&... args) { ...@@ -967,7 +982,7 @@ behavior_impl* concat_expr(without_timeout, const T& arg, const Ts&... args) {
combined_type; combined_type;
auto lvoid = []() { }; auto lvoid = []() { };
typedef default_behavior_impl<combined_type,decltype(lvoid)> impl_type; typedef default_behavior_impl<combined_type,decltype(lvoid)> impl_type;
collect_tdata(all_cases, arg.cases(), args.cases()...); rebind_tdata(all_cases, arg.cases(), args.cases()...);
return new impl_type(all_cases, util::duration{}, lvoid); return new impl_type(all_cases, util::duration{}, lvoid);
} }
......
...@@ -80,20 +80,20 @@ class message_future { ...@@ -80,20 +80,20 @@ class message_future {
/** /**
* @brief Sets @p mexpr as event-handler for the response message. * @brief Sets @p mexpr as event-handler for the response message.
*/ */
template<typename... Cases, typename... Args> template<typename... Cs, typename... Ts>
continue_helper then(const match_expr<Cases...>& a0, const Args&... as) { continue_helper then(const match_expr<Cs...>& arg, const Ts&... args) {
check_consistency(); check_consistency();
self->become_waiting_for(match_expr_convert(a0, as...), m_mid); self->become_waiting_for(match_expr_convert(arg, args...), m_mid);
return {m_mid}; return {m_mid};
} }
/** /**
* @brief Blocks until the response arrives and then executes @p mexpr. * @brief Blocks until the response arrives and then executes @p mexpr.
*/ */
template<typename... Cases, typename... Args> template<typename... Cs, typename... Ts>
void await(const match_expr<Cases...>& arg0, const Args&... args) { void await(const match_expr<Cs...>& arg, const Ts&... args) {
check_consistency(); check_consistency();
self->dequeue_response(match_expr_convert(arg0, args...), m_mid); self->dequeue_response(match_expr_convert(arg, args...), m_mid);
} }
/** /**
...@@ -186,9 +186,9 @@ class sync_receive_helper { ...@@ -186,9 +186,9 @@ class sync_receive_helper {
inline sync_receive_helper(const message_future& mf) : m_mf(mf) { } inline sync_receive_helper(const message_future& mf) : m_mf(mf) { }
template<typename... Args> template<typename... Ts>
inline void operator()(Args&&... args) { inline void operator()(Ts&&... args) {
m_mf.await(std::forward<Args>(args)...); m_mf.await(std::forward<Ts>(args)...);
} }
private: private:
......
...@@ -48,8 +48,7 @@ class basic_memory_cache; ...@@ -48,8 +48,7 @@ class basic_memory_cache;
namespace cppa { namespace network { namespace cppa { namespace network {
class sync_request_info : public extend<memory_managed,sync_request_info>:: class sync_request_info : public extend<memory_managed>::with<memory_cached> {
with<memory_cached> {
friend class detail::memory; friend class detail::memory;
......
...@@ -45,9 +45,9 @@ class default_message_queue : public ref_counted { ...@@ -45,9 +45,9 @@ class default_message_queue : public ref_counted {
typedef value_type& reference; typedef value_type& reference;
template<typename... Args> template<typename... Ts>
void emplace(Args&&... args) { void emplace(Ts&&... args) {
m_impl.emplace_back(std::forward<Args>(args)...); m_impl.emplace_back(std::forward<Ts>(args)...);
} }
inline bool empty() const { return m_impl.empty(); } inline bool empty() const { return m_impl.empty(); }
......
...@@ -146,15 +146,6 @@ class default_peer : public continuable_io { ...@@ -146,15 +146,6 @@ class default_peer : public continuable_io {
enqueue({nullptr, nullptr}, msg); enqueue({nullptr, nullptr}, msg);
} }
/*
template<typename Arg0, typename Arg1, typename... Args>
inline void enqueue(Arg0&& arg0, Arg1&& arg1, Args&&... args) {
enqueue(make_any_tuple(std::forward<Arg0>(arg0),
std::forward<Arg1>(arg1),
std::forward<Args>(args)...));
}
*/
}; };
typedef intrusive_ptr<default_peer> default_peer_ptr; typedef intrusive_ptr<default_peer> default_peer_ptr;
......
...@@ -136,8 +136,8 @@ struct rvalue_builder { ...@@ -136,8 +136,8 @@ struct rvalue_builder {
rvalue_builder() = default; rvalue_builder() = default;
template<typename... Args> template<typename... Ts>
rvalue_builder(rvalue_builder_args_ctor, const Args&... args) rvalue_builder(rvalue_builder_args_ctor, const Ts&... args)
: m_guard(args...) : m_guard(args...)
, m_funs(args...) { , m_funs(args...) {
} }
...@@ -262,8 +262,8 @@ __unspecified__ val(); ...@@ -262,8 +262,8 @@ __unspecified__ val();
* This overload can be used with the wildcards {@link cppa::val val}, * This overload can be used with the wildcards {@link cppa::val val},
* {@link cppa::any_vals any_vals} and {@link cppa::arg_match arg_match}. * {@link cppa::any_vals any_vals} and {@link cppa::arg_match arg_match}.
*/ */
template<typename Arg0, typename... Args> template<typename T, typename... Ts>
__unspecified__ on(const Arg0& arg0, const Args&... args); __unspecified__ on(const T& arg, const Ts&... args);
/** /**
* @brief Left-hand side of a partial function expression that matches types. * @brief Left-hand side of a partial function expression that matches types.
...@@ -297,13 +297,13 @@ typedef typename detail::boxed<util::arg_match_t>::type boxed_arg_match_t; ...@@ -297,13 +297,13 @@ typedef typename detail::boxed<util::arg_match_t>::type boxed_arg_match_t;
constexpr boxed_arg_match_t arg_match = boxed_arg_match_t(); constexpr boxed_arg_match_t arg_match = boxed_arg_match_t();
template<typename Arg0, typename... Args> template<typename T, typename... Ts>
detail::rvalue_builder< detail::rvalue_builder<
detail::value_guard< detail::value_guard<
typename util::tl_filter_not< typename util::tl_filter_not<
typename util::tl_trim< typename util::tl_trim<
typename util::tl_map< typename util::tl_map<
util::type_list<Arg0, Args...>, util::type_list<T,Ts...>,
detail::boxed_and_callable_to_void, detail::boxed_and_callable_to_void,
detail::implicit_conversions detail::implicit_conversions
>::type >::type
...@@ -312,13 +312,13 @@ detail::rvalue_builder< ...@@ -312,13 +312,13 @@ detail::rvalue_builder<
>::type >::type
>, >,
typename util::tl_map< typename util::tl_map<
util::type_list<Arg0, Args...>, util::type_list<T,Ts...>,
detail::boxed_and_not_callable_to_void detail::boxed_and_not_callable_to_void
>::type, >::type,
util::type_list<typename detail::pattern_type<Arg0>::type, util::type_list<typename detail::pattern_type<T>::type,
typename detail::pattern_type<Args>::type...> > typename detail::pattern_type<Ts>::type...> >
on(const Arg0& arg0, const Args&... args) { on(const T& arg, const Ts&... args) {
return {detail::rvalue_builder_args_ctor{}, arg0, args...}; return {detail::rvalue_builder_args_ctor{}, arg, args...};
} }
inline detail::rvalue_builder<detail::empty_value_guard, inline detail::rvalue_builder<detail::empty_value_guard,
......
...@@ -47,8 +47,8 @@ class actor_widget_mixin : public actor_companion_mixin<Base> { ...@@ -47,8 +47,8 @@ class actor_widget_mixin : public actor_companion_mixin<Base> {
public: public:
template<typename... Args> template<typename... Ts>
actor_widget_mixin(Args&&... args) : super(std::forward<Args>(args)...) { } actor_widget_mixin(Ts&&... args) : super(std::forward<Ts>(args)...) { }
struct event_type : public QEvent { struct event_type : public QEvent {
......
...@@ -115,8 +115,8 @@ detail::receive_while_helper<Statement> receive_while(Statement&& stmt); ...@@ -115,8 +115,8 @@ detail::receive_while_helper<Statement> receive_while(Statement&& stmt);
* @param bhvr Denotes the actor's response the next incoming message. * @param bhvr Denotes the actor's response the next incoming message.
* @returns A functor providing the @c until member function. * @returns A functor providing the @c until member function.
*/ */
template<typename... Args> template<typename... Ts>
detail::do_receive_helper do_receive(Args&&... args); detail::do_receive_helper do_receive(Ts&&... args);
/** /**
* @} * @}
......
...@@ -66,8 +66,8 @@ class sb_actor : public Base { ...@@ -66,8 +66,8 @@ class sb_actor : public Base {
protected: protected:
template<typename... Args> template<typename... Ts>
sb_actor(Args&&... args) : Base(std::forward<Args>(args)...) { } sb_actor(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
}; };
......
...@@ -38,9 +38,11 @@ ...@@ -38,9 +38,11 @@
#include "cppa/actor_state.hpp" #include "cppa/actor_state.hpp"
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
#include "cppa/mailbox_based.hpp" #include "cppa/mailbox_based.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/detail/memory.hpp" #include "cppa/detail/memory.hpp"
#include "cppa/detail/receive_policy.hpp" #include "cppa/detail/receive_policy.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/intrusive/single_reader_queue.hpp" #include "cppa/intrusive/single_reader_queue.hpp"
namespace cppa { namespace cppa {
...@@ -68,7 +70,7 @@ struct has_blocking_receive<scheduled_actor> : std::true_type { }; ...@@ -68,7 +70,7 @@ struct has_blocking_receive<scheduled_actor> : std::true_type { };
* @brief A base class for cooperatively scheduled actors. * @brief A base class for cooperatively scheduled actors.
* @extends local_actor * @extends local_actor
*/ */
class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox_based>{ class scheduled_actor : public extend<local_actor>::with<mailbox_based>{
typedef combined_type super; typedef combined_type super;
...@@ -115,6 +117,8 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox ...@@ -115,6 +117,8 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox
*/ */
inline bool is_hidden() const; inline bool is_hidden() const;
virtual void run_detached();
void enqueue(const actor_ptr&, any_tuple); void enqueue(const actor_ptr&, any_tuple);
bool chained_enqueue(const actor_ptr&, any_tuple); bool chained_enqueue(const actor_ptr&, any_tuple);
...@@ -160,8 +164,6 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox ...@@ -160,8 +164,6 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox
void cleanup(std::uint32_t reason); void cleanup(std::uint32_t reason);
typedef detail::recursive_queue_node mailbox_element;
typedef intrusive::single_reader_queue<mailbox_element,detail::disposer> typedef intrusive::single_reader_queue<mailbox_element,detail::disposer>
mailbox_type; mailbox_type;
......
...@@ -37,15 +37,18 @@ ...@@ -37,15 +37,18 @@
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/util/dptr.hpp"
#include "cppa/detail/behavior_stack.hpp" #include "cppa/detail/behavior_stack.hpp"
#include "cppa/detail/receive_policy.hpp" #include "cppa/detail/receive_policy.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
namespace cppa { namespace cppa {
/** /**
* @tparam Base Either @p scheduled or @p threaded. * @brief An actor that uses the blocking API of @p libcppa and thus needs
* its own stack.
*/ */
template<class Base, class Subtype> template<class Base, class Subtype>
class stacked : public Base { class stacked : public Base {
...@@ -62,20 +65,17 @@ class stacked : public Base { ...@@ -62,20 +65,17 @@ class stacked : public Base {
static constexpr auto receive_flag = detail::rp_nestable; static constexpr auto receive_flag = detail::rp_nestable;
virtual void dequeue(behavior& bhvr) { virtual void dequeue(behavior& bhvr) {
m_recv_policy.receive(dthis(), bhvr); m_recv_policy.receive(util::dptr<Subtype>(this), bhvr);
} }
virtual void dequeue_response(behavior& bhvr, message_id request_id) { virtual void dequeue_response(behavior& bhvr, message_id request_id) {
m_recv_policy.receive(dthis(), bhvr, request_id); m_recv_policy.receive(util::dptr<Subtype>(this), bhvr, request_id);
} }
virtual void run() { virtual void run() {
if (!dthis()->m_bhvr_stack.empty()) { auto dthis = util::dptr<Subtype>(this);
dthis()->exec_behavior_stack(); if (!dthis->m_bhvr_stack.empty()) dthis->exec_behavior_stack();
} if (m_behavior) m_behavior();
if (m_behavior) {
m_behavior();
}
} }
inline void set_behavior(std::function<void()> fun) { inline void set_behavior(std::function<void()> fun) {
...@@ -87,11 +87,15 @@ class stacked : public Base { ...@@ -87,11 +87,15 @@ class stacked : public Base {
throw actor_exited(reason); throw actor_exited(reason);
} }
virtual void exec_behavior_stack() {
this->m_bhvr_stack.exec(m_recv_policy, util::dptr<Subtype>(this));
}
protected: protected:
template<typename... Args> template<typename... Ts>
stacked(std::function<void()> fun, Args&&... args) stacked(std::function<void()> fun, Ts&&... args)
: Base(std::forward<Args>(args)...), m_behavior(std::move(fun)) { } : Base(std::forward<Ts>(args)...), m_behavior(std::move(fun)) { }
virtual void do_become(behavior&& bhvr, bool discard_old) { virtual void do_become(behavior&& bhvr, bool discard_old) {
become_impl(std::move(bhvr), discard_old, message_id()); become_impl(std::move(bhvr), discard_old, message_id());
...@@ -102,40 +106,27 @@ class stacked : public Base { ...@@ -102,40 +106,27 @@ class stacked : public Base {
} }
virtual bool has_behavior() { virtual bool has_behavior() {
return static_cast<bool>(m_behavior) || !dthis()->m_bhvr_stack.empty(); return static_cast<bool>(m_behavior)
|| !util::dptr<Subtype>(this)->m_bhvr_stack.empty();
} }
typedef std::chrono::time_point<std::chrono::high_resolution_clock>
timeout_type;
virtual timeout_type init_timeout(const util::duration& rel_time) = 0;
virtual detail::recursive_queue_node* await_message() = 0;
virtual detail::recursive_queue_node* await_message(const timeout_type& abs_time) = 0;
private:
std::function<void()> m_behavior; std::function<void()> m_behavior;
detail::receive_policy m_recv_policy; detail::receive_policy m_recv_policy;
private:
void become_impl(behavior&& bhvr, bool discard_old, message_id mid) { void become_impl(behavior&& bhvr, bool discard_old, message_id mid) {
auto dthis = util::dptr<Subtype>(this);
if (bhvr.timeout().valid()) { if (bhvr.timeout().valid()) {
dthis()->reset_timeout(); dthis->reset_timeout();
dthis()->request_timeout(bhvr.timeout()); dthis->request_timeout(bhvr.timeout());
} }
if (!dthis()->m_bhvr_stack.empty() && discard_old) { if (!dthis->m_bhvr_stack.empty() && discard_old) {
dthis()->m_bhvr_stack.pop_async_back(); dthis->m_bhvr_stack.pop_async_back();
} }
dthis()->m_bhvr_stack.push_back(std::move(bhvr), mid); dthis->m_bhvr_stack.push_back(std::move(bhvr), mid);
} }
virtual void exec_behavior_stack() {
this->m_bhvr_stack.exec(m_recv_policy, dthis());
}
inline Subtype* dthis() { return static_cast<Subtype*>(this); }
}; };
} // namespace cppa } // namespace cppa
......
...@@ -43,18 +43,16 @@ ...@@ -43,18 +43,16 @@
#include <cstdint> #include <cstdint>
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
#include "cppa/either.hpp"
#include "cppa/extend.hpp" #include "cppa/extend.hpp"
#include "cppa/stacked.hpp" #include "cppa/stacked.hpp"
#include "cppa/threaded.hpp"
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
#include "cppa/exit_reason.hpp" #include "cppa/exit_reason.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/mailbox_based.hpp" #include "cppa/mailbox_based.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/detail/receive_policy.hpp" #include "cppa/detail/receive_policy.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/intrusive/blocking_single_reader_queue.hpp"
namespace cppa { namespace cppa {
...@@ -66,10 +64,10 @@ template<> ...@@ -66,10 +64,10 @@ template<>
struct has_blocking_receive<thread_mapped_actor> : std::true_type { }; struct has_blocking_receive<thread_mapped_actor> : std::true_type { };
/** /**
* @brief An actor running in its own thread. * @brief An actor using the blocking API running in its own thread.
* @extends local_actor * @extends local_actor
*/ */
class thread_mapped_actor : public extend<local_actor,thread_mapped_actor>::with<stacked,mailbox_based> { class thread_mapped_actor : public extend<local_actor,thread_mapped_actor>::with<mailbox_based,stacked,threaded> {
friend class self_type; // needs access to cleanup() friend class self_type; // needs access to cleanup()
friend class scheduler_helper; // needs access to mailbox friend class scheduler_helper; // needs access to mailbox
...@@ -88,40 +86,14 @@ class thread_mapped_actor : public extend<local_actor,thread_mapped_actor>::with ...@@ -88,40 +86,14 @@ class thread_mapped_actor : public extend<local_actor,thread_mapped_actor>::with
bool initialized() const; bool initialized() const;
void enqueue(const actor_ptr& sender, any_tuple msg);
void sync_enqueue(const actor_ptr& sender, message_id id, any_tuple msg);
inline void reset_timeout() { }
inline void request_timeout(const util::duration&) { }
inline void handle_timeout(behavior& bhvr) { bhvr.handle_timeout(); }
inline void pop_timeout() { }
inline void push_timeout() { }
inline bool waits_for_timeout(std::uint32_t) { return false; }
protected: protected:
typedef detail::recursive_queue_node mailbox_element;
typedef intrusive::blocking_single_reader_queue<mailbox_element,detail::disposer>
mailbox_type;
void cleanup(std::uint32_t reason); void cleanup(std::uint32_t reason);
private: private:
timeout_type init_timeout(const util::duration& rel_time);
detail::recursive_queue_node* await_message();
detail::recursive_queue_node* await_message(const timeout_type& abs_time);
bool m_initialized; bool m_initialized;
protected:
mailbox_type m_mailbox;
}; };
typedef intrusive_ptr<thread_mapped_actor> thread_mapped_actor_ptr; typedef intrusive_ptr<thread_mapped_actor> thread_mapped_actor_ptr;
......
...@@ -28,71 +28,142 @@ ...@@ -28,71 +28,142 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_STATIC_FOREACH_HPP #ifndef CPPA_THREADED_HPP
#define CPPA_STATIC_FOREACH_HPP #define CPPA_THREADED_HPP
#include "cppa/get.hpp" #include <mutex>
#include <chrono>
namespace cppa { namespace util { #include <condition_variable>
template<bool BeginLessEnd, size_t Begin, size_t End> #include "cppa/mailbox_element.hpp"
struct static_foreach_impl {
template<typename Container, typename Fun, typename... Args> #include "cppa/util/dptr.hpp"
static inline void _(const Container& c, Fun& f, Args&&... args) {
f(get<Begin>(c), std::forward<Args>(args)...); #include "cppa/detail/sync_request_bouncer.hpp"
static_foreach_impl<(Begin+1 < End), Begin+1, End>
::_(c, f, std::forward<Args>(args)...); #include "cppa/intrusive/single_reader_queue.hpp"
}
template<typename Container, typename Fun, typename... Args> namespace cppa { namespace detail { class receive_policy; } }
static inline void _ref(Container& c, Fun& f, Args&&... args) {
f(get_ref<Begin>(c), std::forward<Args>(args)...); namespace cppa {
static_foreach_impl<(Begin+1 < End), Begin+1, End>
::_ref(c, f, std::forward<Args>(args)...); template<class Base, class Subtype>
} class threaded : public Base {
template<typename Container, typename Fun, typename... Args>
static inline void _auto(Container& c, Fun& f, Args&&... args) { friend class detail::receive_policy;
_ref(c, f, std::forward<Args>(args)...);
} typedef std::unique_lock<std::mutex> lock_type;
template<typename Container, typename Fun, typename... Args>
static inline void _auto(const Container& c, Fun& f, Args&&... args) { public:
_(c, f, std::forward<Args>(args)...);
} template<typename... Ts>
template<typename Container, typename Fun, typename... Args> threaded(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
static inline bool eval(const Container& c, Fun& f, Args&&... args) {
return f(get<Begin>(c), std::forward<Args>(args)...) inline void reset_timeout() { }
&& static_foreach_impl<(Begin+1 < End), Begin+1, End>
::eval(c, f, std::forward<Args>(args)...); inline void request_timeout(const util::duration&) { }
}
template<typename Container, typename Fun, typename... Args> inline void handle_timeout(behavior& bhvr) { bhvr.handle_timeout(); }
static inline bool eval_or(const Container& c, Fun& f, Args&&... args) {
return f(get<Begin>(c), std::forward<Args>(args)...) inline void pop_timeout() { }
|| static_foreach_impl<(Begin+1 < End), Begin+1, End>
::eval_or(c, f, std::forward<Args>(args)...); inline void push_timeout() { }
inline bool waits_for_timeout(std::uint32_t) { return false; }
mailbox_element* pop() {
wait_for_data();
return this->m_mailbox.try_pop();
} }
};
template<size_t X, size_t Y> inline mailbox_element* try_pop() {
struct static_foreach_impl<false, X, Y> { return this->m_mailbox.try_pop();
template<typename... Args> }
static inline void _(Args&&...) { }
template<typename... Args> template<typename TimePoint>
static inline void _ref(Args&&...) { } mailbox_element* try_pop(const TimePoint& abs_time) {
template<typename... Args> return (timed_wait_for_data(abs_time)) ? try_pop() : nullptr;
static inline void _auto(Args&&...) { } }
template<typename... Args>
static inline bool eval(Args&&...) { return true; } bool push_back(mailbox_element* new_element) {
template<typename... Args> switch (this->m_mailbox.enqueue(new_element)) {
static inline bool eval_or(Args&&...) { return false; } case intrusive::first_enqueued: {
}; lock_type guard(m_mtx);
m_cv.notify_one();
return true;
}
default: return true;
case intrusive::queue_closed: return false;
}
}
void run_detached() {
auto dthis = util::dptr<Subtype>(this);
dthis->init();
dthis->m_bhvr_stack.exec(dthis->m_recv_policy, dthis);
dthis->on_exit();
}
protected:
typedef threaded combined_type;
virtual void enqueue(const actor_ptr& sender, any_tuple msg) {
auto ptr = this->new_mailbox_element(sender, std::move(msg));
push_back(ptr);
}
virtual void sync_enqueue(const actor_ptr& sender, message_id id, any_tuple msg) {
auto ptr = this->new_mailbox_element(sender, std::move(msg), id);
if (!push_back(ptr)) {
detail::sync_request_bouncer f{this->exit_reason()};
f(sender, id);
}
}
typedef std::chrono::high_resolution_clock::time_point timeout_type;
timeout_type init_timeout(const util::duration& rel_time) {
auto result = std::chrono::high_resolution_clock::now();
result += rel_time;
return result;
}
mailbox_element* await_message() {
return pop();
}
mailbox_element* await_message(const timeout_type& abs_time) {
return try_pop(abs_time);
}
private:
bool timed_wait_for_data(const timeout_type& abs_time) {
CPPA_REQUIRE(not this->m_mailbox.closed());
if (this->m_mailbox.empty()) {
lock_type guard(m_mtx);
while (this->m_mailbox.empty()) {
if (m_cv.wait_until(guard, abs_time) == std::cv_status::timeout) {
return false;
}
}
}
return true;
}
void wait_for_data() {
if (this->m_mailbox.empty()) {
lock_type guard(m_mtx);
while (this->m_mailbox.empty()) m_cv.wait(guard);
}
}
std::mutex m_mtx;
std::condition_variable m_cv;
/**
* @ingroup MetaProgramming
* @brief A for loop that can be used with tuples.
*/
template<size_t Begin, size_t End>
struct static_foreach : static_foreach_impl<(Begin < End), Begin, End> {
}; };
} } // namespace cppa::util } // namespace cppa
#endif // CPPA_STATIC_FOREACH_HPP #endif // CPPA_THREADED_HPP
...@@ -43,22 +43,22 @@ ...@@ -43,22 +43,22 @@
namespace cppa { namespace cppa {
template<class Expr, class Guard, typename Result, typename... Args> template<class Expr, class Guard, typename Result, typename... Ts>
class tpartial_function { class tpartial_function {
typedef typename util::get_callable_trait<Expr>::type ctrait; typedef typename util::get_callable_trait<Expr>::type ctrait;
typedef typename ctrait::arg_types ctrait_args; typedef typename ctrait::arg_types ctrait_args;
static constexpr size_t num_expr_args = util::tl_size<ctrait_args>::value; static constexpr size_t num_expr_args = util::tl_size<ctrait_args>::value;
static_assert(util::tl_exists<util::type_list<Args...>, static_assert(util::tl_exists<util::type_list<Ts...>,
std::is_rvalue_reference >::value == false, std::is_rvalue_reference >::value == false,
"partial functions using rvalue arguments are not supported"); "partial functions using rvalue arguments are not supported");
public: public:
typedef util::type_list<Args...> arg_types; typedef util::type_list<Ts...> arg_types;
static constexpr size_t num_arguments = sizeof...(Args); static constexpr size_t num_arguments = sizeof...(Ts);
static constexpr bool manipulates_args = static constexpr bool manipulates_args =
util::tl_exists<arg_types, util::is_mutable_ref>::value; util::tl_exists<arg_types, util::is_mutable_ref>::value;
...@@ -78,11 +78,11 @@ class tpartial_function { ...@@ -78,11 +78,11 @@ class tpartial_function {
tpartial_function(const tpartial_function&) = default; tpartial_function(const tpartial_function&) = default;
bool defined_at(Args... args) const { bool defined_at(Ts... args) const {
return m_guard(args...); return m_guard(args...);
} }
result_type operator()(Args... args) const { result_type operator()(Ts... args) const {
auto targs = std::forward_as_tuple(args...); auto targs = std::forward_as_tuple(args...);
auto indices = util::get_right_indices<num_expr_args>(targs); auto indices = util::get_right_indices<num_expr_args>(targs);
return util::apply_args(m_expr, targs, indices); return util::apply_args(m_expr, targs, indices);
...@@ -95,34 +95,34 @@ class tpartial_function { ...@@ -95,34 +95,34 @@ class tpartial_function {
}; };
template<class Expr, class Guard, typename Args, template<class Expr, class Guard, typename Ts,
typename Result = util::void_type, size_t Step = 0> typename Result = util::void_type, size_t Step = 0>
struct get_tpartial_function; struct get_tpartial_function;
template<class Expr, class Guard, typename... Args, typename Result> template<class Expr, class Guard, typename... Ts, typename Result>
struct get_tpartial_function<Expr, Guard, util::type_list<Args...>, Result, 1> { struct get_tpartial_function<Expr, Guard, util::type_list<Ts...>, Result, 1> {
typedef tpartial_function<Expr, Guard, Result, Args...> type; typedef tpartial_function<Expr, Guard, Result, Ts...> type;
}; };
template<class Expr, class Guard, typename... Args> template<class Expr, class Guard, typename... Ts>
struct get_tpartial_function<Expr, Guard, struct get_tpartial_function<Expr, Guard,
util::type_list<Args...>, util::void_type, 0> { util::type_list<Ts...>, util::void_type, 0> {
typedef typename util::get_callable_trait<Expr>::type ctrait; typedef typename util::get_callable_trait<Expr>::type ctrait;
typedef typename ctrait::arg_types arg_types; typedef typename ctrait::arg_types arg_types;
static_assert(util::tl_size<arg_types>::value <= sizeof...(Args), static_assert(util::tl_size<arg_types>::value <= sizeof...(Ts),
"Functor takes too much arguments"); "Functor takes too much arguments");
typedef typename get_tpartial_function< typedef typename get_tpartial_function<
Expr, Expr,
Guard, Guard,
// fill arg_types of Expr from left with const Args& // fill arg_types of Expr from left with const Ts&
typename util::tl_zip< typename util::tl_zip<
typename util::tl_pad_left< typename util::tl_pad_left<
typename ctrait::arg_types, typename ctrait::arg_types,
sizeof...(Args) sizeof...(Ts)
>::type, >::type,
util::type_list<const Args&...>, util::type_list<const Ts&...>,
util::left_or_right util::left_or_right
>::type, >::type,
typename ctrait::result_type, typename ctrait::result_type,
......
...@@ -44,16 +44,16 @@ inline auto apply_args(F& f, Tuple& tup, util::int_list<Is...>) ...@@ -44,16 +44,16 @@ inline auto apply_args(F& f, Tuple& tup, util::int_list<Is...>)
return f(get_cv_aware<Is>(tup)...); return f(get_cv_aware<Is>(tup)...);
} }
template<typename F, class Tuple, long... Is, typename... Args> template<typename F, class Tuple, long... Is, typename... Ts>
inline auto apply_args_prefixed(F& f, Tuple& tup, util::int_list<Is...>, Args&&... args) inline auto apply_args_prefixed(F& f, Tuple& tup, util::int_list<Is...>, Ts&&... args)
-> decltype(f(std::forward<Args>(args)..., get_cv_aware<Is>(tup)...)) { -> decltype(f(std::forward<Ts>(args)..., get_cv_aware<Is>(tup)...)) {
return f(std::forward<Args>(args)..., get_cv_aware<Is>(tup)...); return f(std::forward<Ts>(args)..., get_cv_aware<Is>(tup)...);
} }
template<typename F, class Tuple, long... Is, typename... Args> template<typename F, class Tuple, long... Is, typename... Ts>
inline auto apply_args_suffxied(F& f, Tuple& tup, util::int_list<Is...>, Args&&... args) inline auto apply_args_suffxied(F& f, Tuple& tup, util::int_list<Is...>, Ts&&... args)
-> decltype(f(get_cv_aware<Is>(tup)..., std::forward<Args>(args)...)) { -> decltype(f(get_cv_aware<Is>(tup)..., std::forward<Ts>(args)...)) {
return f(get_cv_aware<Is>(tup)..., std::forward<Args>(args)...); return f(get_cv_aware<Is>(tup)..., std::forward<Ts>(args)...);
} }
} } // namespace cppa::util } } // namespace cppa::util
......
...@@ -45,7 +45,7 @@ enum buffer_write_policy { ...@@ -45,7 +45,7 @@ enum buffer_write_policy {
}; };
/** /**
* * @brief
*/ */
class buffer { class buffer {
......
...@@ -36,60 +36,63 @@ ...@@ -36,60 +36,63 @@
#include "cppa/util/rm_ref.hpp" #include "cppa/util/rm_ref.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/conjunction.hpp"
namespace cppa { namespace util { namespace cppa { namespace util {
template<typename Signature> template<typename Signature>
struct callable_trait; struct callable_trait;
// member function pointer (const) // member const function pointer
template<class C, typename ResultType, typename... Args> template<class C, typename Result, typename... Ts>
struct callable_trait<ResultType (C::*)(Args...) const> { struct callable_trait<Result (C::*)(Ts...) const> {
typedef ResultType result_type; typedef Result result_type;
typedef type_list<Args...> arg_types; typedef type_list<Ts...> arg_types;
}; };
// member function pointer // member function pointer
template<class C, typename ResultType, typename... Args> template<class C, typename Result, typename... Ts>
struct callable_trait<ResultType (C::*)(Args...)> { struct callable_trait<Result (C::*)(Ts...)> {
typedef ResultType result_type; typedef Result result_type;
typedef type_list<Args...> arg_types; typedef type_list<Ts...> arg_types;
}; };
// good ol' function // good ol' function
template<typename ResultType, typename... Args> template<typename Result, typename... Ts>
struct callable_trait<ResultType (Args...)> { struct callable_trait<Result (Ts...)> {
typedef ResultType result_type; typedef Result result_type;
typedef type_list<Args...> arg_types; typedef type_list<Ts...> arg_types;
}; };
// good ol' function pointer // good ol' function pointer
template<typename ResultType, typename... Args> template<typename Result, typename... Ts>
struct callable_trait<ResultType (*)(Args...)> { struct callable_trait<Result (*)(Ts...)> {
typedef ResultType result_type; typedef Result result_type;
typedef type_list<Args...> arg_types; typedef type_list<Ts...> arg_types;
}; };
template<bool IsFun, bool IsMemberFun, typename C> // matches (IsFun || IsMemberFun)
template<bool IsFun, bool IsMemberFun, typename T>
struct get_callable_trait_helper { struct get_callable_trait_helper {
typedef callable_trait<C> type; typedef callable_trait<T> type;
}; };
// assume functor providing operator()
template<typename C> template<typename C>
struct get_callable_trait_helper<false, false, C> { struct get_callable_trait_helper<false, false, C> {
// assuming functor
typedef callable_trait<decltype(&C::operator())> type; typedef callable_trait<decltype(&C::operator())> type;
}; };
template<typename C> template<typename T>
struct get_callable_trait { struct get_callable_trait {
typedef typename rm_ref<C>::type fun_type; // type without cv qualifiers
typedef typename typedef typename rm_ref<T>::type bare_type;
get_callable_trait_helper< ( std::is_function<fun_type>::value // if type is a function pointer, this typedef identifies the function
|| std::is_function<typename std::remove_pointer<fun_type>::type>::value), typedef typename std::remove_pointer<bare_type>::type fun_type;
std::is_member_function_pointer<fun_type>::value, typedef typename get_callable_trait_helper<
fun_type>::type std::is_function<bare_type>::value
|| std::is_function<fun_type>::value,
std::is_member_function_pointer<bare_type>::value,
bare_type
>::type
type; type;
typedef typename type::result_type result_type; typedef typename type::result_type result_type;
typedef typename type::arg_types arg_types; typedef typename type::arg_types arg_types;
...@@ -101,51 +104,6 @@ struct get_arg_types { ...@@ -101,51 +104,6 @@ struct get_arg_types {
typedef typename trait_type::arg_types types; typedef typename trait_type::arg_types types;
}; };
template<typename T>
struct is_callable {
template<typename C>
static bool _fun(C*, typename callable_trait<C>::result_type* = nullptr) {
return true;
}
template<typename C>
static bool _fun(C*, typename callable_trait<decltype(&C::operator())>::result_type* = nullptr) {
return true;
}
static void _fun(void*) { }
typedef decltype(_fun(static_cast<typename rm_ref<T>::type*>(nullptr)))
result_type;
public:
static constexpr bool value = std::is_same<bool, result_type>::value;
};
template<typename... Ts>
struct all_callable {
static constexpr bool value = conjunction<is_callable<Ts>...>::value;
};
template<bool IsCallable, typename C>
struct get_result_type_impl {
typedef typename get_callable_trait<C>::type trait_type;
typedef typename trait_type::result_type type;
};
template<typename C>
struct get_result_type_impl<false, C> {
typedef void_type type;
};
template<typename C>
struct get_result_type {
typedef typename get_result_type_impl<is_callable<C>::value, C>::type type;
};
} } // namespace cppa::util } } // namespace cppa::util
#endif // CPPA_UTIL_CALLABLE_TRAIT #endif // CPPA_UTIL_CALLABLE_TRAIT
...@@ -28,34 +28,33 @@ ...@@ -28,34 +28,33 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_IF_ELSE_HPP #ifndef CPPA_DTHIS_HPP
#define CPPA_IF_ELSE_HPP #define CPPA_DTHIS_HPP
#include "cppa/util/wrapped.hpp" #include <type_traits>
namespace cppa { namespace util { namespace cppa { namespace util {
// if (IfStmt == true) type = T; else type = Else::type;
template<bool IfStmt, typename T, class Else>
struct if_else_c {
typedef T type;
};
template<typename T, class Else>
struct if_else_c<false, T, Else> {
typedef typename Else::type type;
};
/** /**
* @brief A conditinal expression for types that allows * @brief Returns <tt>static_cast<Subtype*>(ptr)</tt> if @p Subtype is a
* nested statements (unlike std::conditional). * derived type of @p MixinType, returns @p ptr without cast otherwise.
*
* @c type is defined as @p T if <tt>IfStmt == true</tt>;
* otherwise @c type is defined as @p Else::type.
*/ */
template<class Stmt, typename T, class Else> template<class Subtype, class MixinType>
struct if_else : if_else_c<Stmt::value, T, Else> { }; typename std::conditional<
std::is_base_of<MixinType,Subtype>::value,
Subtype,
MixinType
>::type*
dptr(MixinType* ptr) {
typedef typename std::conditional<
std::is_base_of<MixinType,Subtype>::value,
Subtype,
MixinType
>::type
result_type;
return static_cast<result_type*>(ptr);
}
} } // namespace cppa::util } } // namespace cppa::util
#endif // CPPA_IF_ELSE_HPP #endif // CPPA_DTHIS_HPP
...@@ -28,20 +28,30 @@ ...@@ -28,20 +28,30 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_CHANNEL_HPP #ifndef CPPA_GET_RESULT_TYPE_HPP
#define CPPA_CHANNEL_HPP #define CPPA_GET_RESULT_TYPE_HPP
#include "cppa/ref_counted.hpp" #include "cppa/util/is_callable.hpp"
#include "cppa/util/callable_trait.hpp"
namespace cppa { class message; } namespace cppa { namespace util {
namespace cppa { namespace detail { template<bool IsCallable, typename C>
struct get_result_type_impl {
typedef typename get_callable_trait<C>::type trait_type;
typedef typename trait_type::result_type type;
};
template<typename C>
struct get_result_type_impl<false, C> {
typedef void_type type;
};
// public part of the actor interface template<typename C>
struct channel : ref_counted { struct get_result_type {
virtual void enqueue_msg(const message& msg) = 0; typedef typename get_result_type_impl<is_callable<C>::value, C>::type type;
}; };
} } // namespace cppa::detail } } // namespace cppa::util
#endif // CPPA_CHANNEL_HPP #endif // CPPA_GET_RESULT_TYPE_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 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_IS_CALLABLE_HPP
#define CPPA_IS_CALLABLE_HPP
#include "cppa/util/conjunction.hpp"
#include "cppa/util/callable_trait.hpp"
namespace cppa { namespace util {
template<typename T>
struct is_callable {
template<typename C>
static bool _fun(C*, typename callable_trait<C>::result_type* = nullptr) {
return true;
}
template<typename C>
static bool _fun(C*, typename callable_trait<decltype(&C::operator())>::result_type* = nullptr) {
return true;
}
static void _fun(void*) { }
typedef decltype(_fun(static_cast<typename rm_ref<T>::type*>(nullptr)))
result_type;
public:
static constexpr bool value = std::is_same<bool, result_type>::value;
};
template<typename... Ts>
struct all_callable {
static constexpr bool value = conjunction<is_callable<Ts>...>::value;
};
} } // namespace cppa::util
#endif // CPPA_IS_CALLABLE_HPP
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "cppa/guard_expr.hpp" #include "cppa/guard_expr.hpp"
#include "cppa/util/rm_ref.hpp" #include "cppa/util/rm_ref.hpp"
#include "cppa/util/rebindable_reference.hpp"
namespace cppa { namespace util { namespace cppa { namespace util {
...@@ -44,12 +45,12 @@ struct purge_refs_impl { ...@@ -44,12 +45,12 @@ struct purge_refs_impl {
}; };
template<typename T> template<typename T>
struct purge_refs_impl<ge_reference_wrapper<T> > { struct purge_refs_impl<util::rebindable_reference<T> > {
typedef T type; typedef T type;
}; };
template<typename T> template<typename T>
struct purge_refs_impl<ge_mutable_reference_wrapper<T> > { struct purge_refs_impl<util::rebindable_reference<const T> > {
typedef T type; typedef T type;
}; };
...@@ -58,6 +59,11 @@ struct purge_refs_impl<std::reference_wrapper<T> > { ...@@ -58,6 +59,11 @@ struct purge_refs_impl<std::reference_wrapper<T> > {
typedef T type; typedef T type;
}; };
template<typename T>
struct purge_refs_impl<std::reference_wrapper<const T> > {
typedef T type;
};
/** /**
* @brief Removes references and reference wrappers. * @brief Removes references and reference wrappers.
*/ */
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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 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_REBINDABLE_REFERENCE_HPP
#define CPPA_REBINDABLE_REFERENCE_HPP
#include "cppa/config.hpp"
#include "cppa/util/get_result_type.hpp"
namespace cppa { namespace util {
template<typename T>
struct call_helper {
typedef typename get_result_type<T>::type result_type;
template<typename... Ts>
result_type operator()(T& f, const Ts&... args) const {
return f(std::forward<Ts>(args)...);
}
};
template<>
struct call_helper<bool> {
typedef bool result_type;
bool operator()(const bool& value) const {
return value;
}
};
template<>
struct call_helper<const bool> : call_helper<bool> { };
/**
* @brief A reference wrapper similar to std::reference_wrapper, but
* allows rebinding the reference. Note that this wrapper can
* be 'dangling', because it provides a default constructor.
*/
template<typename T>
class rebindable_reference {
public:
rebindable_reference() : m_ptr(nullptr) { }
rebindable_reference(T& value) : m_ptr(&value) { }
template<typename U>
rebindable_reference(const rebindable_reference<U>& other) : m_ptr(other.ptr()) { }
inline bool bound() const {
return m_ptr != nullptr;
}
inline void rebind(T& value) {
m_ptr = &value;
}
template<typename U>
inline void rebind(const rebindable_reference<U>& other) {
m_ptr = other.ptr();
}
inline T* ptr() const {
CPPA_REQUIRE(bound());
return m_ptr;
}
inline T& get() const {
CPPA_REQUIRE(bound());
return *m_ptr;
}
inline operator T&() const {
CPPA_REQUIRE(bound());
return *m_ptr;
}
template<typename... Ts>
typename call_helper<T>::result_type operator()(Ts&&... args) {
call_helper<T> f;
return f(get(), std::forward<Ts>(args)...);
}
private:
T* m_ptr;
};
} } // namespace cppa::util
#endif // CPPA_REBINDABLE_REFERENCE_HPP
...@@ -54,8 +54,7 @@ namespace cppa { namespace util { ...@@ -54,8 +54,7 @@ namespace cppa { namespace util {
template<typename What, typename With, typename... IfStmt> template<typename What, typename With, typename... IfStmt>
struct replace_type { struct replace_type {
static constexpr bool do_replace = disjunction<IfStmt::value...>::value; static constexpr bool do_replace = disjunction<IfStmt::value...>::value;
typedef typename detail::replace_type<do_replace, What, With>::type typedef typename detail::replace_type<do_replace, What, With>::type type;
type;
}; };
} } // namespace cppa::util } } // namespace cppa::util
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include "cppa/util/at.hpp" #include "cppa/util/at.hpp"
#include "cppa/util/tbind.hpp" #include "cppa/util/tbind.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/type_pair.hpp" #include "cppa/util/type_pair.hpp"
#include "cppa/util/void_type.hpp" #include "cppa/util/void_type.hpp"
...@@ -911,10 +910,10 @@ struct tl_is_zipped { ...@@ -911,10 +910,10 @@ struct tl_is_zipped {
*/ */
template<class List, typename What = void_type> template<class List, typename What = void_type>
struct tl_trim { struct tl_trim {
typedef typename util::if_else< typedef typename std::conditional<
std::is_same<typename tl_back<List>::type, What>, std::is_same<typename tl_back<List>::type,What>::value,
typename tl_trim<typename tl_pop_back<List>::type, What>::type, typename tl_trim<typename tl_pop_back<List>::type, What>::type,
util::wrapped<List> List
>::type >::type
type; type;
}; };
......
...@@ -35,7 +35,7 @@ namespace cppa { namespace util { ...@@ -35,7 +35,7 @@ namespace cppa { namespace util {
/** /**
* @ingroup MetaProgramming * @ingroup MetaProgramming
* @brief A type wrapper as used in {@link cppa::util::if_else if_else}. * @brief A simple type wrapper.
*/ */
template<typename T> template<typename T>
struct wrapped { struct wrapped {
......
...@@ -48,12 +48,12 @@ auto context_switching_actor::init_timeout(const util::duration& tout) -> timeou ...@@ -48,12 +48,12 @@ auto context_switching_actor::init_timeout(const util::duration& tout) -> timeou
return {}; return {};
} }
detail::recursive_queue_node* context_switching_actor::await_message(const timeout_type&) { mailbox_element* context_switching_actor::await_message(const timeout_type&) {
// receives requested timeout message if timeout occured // receives requested timeout message if timeout occured
return await_message(); return await_message();
} }
detail::recursive_queue_node* context_switching_actor::await_message() { mailbox_element* context_switching_actor::await_message() {
auto e = m_mailbox.try_pop(); auto e = m_mailbox.try_pop();
while (e == nullptr) { while (e == nullptr) {
if (m_mailbox.can_fetch_more() == false) { if (m_mailbox.can_fetch_more() == false) {
......
...@@ -138,7 +138,7 @@ resume_result event_based_actor::resume(util::fiber*, actor_ptr& next_job) { ...@@ -138,7 +138,7 @@ resume_result event_based_actor::resume(util::fiber*, actor_ptr& next_job) {
} }
else { else {
CPPA_LOG_DEBUG("try to invoke message: " << to_string(e->msg)); CPPA_LOG_DEBUG("try to invoke message: " << to_string(e->msg));
if (m_bhvr_stack.invoke(m_policy, this, e)) { if (m_bhvr_stack.invoke(m_recv_policy, this, e)) {
CPPA_LOG_DEBUG_IF(m_chained_actor, CPPA_LOG_DEBUG_IF(m_chained_actor,
"set actor with ID " "set actor with ID "
<< m_chained_actor->id() << m_chained_actor->id()
......
...@@ -182,9 +182,9 @@ class local_group_proxy : public local_group { ...@@ -182,9 +182,9 @@ class local_group_proxy : public local_group {
public: public:
template<typename... Args> template<typename... Ts>
local_group_proxy(actor_ptr remote_broker, Args&&... args) local_group_proxy(actor_ptr remote_broker, Ts&&... args)
: super(false, forward<Args>(args)...) { : super(false, forward<Ts>(args)...) {
CPPA_REQUIRE(m_broker == nullptr); CPPA_REQUIRE(m_broker == nullptr);
CPPA_REQUIRE(remote_broker != nullptr); CPPA_REQUIRE(remote_broker != nullptr);
CPPA_REQUIRE(remote_broker->is_proxy()); CPPA_REQUIRE(remote_broker->is_proxy());
......
...@@ -33,8 +33,6 @@ ...@@ -33,8 +33,6 @@
#include <fstream> #include <fstream>
#include <algorithm> #include <algorithm>
#include <execinfo.h> //DEL_ME
#ifndef CPPA_WINDOWS #ifndef CPPA_WINDOWS
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
......
...@@ -28,13 +28,13 @@ ...@@ -28,13 +28,13 @@
\******************************************************************************/ \******************************************************************************/
#include "cppa/detail/recursive_queue_node.hpp" #include "cppa/mailbox_element.hpp"
namespace cppa { namespace detail { namespace cppa {
recursive_queue_node::recursive_queue_node(const actor_ptr& sptr, mailbox_element::mailbox_element(const actor_ptr& sptr,
any_tuple data, any_tuple data,
message_id id) message_id id)
: next(nullptr), marked(false), sender(sptr), msg(std::move(data)), mid(id) { } : next(nullptr), marked(false), sender(sptr), msg(std::move(data)), mid(id) { }
} } // namespace cppa::detail } // namespace cppa
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <typeinfo> #include <typeinfo>
#include "cppa/detail/memory.hpp" #include "cppa/detail/memory.hpp"
#include "cppa/detail/recursive_queue_node.hpp" #include "cppa/mailbox_element.hpp"
using namespace std; using namespace std;
...@@ -64,8 +64,8 @@ cache_map& get_cache_map() { ...@@ -64,8 +64,8 @@ cache_map& get_cache_map() {
cache = new cache_map; cache = new cache_map;
pthread_setspecific(s_key, cache); pthread_setspecific(s_key, cache);
// insert default types // insert default types
unique_ptr<memory_cache> tmp(new basic_memory_cache<recursive_queue_node>); unique_ptr<memory_cache> tmp(new basic_memory_cache<mailbox_element>);
cache->insert(make_pair(&typeid(recursive_queue_node), move(tmp))); cache->insert(make_pair(&typeid(mailbox_element), move(tmp)));
} }
return *cache; return *cache;
} }
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/match.hpp" #include "cppa/match.hpp"
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/either.hpp"
#include "cppa/logging.hpp" #include "cppa/logging.hpp"
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/actor_proxy.hpp" #include "cppa/actor_proxy.hpp"
......
...@@ -80,6 +80,10 @@ scheduled_actor::~scheduled_actor() { ...@@ -80,6 +80,10 @@ scheduled_actor::~scheduled_actor() {
} }
} }
void scheduled_actor::run_detached() {
throw std::logic_error("scheduled_actor::run_detached called");
}
void scheduled_actor::cleanup(std::uint32_t reason) { void scheduled_actor::cleanup(std::uint32_t reason) {
detail::sync_request_bouncer f{reason}; detail::sync_request_bouncer f{reason};
m_mailbox.close(f); m_mailbox.close(f);
......
...@@ -157,8 +157,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) { ...@@ -157,8 +157,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
// setup & local variables // setup & local variables
self.set(m_self.get()); self.set(m_self.get());
bool done = false; bool done = false;
auto& queue = m_self->m_mailbox; std::unique_ptr<mailbox_element,detail::disposer> msg_ptr;
std::unique_ptr<detail::recursive_queue_node,detail::disposer> msg_ptr;
auto tout = hrc::now(); auto tout = hrc::now();
std::multimap<decltype(tout),delayed_msg> messages; std::multimap<decltype(tout),delayed_msg> messages;
// message handling rules // message handling rules
...@@ -188,7 +187,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) { ...@@ -188,7 +187,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
// loop // loop
while (!done) { while (!done) {
while (!msg_ptr) { while (!msg_ptr) {
if (messages.empty()) msg_ptr.reset(queue.pop()); if (messages.empty()) msg_ptr.reset(m_self->pop());
else { else {
tout = hrc::now(); tout = hrc::now();
// handle timeouts (send messages) // handle timeouts (send messages)
...@@ -200,7 +199,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) { ...@@ -200,7 +199,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
} }
// wait for next message or next timeout // wait for next message or next timeout
if (it != messages.end()) { if (it != messages.end()) {
msg_ptr.reset(queue.try_pop(it->first)); msg_ptr.reset(m_self->try_pop(it->first));
} }
} }
} }
......
...@@ -48,6 +48,7 @@ thread_mapped_actor::thread_mapped_actor() : super(std::function<void()>{}), m_i ...@@ -48,6 +48,7 @@ thread_mapped_actor::thread_mapped_actor() : super(std::function<void()>{}), m_i
thread_mapped_actor::thread_mapped_actor(std::function<void()> fun) thread_mapped_actor::thread_mapped_actor(std::function<void()> fun)
: super(std::move(fun)), m_initialized(false) { } : super(std::move(fun)), m_initialized(false) { }
/*
auto thread_mapped_actor::init_timeout(const util::duration& rel_time) -> timeout_type { auto thread_mapped_actor::init_timeout(const util::duration& rel_time) -> timeout_type {
auto result = std::chrono::high_resolution_clock::now(); auto result = std::chrono::high_resolution_clock::now();
result += rel_time; result += rel_time;
...@@ -68,14 +69,7 @@ void thread_mapped_actor::sync_enqueue(const actor_ptr& sender, ...@@ -68,14 +69,7 @@ void thread_mapped_actor::sync_enqueue(const actor_ptr& sender,
f(sender, id); f(sender, id);
} }
} }
*/
detail::recursive_queue_node* thread_mapped_actor::await_message() {
return m_mailbox.pop();
}
detail::recursive_queue_node* thread_mapped_actor::await_message(const timeout_type& abs_time) {
return m_mailbox.try_pop(abs_time);
}
bool thread_mapped_actor::initialized() const { bool thread_mapped_actor::initialized() const {
return m_initialized; return m_initialized;
......
...@@ -204,8 +204,7 @@ actor_ptr thread_pool_scheduler::exec(spawn_options os, scheduled_actor_ptr p) { ...@@ -204,8 +204,7 @@ actor_ptr thread_pool_scheduler::exec(spawn_options os, scheduled_actor_ptr p) {
bool is_hidden = has_hide_flag(os); bool is_hidden = has_hide_flag(os);
if (has_detach_flag(os)) { if (has_detach_flag(os)) {
exec_as_thread(is_hidden, p, [p] { exec_as_thread(is_hidden, p, [p] {
p->exec_behavior_stack(); p->run_detached();
p->on_exit();
}); });
return std::move(p); return std::move(p);
} }
......
...@@ -302,9 +302,24 @@ int main() { ...@@ -302,9 +302,24 @@ int main() {
); );
CPPA_CHECKPOINT(); CPPA_CHECKPOINT();
CPPA_PRINT("test mirror"); {
auto mirror = spawn<simple_mirror,monitored>(); auto mirror = spawn<simple_mirror,monitored>();
send(mirror, "hello mirror");
receive (
on("hello mirror") >> CPPA_CHECKPOINT_CB(),
others() >> CPPA_UNEXPECTED_MSG_CB()
);
quit_actor(mirror, exit_reason::user_defined);
receive (
on(atom("DOWN"), exit_reason::user_defined) >> CPPA_CHECKPOINT_CB(),
others() >> CPPA_UNEXPECTED_MSG_CB()
);
await_all_others_done();
CPPA_CHECKPOINT();
}
CPPA_PRINT("test mirror"); CPPA_PRINT("test detached mirror"); {
auto mirror = spawn<simple_mirror,monitored+detached>();
send(mirror, "hello mirror"); send(mirror, "hello mirror");
receive ( receive (
on("hello mirror") >> CPPA_CHECKPOINT_CB(), on("hello mirror") >> CPPA_CHECKPOINT_CB(),
...@@ -317,6 +332,7 @@ int main() { ...@@ -317,6 +332,7 @@ int main() {
); );
await_all_others_done(); await_all_others_done();
CPPA_CHECKPOINT(); CPPA_CHECKPOINT();
}
CPPA_PRINT("test echo actor"); CPPA_PRINT("test echo actor");
auto mecho = spawn(echo_actor); auto mecho = spawn(echo_actor);
......
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