Commit 04fc1827 authored by Joseph Noir's avatar Joseph Noir

Merge branch 'unstable' into topic/opencl

parents 16cb9399 05d61a8d
...@@ -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,8 +138,6 @@ set(LIBCPPA_SRC ...@@ -137,8 +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/receive.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
...@@ -80,7 +79,6 @@ cppa/group.hpp ...@@ -80,7 +79,6 @@ cppa/group.hpp
cppa/guard_expr.hpp cppa/guard_expr.hpp
cppa/intrusive/blocking_single_reader_queue.hpp cppa/intrusive/blocking_single_reader_queue.hpp
cppa/intrusive/single_reader_queue.hpp cppa/intrusive/single_reader_queue.hpp
cppa/intrusive_fwd_ptr.hpp
cppa/intrusive_ptr.hpp cppa/intrusive_ptr.hpp
cppa/local_actor.hpp cppa/local_actor.hpp
cppa/logging.hpp cppa/logging.hpp
...@@ -145,7 +143,6 @@ cppa/util/duration.hpp ...@@ -145,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
...@@ -168,7 +165,6 @@ cppa/util/rm_ref.hpp ...@@ -168,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
...@@ -244,8 +240,7 @@ src/partial_function.cpp ...@@ -244,8 +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/receive.cpp src/mailbox_element.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
...@@ -302,3 +297,8 @@ cppa/extend.hpp ...@@ -302,3 +297,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
...@@ -86,7 +86,7 @@ class actor : public channel { ...@@ -86,7 +86,7 @@ class actor : public channel {
* @pre <tt>id.valid()</tt> * @pre <tt>id.valid()</tt>
*/ */
virtual void sync_enqueue(const actor_ptr& sender, virtual void sync_enqueue(const actor_ptr& sender,
message_id_t id, message_id id,
any_tuple msg) = 0; any_tuple msg) = 0;
/** /**
...@@ -96,7 +96,7 @@ class actor : public channel { ...@@ -96,7 +96,7 @@ class actor : public channel {
* its state to @p pending in response to the enqueue operation. * its state to @p pending in response to the enqueue operation.
*/ */
virtual bool chained_sync_enqueue(const actor_ptr& sender, virtual bool chained_sync_enqueue(const actor_ptr& sender,
message_id_t id, message_id id,
any_tuple msg); any_tuple msg);
/** /**
...@@ -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,37 +129,33 @@ class actor_companion_mixin : public Base { ...@@ -129,37 +129,33 @@ 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_t 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&) { throw_no_recv(); } void dequeue(behavior&) {
throw_no_recv();
void dequeue(partial_function&) { throw_no_recv(); } }
void dequeue_response(behavior&, message_id_t) { void dequeue_response(behavior&, message_id) {
throw_no_recv(); throw_no_recv();
} }
void become_waiting_for(behavior&&, message_id_t) { void become_waiting_for(behavior, message_id) {
throw_no_become(); throw_no_become();
} }
...@@ -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"
...@@ -56,10 +55,18 @@ class behavior { ...@@ -56,10 +55,18 @@ class behavior {
public: public:
/** @cond PRIVATE */
typedef intrusive_ptr<detail::behavior_impl> impl_ptr; typedef intrusive_ptr<detail::behavior_impl> impl_ptr;
inline auto as_behavior_impl() const -> const impl_ptr&;
inline behavior(impl_ptr ptr);
static constexpr bool may_have_timeout = true; static constexpr bool may_have_timeout = true;
/** @endcond */
behavior() = default; behavior() = default;
behavior(behavior&&) = default; behavior(behavior&&) = default;
behavior(const behavior&) = default; behavior(const behavior&) = default;
...@@ -68,49 +75,39 @@ class behavior { ...@@ -68,49 +75,39 @@ class behavior {
behavior(const partial_function& fun); behavior(const partial_function& fun);
inline behavior(impl_ptr ptr) : m_impl(std::move(ptr)) { }
template<typename F> template<typename F>
behavior(const timeout_definition<F>& arg) behavior(const timeout_definition<F>& arg);
: m_impl(detail::new_default_behavior_impl(detail::dummy_match_expr{},
arg.timeout,
arg.handler) ) { }
template<typename F> template<typename F>
behavior(util::duration d, F f) behavior(util::duration d, F f);
: m_impl(detail::new_default_behavior_impl(detail::dummy_match_expr{}, d, f)) { }
template<typename... Cases>
behavior(const match_expr<Cases...>& arg0)
: m_impl(detail::new_default_behavior_impl(arg0, util::duration(), []() { })) { }
template<typename... Cases, typename Arg1, typename... Args> template<typename... Cases, typename... Ts>
behavior(const match_expr<Cases...>& arg0, const Arg1& arg1, const Args&... args) behavior(const match_expr<Cases...>& arg, const Ts&... args);
: m_impl(detail::match_expr_concat(arg0, arg1, args...)) { }
inline void handle_timeout() { /**
m_impl->handle_timeout(); * @brief Invokes the timeout callback.
} */
inline void handle_timeout();
inline const util::duration& timeout() const {
return m_impl->timeout();
}
inline bool undefined() const { /**
return m_impl == nullptr || m_impl->timeout().valid() == false; * @brief Returns the duration after which receives using
} * this behavior should time out.
*/
inline const util::duration& timeout() const;
/**
* @copydoc partial_function::operator()()
*/
template<typename T> template<typename T>
inline bool operator()(T&& arg) { inline bool operator()(T&& arg);
return (m_impl) && m_impl->invoke(std::forward<T>(arg));
}
/**
* @brief Adds a continuation to this behavior that is executed
* whenever this behavior was successfully applied to
* a message.
*/
template<typename F> template<typename F>
inline behavior add_continuation(F fun) { inline behavior add_continuation(F fun);
return {new detail::continuation_decorator<F>(std::move(fun), m_impl)};
}
const impl_ptr& as_behavior_impl() const { return m_impl; }
private: private:
...@@ -118,12 +115,60 @@ class behavior { ...@@ -118,12 +115,60 @@ class behavior {
}; };
template<typename... Lhs, typename F> /**
inline behavior operator,(const match_expr<Lhs...>& lhs, * @brief Creates a behavior from a match expression and a timeout definition.
* @relates behavior
*/
template<typename... Cases, typename F>
inline behavior operator,(const match_expr<Cases...>& lhs,
const timeout_definition<F>& rhs) { const timeout_definition<F>& rhs) {
return match_expr_convert(lhs, rhs); return match_expr_convert(lhs, rhs);
} }
/******************************************************************************
* inline and template member function implementations *
******************************************************************************/
template<typename F>
behavior::behavior(const timeout_definition<F>& arg)
: m_impl(detail::new_default_behavior_impl(detail::dummy_match_expr{},
arg.timeout,
arg.handler) ) { }
template<typename F>
behavior::behavior(util::duration d, F f)
: m_impl(detail::new_default_behavior_impl(detail::dummy_match_expr{}, d, f)) { }
template<typename... Cases, typename... Ts>
behavior::behavior(const match_expr<Cases...>& arg, const Ts&... args)
: m_impl(detail::match_expr_concat(arg, args...)) { }
inline behavior::behavior(impl_ptr ptr) : m_impl(std::move(ptr)) { }
inline void behavior::handle_timeout() {
m_impl->handle_timeout();
}
inline const util::duration& behavior::timeout() const {
return m_impl->timeout();
}
template<typename T>
inline bool behavior::operator()(T&& arg) {
return (m_impl) && m_impl->invoke(std::forward<T>(arg));
}
inline auto behavior::as_behavior_impl() const -> const impl_ptr& {
return m_impl;
}
template<typename F>
inline behavior behavior::add_continuation(F fun) {
return {new detail::continuation_decorator<F>(std::move(fun), m_impl)};
}
} // namespace cppa } // namespace cppa
#endif // CPPA_BEHAVIOR_HPP #endif // CPPA_BEHAVIOR_HPP
...@@ -67,12 +67,6 @@ class channel : public ref_counted { ...@@ -67,12 +67,6 @@ class channel : public ref_counted {
virtual ~channel(); virtual ~channel();
private:
// channel is a sealed class and the only
// allowed subclasses are actor and group.
channel() = default;
}; };
/** /**
...@@ -84,8 +78,8 @@ typedef intrusive_ptr<channel> channel_ptr; ...@@ -84,8 +78,8 @@ typedef intrusive_ptr<channel> channel_ptr;
/** /**
* @brief Convenience alias. * @brief Convenience alias.
*/ */
template<typename T> template<typename T, typename R = void>
using enable_if_channel = std::enable_if<std::is_base_of<channel,T>::value>; using enable_if_channel = std::enable_if<std::is_base_of<channel,T>::value,R>;
} // namespace cppa } // namespace cppa
......
...@@ -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"
...@@ -191,11 +192,20 @@ ...@@ -191,11 +192,20 @@
* *
* @defgroup MessageHandling Message handling. * @defgroup MessageHandling Message handling.
* *
* This is the beating heart of @p libcppa. Actor programming is all about * @brief This is the beating heart of @p libcppa. Actor programming is
* message handling. * all about message handling.
* *
* A message in @p libcppa is a n-tuple of values (with size >= 1). You can use * A message in @p libcppa is a n-tuple of values (with size >= 1). You can use
* almost every type in a messages. * almost every type in a messages - as long as it is announced, i.e., known
* by libcppa's type system.
*
* @defgroup BlockingAPI Blocking API.
*
* @brief Blocking functions to receive messages.
*
* The blocking API of libcppa is intended to be used for migrating
* previously threaded applications. When writing new code, you should use
* ibcppas nonblocking become/unbecome API.
* *
* @section Send Send messages * @section Send Send messages
* *
...@@ -414,15 +424,14 @@ namespace cppa { ...@@ -414,15 +424,14 @@ namespace cppa {
namespace detail { namespace detail {
template<typename T> template<typename T>
inline void send_impl(T* whom, any_tuple&& what) { inline void send_impl(T* ptr, any_tuple&& arg) {
if (whom) self->send_message(whom, std::move(what)); if (ptr) self->send_message(ptr, std::move(arg));
} }
template<typename T, typename... Ts> template<typename T, typename... Ts>
inline void send_tpl_impl(T* whom, Ts&&... what) { inline void send_tpl_impl(T* ptr, Ts&&... args) {
static_assert(sizeof...(Ts) > 0, "no message to send"); static_assert(sizeof...(Ts) > 0, "no message to send");
if (whom) self->send_message(whom, if (ptr) self->send_message(ptr, make_any_tuple(std::forward<Ts>(args)...));
make_any_tuple(std::forward<Ts>(what)...));
} }
} // namespace detail } // namespace detail
...@@ -438,7 +447,7 @@ inline void send_tpl_impl(T* whom, Ts&&... what) { ...@@ -438,7 +447,7 @@ inline void send_tpl_impl(T* whom, Ts&&... what) {
* @param what Message content as tuple. * @param what Message content as tuple.
*/ */
template<class C, typename... Ts> template<class C, typename... Ts>
inline typename std::enable_if<std::is_base_of<channel, C>::value>::type inline typename enable_if_channel<C>::type
send_tuple(const intrusive_ptr<C>& whom, any_tuple what) { send_tuple(const intrusive_ptr<C>& whom, any_tuple what) {
detail::send_impl(whom.get(), std::move(what)); detail::send_impl(whom.get(), std::move(what));
} }
...@@ -450,9 +459,9 @@ send_tuple(const intrusive_ptr<C>& whom, any_tuple what) { ...@@ -450,9 +459,9 @@ send_tuple(const intrusive_ptr<C>& whom, any_tuple what) {
* @pre <tt>sizeof...(Ts) > 0</tt> * @pre <tt>sizeof...(Ts) > 0</tt>
*/ */
template<class C, typename... Ts> template<class C, typename... Ts>
inline typename std::enable_if<std::is_base_of<channel, C>::value>::type inline typename enable_if_channel<C>::type
send(const intrusive_ptr<C>& whom, Ts&&... what) { send(const intrusive_ptr<C>& whom, Ts&&... args) {
detail::send_tpl_impl(whom.get(), std::forward<Ts>(what)...); detail::send_tpl_impl(whom.get(), std::forward<Ts>(args)...);
} }
/** /**
...@@ -464,7 +473,7 @@ send(const intrusive_ptr<C>& whom, Ts&&... what) { ...@@ -464,7 +473,7 @@ send(const intrusive_ptr<C>& whom, Ts&&... what) {
* @pre <tt>sizeof...(Ts) > 0</tt> * @pre <tt>sizeof...(Ts) > 0</tt>
*/ */
template<class C, typename... Ts> template<class C, typename... Ts>
inline typename std::enable_if<std::is_base_of<channel, C>::value>::type inline typename enable_if_channel<C>::type
send_tuple_as(const actor_ptr& from, const intrusive_ptr<C>& whom, any_tuple what) { send_tuple_as(const actor_ptr& from, const intrusive_ptr<C>& whom, any_tuple what) {
if (whom) whom->enqueue(from.get(), std::move(what)); if (whom) whom->enqueue(from.get(), std::move(what));
} }
...@@ -478,7 +487,7 @@ send_tuple_as(const actor_ptr& from, const intrusive_ptr<C>& whom, any_tuple wha ...@@ -478,7 +487,7 @@ send_tuple_as(const actor_ptr& from, const intrusive_ptr<C>& whom, any_tuple wha
* @pre <tt>sizeof...(Ts) > 0</tt> * @pre <tt>sizeof...(Ts) > 0</tt>
*/ */
template<class C, typename... Ts> template<class C, typename... Ts>
inline typename std::enable_if<std::is_base_of<channel, C>::value>::type inline typename enable_if_channel<C>::type
send_as(const actor_ptr& from, const intrusive_ptr<C>& whom, Ts&&... what) { send_as(const actor_ptr& from, const intrusive_ptr<C>& whom, Ts&&... what) {
send_tuple_as(from, whom, make_any_tuple(std::forward<Ts>(what)...)); send_tuple_as(from, whom, make_any_tuple(std::forward<Ts>(what)...));
} }
...@@ -495,8 +504,7 @@ send_as(const actor_ptr& from, const intrusive_ptr<C>& whom, Ts&&... what) { ...@@ -495,8 +504,7 @@ send_as(const actor_ptr& from, const intrusive_ptr<C>& whom, Ts&&... what) {
* @returns @p whom. * @returns @p whom.
*/ */
template<class C> template<class C>
inline typename std::enable_if<std::is_base_of<channel, C>::value, inline typename enable_if_channel<C,const intrusive_ptr<C>&>::type
const intrusive_ptr<C>& >::type
operator<<(const intrusive_ptr<C>& whom, any_tuple what) { operator<<(const intrusive_ptr<C>& whom, any_tuple what) {
send_tuple(whom, std::move(what)); send_tuple(whom, std::move(what));
return whom; return whom;
...@@ -683,18 +691,20 @@ inline void delayed_reply(const std::chrono::duration<Rep, Period>& rtime, ...@@ -683,18 +691,20 @@ inline void delayed_reply(const std::chrono::duration<Rep, Period>& rtime,
delayed_reply_tuple(rtime, make_any_tuple(std::forward<Ts>(what)...)); delayed_reply_tuple(rtime, make_any_tuple(std::forward<Ts>(what)...));
} }
/** @} */ /**
* @}
*/
// matches "send(this, ...)" and "send(self, ...)" // matches "send(this, ...)" and "send(self, ...)"
inline void send_tuple(local_actor* whom, any_tuple what) { inline void send_tuple(channel* whom, any_tuple what) {
detail::send_impl(whom, std::move(what)); detail::send_impl(whom, std::move(what));
} }
template<typename... Ts> template<typename... Ts>
inline void send(local_actor* whom, Ts&&... args) { inline void send(channel* whom, Ts&&... args) {
detail::send_tpl_impl(whom, std::forward<Ts>(args)...); detail::send_tpl_impl(whom, std::forward<Ts>(args)...);
} }
inline const self_type& operator<<(const self_type& s, any_tuple what) { inline const self_type& operator<<(const self_type& s, any_tuple what) {
detail::send_impl(s.get(), std::move(what)); detail::send_impl(static_cast<channel*>(s.get()), std::move(what));
return s; return s;
} }
inline actor_ptr eval_sopts(spawn_options opts, actor_ptr ptr) { inline actor_ptr eval_sopts(spawn_options opts, actor_ptr ptr) {
...@@ -732,7 +742,14 @@ actor_ptr spawn(Ts&&... args) { ...@@ -732,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));
} }
...@@ -844,15 +861,24 @@ void shutdown(); // note: implemented in singleton_manager.cpp ...@@ -844,15 +861,24 @@ void shutdown(); // note: implemented in singleton_manager.cpp
*/ */
inline void quit_actor(const actor_ptr& whom, std::uint32_t reason) { inline void quit_actor(const actor_ptr& whom, std::uint32_t reason) {
CPPA_REQUIRE(reason != exit_reason::normal); CPPA_REQUIRE(reason != exit_reason::normal);
send(whom, atom("EXIT"), reason); send(whom.get(), atom("EXIT"), reason);
} }
/**
* @brief Sets the actor's behavior and discards the previous behavior
* unless {@link keep_behavior} is given as first argument.
*/
template<typename... Ts> template<typename... Ts>
inline void become(Ts&&... args) { inline void become(Ts&&... args) {
self->become(std::forward<Ts>(args)...); self->become(std::forward<Ts>(args)...);
} }
inline void unbecome() { self->unbecome(); } /**
* @brief Returns to a previous behavior if available.
*/
inline void unbecome() {
self->unbecome();
}
struct actor_ostream { struct actor_ostream {
...@@ -883,9 +909,11 @@ inline const actor_ostream& operator<<(const actor_ostream& o, const any_tuple& ...@@ -883,9 +909,11 @@ inline const actor_ostream& operator<<(const actor_ostream& o, const any_tuple&
} }
template<typename T> template<typename T>
inline typename std::enable_if< !std::is_convertible<T,std::string>::value inline typename std::enable_if<
!std::is_convertible<T,std::string>::value
&& !std::is_convertible<T,any_tuple>::value, && !std::is_convertible<T,any_tuple>::value,
const actor_ostream&>::type const actor_ostream&
>::type
operator<<(const actor_ostream& o, T&& arg) { operator<<(const actor_ostream& o, T&& arg) {
return o.write(std::to_string(std::forward<T>(arg))); return o.write(std::to_string(std::forward<T>(arg)));
} }
......
...@@ -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 {
...@@ -54,14 +54,14 @@ class behavior_stack ...@@ -54,14 +54,14 @@ class behavior_stack
behavior_stack(const behavior_stack&) = delete; behavior_stack(const behavior_stack&) = delete;
behavior_stack& operator=(const behavior_stack&) = delete; behavior_stack& operator=(const behavior_stack&) = delete;
typedef std::pair<behavior,message_id_t> element_type; typedef std::pair<behavior,message_id> element_type;
public: public:
behavior_stack() = default; behavior_stack() = default;
// @pre expected_response.valid() // @pre expected_response.valid()
option<behavior&> sync_handler(message_id_t expected_response); option<behavior&> sync_handler(message_id expected_response);
// erases the last asynchronous message handler // erases the last asynchronous message handler
void pop_async_back(); void pop_async_back();
...@@ -69,7 +69,7 @@ class behavior_stack ...@@ -69,7 +69,7 @@ class behavior_stack
void clear(); void clear();
// erases the synchronous response handler associated with @p rid // erases the synchronous response handler associated with @p rid
void erase(message_id_t rid) { void erase(message_id rid) {
erase_if([=](const element_type& e) { return e.second == rid; }); erase_if([=](const element_type& e) { return e.second == rid; });
} }
...@@ -81,7 +81,7 @@ class behavior_stack ...@@ -81,7 +81,7 @@ class behavior_stack
} }
inline void push_back(behavior&& what, inline void push_back(behavior&& what,
message_id_t response_id = message_id_t::invalid) { message_id response_id = message_id::invalid) {
m_elements.emplace_back(std::move(what), response_id); m_elements.emplace_back(std::move(what), response_id);
} }
...@@ -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
......
...@@ -51,24 +51,15 @@ struct receive_while_helper { ...@@ -51,24 +51,15 @@ struct receive_while_helper {
template<typename S> template<typename S>
receive_while_helper(S&& stmt) : m_stmt(std::forward<S>(stmt)) { } receive_while_helper(S&& stmt) : m_stmt(std::forward<S>(stmt)) { }
void operator()(behavior& bhvr) { template<typename... Ts>
void operator()(Ts&&... args) {
static_assert(sizeof...(Ts) > 0,
"operator() requires at least one argument");
behavior tmp = match_expr_convert(std::forward<Ts>(args)...);
local_actor* sptr = self; local_actor* sptr = self;
while (m_stmt()) sptr->dequeue(bhvr); while (m_stmt()) sptr->dequeue(tmp);
} }
void operator()(partial_function& fun) {
local_actor* sptr = self;
while (m_stmt()) sptr->dequeue(fun);
}
template<typename Arg0, typename... Args>
void operator()(Arg0&& arg0, Args&&... args) {
auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...);
(*this)(tmp);
}
}; };
template<typename T> template<typename T>
...@@ -81,21 +72,11 @@ class receive_for_helper { ...@@ -81,21 +72,11 @@ class receive_for_helper {
receive_for_helper(T& first, const T& last) : begin(first), end(last) { } receive_for_helper(T& first, const T& last) : begin(first), end(last) { }
void operator()(behavior& bhvr) { template<typename... Ts>
void operator()(Ts&&... args) {
auto tmp = match_expr_convert(std::forward<Ts>(args)...);
local_actor* sptr = self; local_actor* sptr = self;
for ( ; begin != end; ++begin) sptr->dequeue(bhvr); for ( ; begin != end; ++begin) sptr->dequeue(tmp);
}
void operator()(partial_function& fun) {
local_actor* sptr = self;
for ( ; begin != end; ++begin) sptr->dequeue(fun);
}
template<typename Arg0, typename... Args>
void operator()(Arg0&& arg0, Args&&... args) {
auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...);
(*this)(tmp);
} }
}; };
...@@ -106,10 +87,7 @@ class do_receive_helper { ...@@ -106,10 +87,7 @@ class do_receive_helper {
public: public:
template<typename... Args> inline do_receive_helper(behavior&& bhvr) : m_bhvr(std::move(bhvr)) { }
do_receive_helper(Args&&... args)
: m_bhvr(match_expr_convert(std::forward<Args>(args)...)) {
}
do_receive_helper(do_receive_helper&&) = default; do_receive_helper(do_receive_helper&&) = default;
......
...@@ -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,
...@@ -76,7 +76,7 @@ class receive_policy { ...@@ -76,7 +76,7 @@ class receive_policy {
template<class Client, class Fun> template<class Client, class Fun>
bool invoke_from_cache(Client* client, bool invoke_from_cache(Client* client,
Fun& fun, Fun& fun,
message_id_t awaited_response = message_id_t()) { message_id awaited_response = message_id{}) {
std::integral_constant<receive_policy_flag,Client::receive_flag> policy; std::integral_constant<receive_policy_flag,Client::receive_flag> policy;
auto i = m_cache.begin(); auto i = m_cache.begin();
auto e = m_cache.end(); auto e = m_cache.end();
...@@ -108,7 +108,7 @@ class receive_policy { ...@@ -108,7 +108,7 @@ class receive_policy {
bool invoke(Client* client, bool invoke(Client* client,
pointer node_ptr, pointer node_ptr,
Fun& fun, Fun& fun,
message_id_t awaited_response = message_id_t()) { message_id awaited_response = message_id()) {
smart_pointer node(node_ptr); smart_pointer node(node_ptr);
std::integral_constant<receive_policy_flag,Client::receive_flag> policy; std::integral_constant<receive_policy_flag,Client::receive_flag> policy;
switch (this->handle_message(client, node.get(), fun, switch (this->handle_message(client, node.get(), fun,
...@@ -176,7 +176,7 @@ class receive_policy { ...@@ -176,7 +176,7 @@ class receive_policy {
} }
template<class Client> template<class Client>
void receive(Client* client, behavior& bhvr, message_id_t mid) { void receive(Client* client, behavior& bhvr, message_id mid) {
CPPA_REQUIRE(mid.is_response()); CPPA_REQUIRE(mid.is_response());
if (!invoke_from_cache(client, bhvr, mid)) { if (!invoke_from_cache(client, bhvr, mid)) {
if (bhvr.timeout().valid()) { if (bhvr.timeout().valid()) {
...@@ -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) {
...@@ -231,7 +236,7 @@ class receive_policy { ...@@ -231,7 +236,7 @@ class receive_policy {
template<class Client> template<class Client>
filter_result filter_msg(Client* client, pointer node) { filter_result filter_msg(Client* client, pointer node) {
const any_tuple& msg = node->msg; const any_tuple& msg = node->msg;
auto message_id = node->mid; auto mid = node->mid;
auto& arr = detail::static_types_array<atom_value,std::uint32_t>::arr; auto& arr = detail::static_types_array<atom_value,std::uint32_t>::arr;
if ( msg.size() == 2 if ( msg.size() == 2
&& msg.type_at(0) == arr[0] && msg.type_at(0) == arr[0]
...@@ -239,7 +244,7 @@ class receive_policy { ...@@ -239,7 +244,7 @@ class receive_policy {
auto v0 = msg.get_as<atom_value>(0); auto v0 = msg.get_as<atom_value>(0);
auto v1 = msg.get_as<std::uint32_t>(1); auto v1 = msg.get_as<std::uint32_t>(1);
if (v0 == atom("EXIT")) { if (v0 == atom("EXIT")) {
CPPA_REQUIRE(!message_id.valid()); CPPA_REQUIRE(!mid.valid());
if (client->m_trap_exit == false) { if (client->m_trap_exit == false) {
if (v1 != exit_reason::normal) { if (v1 != exit_reason::normal) {
client->quit(v1); client->quit(v1);
...@@ -249,7 +254,7 @@ class receive_policy { ...@@ -249,7 +254,7 @@ class receive_policy {
} }
} }
else if (v0 == atom("SYNC_TOUT")) { else if (v0 == atom("SYNC_TOUT")) {
CPPA_REQUIRE(!message_id.valid()); CPPA_REQUIRE(!mid.valid());
return client->waits_for_timeout(v1) ? timeout_message return client->waits_for_timeout(v1) ? timeout_message
: expired_timeout_message; : expired_timeout_message;
} }
...@@ -257,11 +262,11 @@ class receive_policy { ...@@ -257,11 +262,11 @@ class receive_policy {
else if ( msg.size() == 1 else if ( msg.size() == 1
&& msg.type_at(0) == arr[0] && msg.type_at(0) == arr[0]
&& msg.get_as<atom_value>(0) == atom("TIMEOUT") && msg.get_as<atom_value>(0) == atom("TIMEOUT")
&& message_id.is_response()) { && mid.is_response()) {
return timeout_response_message; return timeout_response_message;
} }
if (message_id.is_response()) { if (mid.is_response()) {
return (client->awaits(message_id)) ? sync_response return (client->awaits(mid)) ? sync_response
: expired_sync_response; : expired_sync_response;
} }
return ordinary_message; return ordinary_message;
...@@ -340,7 +345,7 @@ class receive_policy { ...@@ -340,7 +345,7 @@ class receive_policy {
handle_message_result handle_message(Client* client, handle_message_result handle_message(Client* client,
pointer node, pointer node,
Fun& fun, Fun& fun,
message_id_t awaited_response, message_id awaited_response,
Policy policy ) { Policy policy ) {
bool handle_sync_failure_on_mismatch = true; bool handle_sync_failure_on_mismatch = true;
if (hm_should_skip(node, policy)) { if (hm_should_skip(node, policy)) {
......
...@@ -38,14 +38,13 @@ namespace cppa { namespace detail { ...@@ -38,14 +38,13 @@ namespace cppa { namespace detail {
struct scheduled_actor_dummy : scheduled_actor { struct scheduled_actor_dummy : scheduled_actor {
scheduled_actor_dummy(); scheduled_actor_dummy();
void enqueue(const actor_ptr&, any_tuple); void enqueue(const actor_ptr&, any_tuple);
void sync_enqueue(const actor_ptr&, message_id_t, any_tuple); void sync_enqueue(const actor_ptr&, message_id, any_tuple);
resume_result resume(util::fiber*, actor_ptr&); resume_result resume(util::fiber*, actor_ptr&);
void quit(std::uint32_t); void quit(std::uint32_t);
void dequeue(behavior&); void dequeue(behavior&);
void dequeue(partial_function&); void dequeue_response(behavior&, message_id);
void dequeue_response(behavior&, message_id_t);
void do_become(behavior&&, bool); void do_become(behavior&&, bool);
void become_waiting_for(behavior&&, message_id_t); void become_waiting_for(behavior, message_id);
bool has_behavior(); bool has_behavior();
scheduled_actor_type impl_type(); scheduled_actor_type impl_type();
}; };
......
...@@ -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 {
...@@ -45,7 +45,7 @@ struct sync_request_bouncer { ...@@ -45,7 +45,7 @@ struct sync_request_bouncer {
std::uint32_t rsn; std::uint32_t rsn;
constexpr sync_request_bouncer(std::uint32_t r) constexpr sync_request_bouncer(std::uint32_t r)
: rsn(r == exit_reason::not_exited ? exit_reason::normal : r) { } : rsn(r == exit_reason::not_exited ? exit_reason::normal : r) { }
inline void operator()(const actor_ptr& sender, const message_id_t& mid) const { inline void operator()(const actor_ptr& sender, const message_id& mid) const {
CPPA_REQUIRE(rsn != exit_reason::not_exited); CPPA_REQUIRE(rsn != exit_reason::not_exited);
if (mid.is_request() && sender != nullptr) { if (mid.is_request() && sender != nullptr) {
actor_ptr nobody; actor_ptr nobody;
...@@ -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,19 +59,14 @@ class event_based_actor : public scheduled_actor { ...@@ -60,19 +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(partial_function&); //override void dequeue_response(behavior&, message_id);
/** resume_result resume(util::fiber*, actor_ptr&);
* @copydoc dequeue(behavior&)
*/
void dequeue_response(behavior&, message_id_t);
resume_result resume(util::fiber*, actor_ptr&); //override
/** /**
* @brief Initializes the actor. * @brief Initializes the actor.
...@@ -97,9 +91,10 @@ class event_based_actor : public scheduled_actor { ...@@ -97,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.");
} }
...@@ -107,30 +102,32 @@ class event_based_actor : public scheduled_actor { ...@@ -107,30 +102,32 @@ 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_t mf); void become_waiting_for(behavior bhvr, message_id mf);
detail::receive_policy m_recv_policy;
private: private:
...@@ -154,8 +151,6 @@ class event_based_actor : public scheduled_actor { ...@@ -154,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 ...
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include <stdexcept> #include <stdexcept>
#include <type_traits> #include <type_traits>
#include "cppa/intrusive_fwd_ptr.hpp"
#include "cppa/util/comparable.hpp" #include "cppa/util/comparable.hpp"
namespace cppa { namespace cppa {
...@@ -73,12 +72,6 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >, ...@@ -73,12 +72,6 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >,
intrusive_ptr(const intrusive_ptr& other) { set_ptr(other.get()); } intrusive_ptr(const intrusive_ptr& other) { set_ptr(other.get()); }
template<typename Y, typename Ref, typename Deref>
intrusive_ptr(intrusive_fwd_ptr<Y,Ref,Deref> other) : m_ptr(other.release()) {
static_assert(std::is_convertible<Y*, T*>::value,
"Y* is not assignable to T*");
}
template<typename Y> template<typename Y>
intrusive_ptr(intrusive_ptr<Y> other) : m_ptr(other.release()) { intrusive_ptr(intrusive_ptr<Y> other) : m_ptr(other.release()) {
static_assert(std::is_convertible<Y*, T*>::value, static_assert(std::is_convertible<Y*, T*>::value,
...@@ -120,9 +113,9 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >, ...@@ -120,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) {
...@@ -214,9 +207,9 @@ inline bool operator!=(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs) ...@@ -214,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
......
...@@ -42,14 +42,14 @@ ...@@ -42,14 +42,14 @@
#include "cppa/message_id.hpp" #include "cppa/message_id.hpp"
#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/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/memory_cached.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,15 +85,10 @@ constexpr keep_behavior_t keep_behavior = keep_behavior_t{}; ...@@ -85,15 +85,10 @@ 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;
friend class scheduler;
friend class detail::memory;
friend class detail::receive_policy;
template<typename> friend class detail::basic_memory_cache;
public: public:
/** /**
...@@ -119,36 +114,11 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> { ...@@ -119,36 +114,11 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
* linked actors, sets its state to @c exited and finishes execution. * linked actors, sets its state to @c exited and finishes execution.
* @param reason Exit reason that will be send to * @param reason Exit reason that will be send to
* linked actors and monitors. * linked actors and monitors.
* @note Throws {@link actor_exited} to unwind the stack
* when called in context-switching or thread-based actors.
*/ */
virtual void quit(std::uint32_t reason = exit_reason::normal) = 0; virtual void quit(std::uint32_t reason = exit_reason::normal) = 0;
/**
* @brief Removes the first element from the mailbox @p pfun is defined
* for and invokes @p pfun with the removed element.
* Blocks until a matching message arrives if @p pfun is not
* defined for any message in the actor's mailbox.
* @param pfun A partial function denoting the actor's response to the
* next incoming message.
* @warning You should not call this member function by hand.
* Use the {@link cppa::receive receive} function or
* the @p become member function in case of event-based actors.
*/
virtual void dequeue(partial_function& pfun) = 0;
/**
* @brief Removes the first element from the mailbox @p bhvr is defined
* for and invokes @p bhvr with the removed element.
* Blocks until either a matching message arrives if @p bhvr is not
* defined for any message in the actor's mailbox or until a
* timeout occurs.
* @param bhvr A partial function with optional timeout denoting the
* actor's response to the next incoming message.
* @warning You should not call this member function by hand.
* Use the {@link cppa::receive receive} function or
* the @p become member function in case of event-based actors.
*/
virtual void dequeue(behavior& bhvr) = 0;
/** /**
* @brief Checks whether this actor traps exit messages. * @brief Checks whether this actor traps exit messages.
*/ */
...@@ -191,47 +161,13 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> { ...@@ -191,47 +161,13 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
* @param whom The actor that should be monitored by this actor. * @param whom The actor that should be monitored by this actor.
* @note Each call to @p monitor creates a new, independent monitor. * @note Each call to @p monitor creates a new, independent monitor.
*/ */
void monitor(actor_ptr whom); void monitor(const actor_ptr& whom);
/** /**
* @brief Removes a monitor from @p whom. * @brief Removes a monitor from @p whom.
* @param whom A monitored actor. * @param whom A monitored actor.
*/ */
void demonitor(actor_ptr whom); void demonitor(const actor_ptr& whom);
// become/unbecome API
/**
* @brief Sets the actor's behavior to @p bhvr and discards the
* previous behavior if the policy is {@link discard_behavior}.
*/
template<bool Discard>
inline void become(behavior_policy<Discard>, behavior bhvr);
/**
* @brief Sets the actor's behavior and discards the
* previous behavior if the policy is {@link discard_behavior}.
*/
template<bool Discard, typename T0, typename T1, typename... Ts>
inline void become(behavior_policy<Discard>, T0&& a0, T1&& a1, Ts&&... as);
/**
* @brief Sets the actor's behavior;
* equal to <tt>become(discard_old, bhvr</tt>.
*/
inline void become(behavior bhvr);
/**
* @brief Sets the actor's behavior;
* equal to <tt>become(discard_old, bhvr</tt>.
*/
template<typename... Cases, typename... Ts>
inline void become(match_expr<Cases...> a, Ts&&... as);
/**
* @brief Returns to a previous behavior if available.
*/
inline void unbecome();
/** /**
* @brief Can be overridden to initialize an actor before any * @brief Can be overridden to initialize an actor before any
...@@ -256,6 +192,7 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> { ...@@ -256,6 +192,7 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
std::vector<group_ptr> joined_groups(); std::vector<group_ptr> joined_groups();
/** /**
* @ingroup BlockingAPI
* @brief Executes an actor's behavior stack until it is empty. * @brief Executes an actor's behavior stack until it is empty.
* *
* This member function allows thread-based and context-switching actors * This member function allows thread-based and context-switching actors
...@@ -308,146 +245,108 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> { ...@@ -308,146 +245,108 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
else quit(exit_reason::unhandled_sync_failure); else quit(exit_reason::unhandled_sync_failure);
} }
// library-internal members and member functions that shall /** @cond PRIVATE */
// not appear in the documentation
virtual void dequeue(behavior& bhvr) = 0;
inline void dequeue(behavior&& bhvr);
virtual void dequeue_response(behavior&, message_id) = 0;
inline void dequeue_response(behavior&&, message_id);
# ifndef CPPA_DOCUMENTATION template<bool Discard, typename... Ts>
void become(behavior_policy<Discard>, Ts&&... args);
// backward compatiblity, handle_response was part of local_actor template<typename T, typename... Ts>
// until version 0.6 void become(T arg, Ts&&... args);
sync_handle_helper handle_response(const message_future& mf);
inline void unbecome();
local_actor(bool is_scheduled = false); local_actor(bool is_scheduled = false);
virtual bool initialized() const = 0; virtual bool initialized() const = 0;
inline bool chaining_enabled() { inline bool chaining_enabled();
return m_chaining && !m_chained_actor;
}
inline void send_message(channel* whom, any_tuple&& what) { inline void send_message(channel* whom, any_tuple&& what);
whom->enqueue(this, std::move(what));
}
inline void send_message(const actor_ptr& whom, any_tuple&& what) { inline void send_message(actor* whom, any_tuple&& what);
if (chaining_enabled()) {
if (whom->chained_enqueue(this, std::move(what))) {
m_chained_actor = whom;
}
}
else whom->enqueue(this, std::move(what));
}
inline message_id_t send_sync_message(const actor_ptr& whom, any_tuple&& what) { inline message_id send_sync_message(const actor_ptr& whom,
auto id = ++m_last_request_id; any_tuple&& what);
CPPA_REQUIRE(id.is_request());
if (chaining_enabled()) {
if (whom->chained_sync_enqueue(this, id, std::move(what))) {
m_chained_actor = whom;
}
}
else whom->sync_enqueue(this, id, std::move(what));
auto awaited_response = id.response_id();
m_pending_responses.push_back(awaited_response);
return awaited_response;
}
message_id_t send_timed_sync_message(const actor_ptr& whom, message_id send_timed_sync_message(const actor_ptr& whom,
const util::duration& rel_time, const util::duration& rel_time,
any_tuple&& what); any_tuple&& what);
// returns 0 if last_dequeued() is an asynchronous or sync request message, // returns 0 if last_dequeued() is an asynchronous or sync request message,
// a response id generated from the request id otherwise // a response id generated from the request id otherwise
inline message_id_t get_response_id() { inline message_id get_response_id();
auto id = m_current_node->mid;
return (id.is_request()) ? id.response_id() : message_id_t();
}
void reply_message(any_tuple&& what); void reply_message(any_tuple&& what);
void forward_message(const actor_ptr& new_receiver); void forward_message(const actor_ptr& new_receiver);
inline const actor_ptr& chained_actor() { inline const actor_ptr& chained_actor();
return m_chained_actor;
}
inline void chained_actor(const actor_ptr& value) { inline void chained_actor(const actor_ptr& value);
m_chained_actor = value;
}
inline bool awaits(message_id_t response_id) { inline bool awaits(message_id response_id);
CPPA_REQUIRE(response_id.is_response());
return std::any_of(m_pending_responses.begin(),
m_pending_responses.end(),
[=](message_id_t other) {
return response_id == other;
});
}
inline void mark_arrived(message_id_t response_id) { inline void mark_arrived(message_id response_id);
auto last = m_pending_responses.end();
auto i = std::find(m_pending_responses.begin(), last, response_id);
if (i != last) m_pending_responses.erase(i);
}
virtual void dequeue_response(behavior&, message_id_t) = 0; virtual void become_waiting_for(behavior, message_id) = 0;
inline void dequeue_response(behavior&& bhvr, message_id_t mid) { inline detail::behavior_stack& bhvr_stack();
behavior tmp{std::move(bhvr)};
dequeue_response(tmp, mid);
}
virtual void become_waiting_for(behavior&&, message_id_t) = 0; protected:
inline detail::behavior_stack& bhvr_stack() { virtual void do_become(behavior&& bhvr, bool discard_old) = 0;
return m_bhvr_stack;
}
protected: inline void do_become(const behavior& bhvr, bool discard_old);
inline void remove_handler(message_id id);
void cleanup(std::uint32_t reason);
// true if this actor uses the chained_send optimization // true if this actor uses the chained_send optimization
bool m_chaining; bool m_chaining;
// true if this actor receives EXIT messages as ordinary messages // true if this actor receives EXIT messages as ordinary messages
bool m_trap_exit; bool m_trap_exit;
// true if this actor takes part in cooperative scheduling // true if this actor takes part in cooperative scheduling
bool m_is_scheduled; bool m_is_scheduled;
// pointer to the actor that is marked as successor due to a chained send // pointer to the actor that is marked as successor due to a chained send
actor_ptr m_chained_actor; actor_ptr m_chained_actor;
// identifies the ID of the last sent synchronous request // identifies the ID of the last sent synchronous request
message_id_t m_last_request_id; message_id m_last_request_id;
// identifies all IDs of sync messages waiting for a response // identifies all IDs of sync messages waiting for a response
std::vector<message_id_t> 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;
// allows actors to keep previous behaviors and enables unbecome() // allows actors to keep previous behaviors and enables unbecome()
detail::behavior_stack m_bhvr_stack; detail::behavior_stack m_bhvr_stack;
inline void remove_handler(message_id_t id) {
m_bhvr_stack.erase(id);
}
void cleanup(std::uint32_t reason);
private: private:
std::function<void()> m_sync_failure_handler; std::function<void()> m_sync_failure_handler;
std::function<void()> m_sync_timeout_handler; std::function<void()> m_sync_timeout_handler;
# endif // CPPA_DOCUMENTATION /** @endcond */
protected:
virtual void do_become(behavior&& bhvr, bool discard_old) = 0;
inline void do_become(const behavior& bhvr, bool discard_old) {
behavior copy{bhvr};
do_become(std::move(copy), discard_old);
}
}; };
...@@ -457,10 +356,21 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> { ...@@ -457,10 +356,21 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
*/ */
typedef intrusive_ptr<local_actor> local_actor_ptr; typedef intrusive_ptr<local_actor> local_actor_ptr;
/****************************************************************************** /******************************************************************************
* inline and template member function implementations * * inline and template member function implementations *
******************************************************************************/ ******************************************************************************/
void local_actor::dequeue(behavior&& bhvr) {
behavior tmp{std::move(bhvr)};
dequeue(tmp);
}
inline void local_actor::dequeue_response(behavior&& bhvr, message_id id) {
behavior tmp{std::move(bhvr)};
dequeue_response(tmp, id);
}
inline bool local_actor::trap_exit() const { inline bool local_actor::trap_exit() const {
return m_trap_exit; return m_trap_exit;
} }
...@@ -485,28 +395,90 @@ inline actor_ptr& local_actor::last_sender() { ...@@ -485,28 +395,90 @@ inline actor_ptr& local_actor::last_sender() {
return m_current_node->sender; return m_current_node->sender;
} }
template<bool Discard> template<bool Discard, typename... Ts>
inline void local_actor::become(behavior_policy<Discard>, behavior bhvr) { inline void local_actor::become(behavior_policy<Discard>, Ts&&... args) {
do_become(std::move(bhvr), Discard); do_become(match_expr_convert(std::forward<Ts>(args)...), Discard);
} }
template<bool Discard, typename T0, typename T1, typename... Ts> template<typename T, typename... Ts>
inline void local_actor::become(behavior_policy<Discard>, T0&& a0, T1&& a1, Ts&&... as) { inline void local_actor::become(T arg, Ts&&... args) {
auto bhvr = match_expr_convert(std::forward<T0>(a0), std::forward<T1>(a1), std::forward<Ts>(as)...); do_become(match_expr_convert(arg, std::forward<Ts>(args)...), true);
do_become(std::move(bhvr), Discard);
} }
inline void local_actor::become(behavior bhvr) { inline void local_actor::unbecome() {
do_become(std::move(bhvr), true); m_bhvr_stack.pop_async_back();
} }
template<typename... Cases, typename... Ts> inline bool local_actor::chaining_enabled() {
inline void local_actor::become(match_expr<Cases...> a, Ts&&... as) { return m_chaining && !m_chained_actor;
do_become(match_expr_convert(std::move(a), std::forward<Ts>(as)...), true);
} }
inline void local_actor::unbecome() { inline void local_actor::send_message(channel* whom, any_tuple&& what) {
m_bhvr_stack.pop_async_back(); whom->enqueue(this, std::move(what));
}
inline void local_actor::send_message(actor* whom, any_tuple&& what) {
if (chaining_enabled()) {
if (whom->chained_enqueue(this, std::move(what))) {
m_chained_actor.reset(whom);
}
}
else whom->enqueue(this, std::move(what));
}
inline message_id local_actor::send_sync_message(const actor_ptr& whom, any_tuple&& what) {
auto id = ++m_last_request_id;
CPPA_REQUIRE(id.is_request());
if (chaining_enabled()) {
if (whom->chained_sync_enqueue(this, id, std::move(what))) {
chained_actor(whom);
}
}
else whom->sync_enqueue(this, id, std::move(what));
auto awaited_response = id.response_id();
m_pending_responses.push_back(awaited_response);
return awaited_response;
}
inline message_id local_actor::get_response_id() {
auto id = m_current_node->mid;
return (id.is_request()) ? id.response_id() : message_id();
}
inline const actor_ptr& local_actor::chained_actor() {
return m_chained_actor;
}
inline void local_actor::chained_actor(const actor_ptr& value) {
m_chained_actor = value;
}
inline bool local_actor::awaits(message_id response_id) {
CPPA_REQUIRE(response_id.is_response());
return std::any_of(m_pending_responses.begin(),
m_pending_responses.end(),
[=](message_id other) {
return response_id == other;
});
}
inline void local_actor::mark_arrived(message_id response_id) {
auto last = m_pending_responses.end();
auto i = std::find(m_pending_responses.begin(), last, response_id);
if (i != last) m_pending_responses.erase(i);
}
inline detail::behavior_stack& local_actor::bhvr_stack() {
return m_bhvr_stack;
}
inline void local_actor::do_become(const behavior& bhvr, bool discard_old) {
behavior copy{bhvr};
do_become(std::move(copy), discard_old);
}
inline void local_actor::remove_handler(message_id id) {
m_bhvr_stack.erase(id);
} }
} // namespace cppa } // namespace cppa
......
...@@ -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,51 +34,52 @@ ...@@ -34,51 +34,52 @@
#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
actor_ptr sender; // points to the sender of msg actor_ptr sender; // points to the sender of msg
any_tuple msg; // 'content field' any_tuple msg; // 'content field'
message_id_t 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_t id = message_id_t{}); 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);
} }
......
...@@ -56,7 +56,7 @@ class message_future { ...@@ -56,7 +56,7 @@ class message_future {
public: public:
inline continue_helper(message_id_t mid) : m_mid(mid) { } inline continue_helper(message_id mid) : m_mid(mid) { }
template<typename F> template<typename F>
void continue_with(F fun) { void continue_with(F fun) {
...@@ -71,7 +71,7 @@ class message_future { ...@@ -71,7 +71,7 @@ class message_future {
private: private:
message_id_t m_mid; message_id m_mid;
}; };
...@@ -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);
} }
/** /**
...@@ -127,16 +127,16 @@ class message_future { ...@@ -127,16 +127,16 @@ class message_future {
/** /**
* @brief Returns the awaited response ID. * @brief Returns the awaited response ID.
*/ */
inline const message_id_t& id() const { return m_mid; } inline const message_id& id() const { return m_mid; }
message_future(const message_future&) = default; message_future(const message_future&) = default;
message_future& operator=(const message_future&) = default; message_future& operator=(const message_future&) = default;
inline message_future(const message_id_t& from) : m_mid(from) { } inline message_future(const message_id& from) : m_mid(from) { }
private: private:
message_id_t m_mid; message_id m_mid;
template<typename... Fs> template<typename... Fs>
behavior fs2bhvr(Fs... fs) { behavior fs2bhvr(Fs... fs) {
...@@ -169,9 +169,9 @@ class sync_handle_helper { ...@@ -169,9 +169,9 @@ class sync_handle_helper {
inline sync_handle_helper(const message_future& mf) : m_mf(mf) { } inline sync_handle_helper(const message_future& mf) : m_mf(mf) { }
template<typename... Args> template<typename... Ts>
inline message_future::continue_helper operator()(Args&&... args) { inline message_future::continue_helper operator()(Ts&&... args) {
return m_mf.then(std::forward<Args>(args)...); return m_mf.then(std::forward<Ts>(args)...);
} }
private: private:
...@@ -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:
......
...@@ -42,7 +42,7 @@ struct invalid_message_id { constexpr invalid_message_id() { } }; ...@@ -42,7 +42,7 @@ struct invalid_message_id { constexpr invalid_message_id() { } };
* @brief * @brief
* @note Asynchronous messages always have an invalid message id. * @note Asynchronous messages always have an invalid message id.
*/ */
class message_id_t : util::comparable<message_id_t> { class message_id : util::comparable<message_id> {
static constexpr std::uint64_t response_flag_mask = 0x8000000000000000; static constexpr std::uint64_t response_flag_mask = 0x8000000000000000;
static constexpr std::uint64_t answered_flag_mask = 0x4000000000000000; static constexpr std::uint64_t answered_flag_mask = 0x4000000000000000;
...@@ -50,14 +50,14 @@ class message_id_t : util::comparable<message_id_t> { ...@@ -50,14 +50,14 @@ class message_id_t : util::comparable<message_id_t> {
public: public:
constexpr message_id_t() : m_value(0) { } constexpr message_id() : m_value(0) { }
message_id_t(message_id_t&&) = default; message_id(message_id&&) = default;
message_id_t(const message_id_t&) = default; message_id(const message_id&) = default;
message_id_t& operator=(message_id_t&&) = default; message_id& operator=(message_id&&) = default;
message_id_t& operator=(const message_id_t&) = default; message_id& operator=(const message_id&) = default;
inline message_id_t& operator++() { inline message_id& operator++() {
++m_value; ++m_value;
return *this; return *this;
} }
...@@ -78,12 +78,12 @@ class message_id_t : util::comparable<message_id_t> { ...@@ -78,12 +78,12 @@ class message_id_t : util::comparable<message_id_t> {
return valid() && !is_response(); return valid() && !is_response();
} }
inline message_id_t response_id() const { inline message_id response_id() const {
return message_id_t(valid() ? m_value | response_flag_mask : 0); return message_id(valid() ? m_value | response_flag_mask : 0);
} }
inline message_id_t request_id() const { inline message_id request_id() const {
return message_id_t(m_value & request_id_mask); return message_id(m_value & request_id_mask);
} }
inline void mark_as_answered() { inline void mark_as_answered() {
...@@ -94,24 +94,24 @@ class message_id_t : util::comparable<message_id_t> { ...@@ -94,24 +94,24 @@ class message_id_t : util::comparable<message_id_t> {
return m_value; return m_value;
} }
static inline message_id_t from_integer_value(std::uint64_t value) { static inline message_id from_integer_value(std::uint64_t value) {
message_id_t result; message_id result;
result.m_value = value; result.m_value = value;
return result; return result;
} }
static constexpr invalid_message_id invalid = invalid_message_id{}; static constexpr invalid_message_id invalid = invalid_message_id{};
constexpr message_id_t(invalid_message_id) : m_value(0) { } constexpr message_id(invalid_message_id) : m_value(0) { }
long compare(const message_id_t& other) const { long compare(const message_id& other) const {
return (m_value == other.m_value) return (m_value == other.m_value)
? 0 : ((m_value < other.m_value) ? -1 : 1); ? 0 : ((m_value < other.m_value) ? -1 : 1);
} }
private: private:
explicit constexpr message_id_t(std::uint64_t value) : m_value(value) { } explicit constexpr message_id(std::uint64_t value) : m_value(value) { }
std::uint64_t m_value; std::uint64_t m_value;
......
...@@ -36,8 +36,6 @@ ...@@ -36,8 +36,6 @@
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/network/protocol.hpp"
namespace cppa { namespace network { namespace cppa { namespace network {
class middleman; class middleman;
......
...@@ -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;
...@@ -59,11 +58,11 @@ class sync_request_info : public extend<memory_managed,sync_request_info>:: ...@@ -59,11 +58,11 @@ class sync_request_info : public extend<memory_managed,sync_request_info>::
pointer next; // intrusive next pointer pointer next; // intrusive next pointer
actor_ptr sender; // points to the sender of the message actor_ptr sender; // points to the sender of the message
message_id_t mid; // sync message ID message_id mid; // sync message ID
private: private:
sync_request_info(actor_ptr sptr, message_id_t id); sync_request_info(actor_ptr sptr, message_id id);
}; };
...@@ -79,7 +78,7 @@ class default_actor_proxy : public actor_proxy { ...@@ -79,7 +78,7 @@ class default_actor_proxy : public actor_proxy {
void enqueue(const actor_ptr& sender, any_tuple msg); void enqueue(const actor_ptr& sender, any_tuple msg);
void sync_enqueue(const actor_ptr& sender, message_id_t id, any_tuple msg); void sync_enqueue(const actor_ptr& sender, message_id id, any_tuple msg);
void link_to(const actor_ptr& other); void link_to(const actor_ptr& other);
...@@ -107,7 +106,7 @@ class default_actor_proxy : public actor_proxy { ...@@ -107,7 +106,7 @@ class default_actor_proxy : public actor_proxy {
void forward_msg(const actor_ptr& sender, void forward_msg(const actor_ptr& sender,
any_tuple msg, any_tuple msg,
message_id_t mid = message_id_t()); message_id mid = message_id());
default_protocol_ptr m_proto; default_protocol_ptr m_proto;
process_information_ptr m_pinf; process_information_ptr m_pinf;
......
...@@ -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;
......
...@@ -49,13 +49,13 @@ class message_header { ...@@ -49,13 +49,13 @@ class message_header {
actor_ptr sender; actor_ptr sender;
actor_ptr receiver; actor_ptr receiver;
message_id_t id; message_id id;
message_header(); message_header();
message_header(const actor_ptr& sender, message_header(const actor_ptr& sender,
const actor_ptr& receiver, const actor_ptr& receiver,
message_id_t id = message_id_t::invalid); message_id id = message_id::invalid);
inline void deliver(any_tuple msg) const { inline void deliver(any_tuple msg) const {
if (receiver) { if (receiver) {
......
...@@ -36,15 +36,16 @@ ...@@ -36,15 +36,16 @@
#include <memory> #include <memory>
#include <functional> #include <functional>
#include "cppa/network/protocol.hpp"
#include "cppa/network/acceptor.hpp"
#include "cppa/network/continuable_reader.hpp" #include "cppa/network/continuable_reader.hpp"
#include "cppa/network/continuable_io.hpp"
namespace cppa { namespace detail { class singleton_manager; } } namespace cppa { namespace detail { class singleton_manager; } }
namespace cppa { namespace network { namespace cppa { namespace network {
class protocol;
typedef intrusive_ptr<protocol> protocol_ptr;
/** /**
* @brief Multiplexes asynchronous IO. * @brief Multiplexes asynchronous IO.
*/ */
......
...@@ -39,9 +39,9 @@ ...@@ -39,9 +39,9 @@
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/primitive_variant.hpp" #include "cppa/primitive_variant.hpp"
#include "cppa/intrusive_fwd_ptr.hpp"
#include "cppa/network/acceptor.hpp" #include "cppa/network/acceptor.hpp"
#include "cppa/network/middleman.hpp"
namespace cppa { class actor_addressing; } namespace cppa { class actor_addressing; }
...@@ -83,14 +83,6 @@ class protocol : public ref_counted { ...@@ -83,14 +83,6 @@ class protocol : public ref_counted {
void run_later(std::function<void()> fun); void run_later(std::function<void()> fun);
struct ref_ftor {
void operator()(abstract_middleman*) const;
};
struct deref_ftor {
void operator()(abstract_middleman*) const;
};
protected: protected:
// note: not thread-safe; call only in run_later functor! // note: not thread-safe; call only in run_later functor!
...@@ -111,7 +103,7 @@ class protocol : public ref_counted { ...@@ -111,7 +103,7 @@ class protocol : public ref_counted {
private: private:
intrusive_fwd_ptr<abstract_middleman,ref_ftor,deref_ftor> m_parent; intrusive_ptr<abstract_middleman> m_parent;
}; };
......
...@@ -119,7 +119,7 @@ class object { ...@@ -119,7 +119,7 @@ class object {
/** /**
* @brief Creates a (deep) copy of @p other and assigns it to @p this. * @brief Creates a (deep) copy of @p other and assigns it to @p this.
* @return @p *this * @returns @p *this
*/ */
object& operator=(const object& other); object& operator=(const object& other);
......
...@@ -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,
......
...@@ -61,60 +61,54 @@ class partial_function { ...@@ -61,60 +61,54 @@ class partial_function {
public: public:
/** @cond PRIVATE */
typedef intrusive_ptr<detail::behavior_impl> impl_ptr; typedef intrusive_ptr<detail::behavior_impl> impl_ptr;
inline auto as_behavior_impl() const -> const impl_ptr&;
partial_function(impl_ptr ptr);
static constexpr bool may_have_timeout = false; static constexpr bool may_have_timeout = false;
/** @endcond */
partial_function() = default; partial_function() = default;
partial_function(partial_function&&) = default; partial_function(partial_function&&) = default;
partial_function(const partial_function&) = default; partial_function(const partial_function&) = default;
partial_function& operator=(partial_function&&) = default; partial_function& operator=(partial_function&&) = default;
partial_function& operator=(const partial_function&) = default; partial_function& operator=(const partial_function&) = default;
template<typename... Cases> template<typename... Cs>
partial_function(const match_expr<Cases...>& mexpr) partial_function(const match_expr<Cs...>& mexpr);
: m_impl(mexpr.as_behavior_impl()) { }
partial_function(impl_ptr ptr);
inline bool undefined() const {
return m_impl == nullptr;
}
inline bool defined_at(const any_tuple& value) {
return (m_impl) && m_impl->defined_at(value);
}
template<typename T>
inline bool operator()(T&& arg) {
return (m_impl) && m_impl->invoke(std::forward<T>(arg));
}
inline partial_function or_else(const partial_function& other) const {
return m_impl->or_else(other.m_impl);
}
inline behavior or_else(const behavior& other) const {
return behavior{m_impl->or_else(other.m_impl)};
}
/**
* @brief Returns @p true if this partial function is defined for the
* types of @p value, false otherwise.
*/
inline bool defined_at(const any_tuple& value);
/**
* @brief Returns @p true if this partial function was applied to
* @p args, false otherwise.
* @note This member function can return @p false even if
* {@link defined_at()} returns @p true, because {@link defined_at()}
* does <b>not</b> evaluate guards.
*/
template<typename T> template<typename T>
typename std::conditional<T::may_have_timeout,behavior,partial_function>::type inline bool operator()(T&& arg);
or_else(const T& arg) const;
template<typename T0, typename T1, typename... Ts> /**
* @brief Adds a fallback which is used where
* this partial function is not defined.
*/
template<typename... Ts>
typename std::conditional< typename std::conditional<
util::disjunction< util::disjunction<Ts::may_have_timeout...>::value,
T0::may_have_timeout,
T1::may_have_timeout,
Ts::may_have_timeout...
>::value,
behavior, behavior,
partial_function partial_function
>::type >::type
or_else(const T0& arg0, const T1& arg1, const Ts&... args) const; or_else(Ts&&... args) const;
inline const impl_ptr& as_behavior_impl() const;
private: private:
...@@ -122,45 +116,57 @@ class partial_function { ...@@ -122,45 +116,57 @@ class partial_function {
}; };
template<typename T, typename... Ts> template<typename T>
typename std::conditional<T::may_have_timeout,behavior,partial_function>::type
match_expr_convert(const T& arg) {
return {arg};
}
template<typename T0, typename T1, typename... Ts>
typename std::conditional< typename std::conditional<
util::disjunction< util::disjunction<
T::may_have_timeout, T0::may_have_timeout,
T1::may_have_timeout,
Ts::may_have_timeout... Ts::may_have_timeout...
>::value, >::value,
behavior, behavior,
partial_function partial_function
>::type >::type
match_expr_convert(const T& arg0, const Ts&... args) { match_expr_convert(const T0& arg0, const T1& arg1, const Ts&... args) {
return detail::match_expr_concat(arg0, args...); return detail::match_expr_concat(arg0, arg1, args...);
} }
/****************************************************************************** /******************************************************************************
* inline and template member function implementations * * inline and template member function implementations *
******************************************************************************/ ******************************************************************************/
inline const partial_function::impl_ptr& partial_function::as_behavior_impl() const { template<typename... Cs>
return m_impl; partial_function::partial_function(const match_expr<Cs...>& mexpr)
: m_impl(mexpr.as_behavior_impl()) { }
inline bool partial_function::defined_at(const any_tuple& value) {
return (m_impl) && m_impl->defined_at(value);
} }
template<typename T> template<typename T>
typename std::conditional<T::may_have_timeout,behavior,partial_function>::type inline bool partial_function::operator()(T&& arg) {
partial_function::or_else(const T& arg) const { return (m_impl) && m_impl->invoke(std::forward<T>(arg));
return m_impl->or_else(arg.as_behavior_impl());
} }
template<typename T0, typename T1, typename... Ts> template<typename... Ts>
typename std::conditional< typename std::conditional<
util::disjunction< util::disjunction<Ts::may_have_timeout...>::value,
T0::may_have_timeout,
T1::may_have_timeout,
Ts::may_have_timeout...
>::value,
behavior, behavior,
partial_function partial_function
>::type >::type
partial_function::or_else(const T0& arg0, const T1& arg1, const Ts&... args) const { partial_function::or_else(Ts&&... args) const {
return m_impl->or_else(match_expr_convert(arg0, arg1, args...).as_behavior_impl()); auto tmp = match_expr_convert(std::forward<Ts>(args)...);
return m_impl->or_else(tmp.as_behavior_impl());
}
inline auto partial_function::as_behavior_impl() const -> const impl_ptr& {
return m_impl;
} }
} // namespace cppa } // namespace cppa
......
...@@ -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 {
......
...@@ -38,62 +38,64 @@ ...@@ -38,62 +38,64 @@
namespace cppa { namespace cppa {
#ifdef CPPA_DOCUMENTATION /**
* @ingroup BlockingAPI
* @{
*/
/** /**
* @brief Dequeues the next message from the mailbox that's matched * @brief Dequeues the next message from the mailbox that
* by @p bhvr and executes the corresponding callback. * is matched by given behavior.
* @param bhvr Denotes the actor's response the next incoming message.
*/ */
void receive(behavior& bhvr); template<typename... Ts>
void receive(Ts&&... args);
/** /**
* @brief Receives messages in an endless loop. * @brief Receives messages in an endless loop.
* * Semantically equal to: <tt>for (;;) { receive(...); }</tt>
* Semantically equal to: <tt>for (;;) { receive(bhvr); }</tt>
* @param bhvr Denotes the actor's response the next incoming message.
*/ */
void receive_loop(behavior& bhvr); template<typename... Ts>
void receive_loop(Ts&&... args);
/** /**
* @brief Receives messages as long as @p stmt returns true. * @brief Receives messages as in a range-based loop.
* *
* Semantically equal to: <tt>while (stmt()) { receive(...); }</tt>. * Semantically equal to:
* <tt>for ( ; begin != end; ++begin) { receive(...); }</tt>.
* *
* <b>Usage example:</b> * <b>Usage example:</b>
* @code * @code
* int i = 0; * int i = 0;
* receive_while([&]() { return (++i <= 10); }) * receive_for(i, 10) (
* ( * on(atom("get")) >> [&]() { reply("result", i); }
* on<int>() >> int_fun,
* on<float>() >> float_fun
* ); * );
* @endcode * @endcode
* @param stmt Lambda expression, functor or function returning a @c bool. * @param begin First value in range.
* @param end Last value in range (excluded).
* @returns A functor implementing the loop. * @returns A functor implementing the loop.
*/ */
template<typename Statement> template<typename T>
auto receive_while(Statement&& stmt); detail::receive_for_helper<T> receive_for(T& begin, const T& end);
/** /**
* @brief Receives messages as in a range-based loop. * @brief Receives messages as long as @p stmt returns true.
* *
* Semantically equal to: <tt>for ( ; begin != end; ++begin) { receive(...); }</tt>. * Semantically equal to: <tt>while (stmt()) { receive(...); }</tt>.
* *
* <b>Usage example:</b> * <b>Usage example:</b>
* @code * @code
* int i = 0; * int i = 0;
* receive_for(i, 10) * receive_while([&]() { return (++i <= 10); })
* ( * (
* on(atom("get")) >> [&]() { reply("result", i); } * on<int>() >> int_fun,
* on<float>() >> float_fun
* ); * );
* @endcode * @endcode
* @param begin First value in range. * @param stmt Lambda expression, functor or function returning a @c bool.
* @param end Last value in range (excluded).
* @returns A functor implementing the loop. * @returns A functor implementing the loop.
*/ */
template<typename T> template<typename Statement>
auto receive_for(T& begin, const T& end); detail::receive_while_helper<Statement> receive_while(Statement&& stmt);
/** /**
* @brief Receives messages until @p stmt returns true. * @brief Receives messages until @p stmt returns true.
...@@ -113,32 +115,34 @@ auto receive_for(T& begin, const T& end); ...@@ -113,32 +115,34 @@ auto receive_for(T& begin, const T& end);
* @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.
*/ */
auto do_receive(behavior& bhvr); template<typename... Ts>
detail::do_receive_helper do_receive(Ts&&... args);
#else // CPPA_DOCUMENTATION /**
* @}
*/
inline void receive(behavior& bhvr) { self->dequeue(bhvr); }
inline void receive(partial_function& fun) { self->dequeue(fun); } /******************************************************************************
* inline and template function implementations *
******************************************************************************/
template<typename Arg0, typename... Args> template<typename... Ts>
void receive(Arg0&& arg0, Args&&... args) { void receive(Ts&&... args) {
auto tmp = match_expr_convert(std::forward<Arg0>(arg0), static_assert(sizeof...(Ts), "receive() requires at least one argument");
std::forward<Args>(args)...); self->dequeue(match_expr_convert(std::forward<Ts>(args)...));
receive(tmp);
} }
void receive_loop(behavior& rules); inline void receive_loop(behavior rules) {
void receive_loop(behavior&& rules); local_actor* sptr = self;
for (;;) sptr->dequeue(rules);
void receive_loop(partial_function& rules); }
void receive_loop(partial_function&& rules);
template<typename Arg0, typename... Args> template<typename... Ts>
void receive_loop(Arg0&& arg0, Args&&... args) { void receive_loop(Ts&&... args) {
auto tmp = match_expr_convert(std::forward<Arg0>(arg0), behavior bhvr = match_expr_convert(std::forward<Ts>(args)...);
std::forward<Args>(args)...); local_actor* sptr = self;
receive_loop(tmp); for (;;) sptr->dequeue(bhvr);
} }
template<typename T> template<typename T>
...@@ -153,13 +157,12 @@ detail::receive_while_helper<Statement> receive_while(Statement&& stmt) { ...@@ -153,13 +157,12 @@ detail::receive_while_helper<Statement> receive_while(Statement&& stmt) {
return std::move(stmt); return std::move(stmt);
} }
template<typename... Args> template<typename... Ts>
detail::do_receive_helper do_receive(Args&&... args) { detail::do_receive_helper do_receive(Ts&&... args) {
return detail::do_receive_helper(std::forward<Args>(args)...); behavior bhvr = match_expr_convert(std::forward<Ts>(args)...);
return detail::do_receive_helper(std::move(bhvr));
} }
#endif // CPPA_DOCUMENTATION
} // namespace cppa } // namespace cppa
#endif // CPPA_RECEIVE_HPP #endif // CPPA_RECEIVE_HPP
...@@ -52,7 +52,7 @@ class response_handle { ...@@ -52,7 +52,7 @@ class response_handle {
response_handle(const actor_ptr& from, response_handle(const actor_ptr& from,
const actor_ptr& to, const actor_ptr& to,
const message_id_t& response_id); const message_id& response_id);
/** /**
* @brief Queries whether response message is still outstanding. * @brief Queries whether response message is still outstanding.
...@@ -73,7 +73,7 @@ class response_handle { ...@@ -73,7 +73,7 @@ class response_handle {
/** /**
* @brief Returns the message id for the response message. * @brief Returns the message id for the response message.
*/ */
inline const message_id_t& response_id() const { return m_id; } inline const message_id& response_id() const { return m_id; }
/** /**
* @brief Returns the actor that is going send the response message. * @brief Returns the actor that is going send the response message.
...@@ -89,7 +89,7 @@ class response_handle { ...@@ -89,7 +89,7 @@ class response_handle {
actor_ptr m_from; actor_ptr m_from;
actor_ptr m_to; actor_ptr m_to;
message_id_t m_id; message_id m_id;
}; };
......
...@@ -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,13 +117,15 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox ...@@ -115,13 +117,15 @@ 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);
void sync_enqueue(const actor_ptr&, message_id_t, any_tuple); void sync_enqueue(const actor_ptr&, message_id, any_tuple);
bool chained_sync_enqueue(const actor_ptr&, message_id_t, any_tuple); bool chained_sync_enqueue(const actor_ptr&, message_id, any_tuple);
void request_timeout(const util::duration& d); void request_timeout(const util::duration& d);
...@@ -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;
...@@ -195,7 +197,7 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox ...@@ -195,7 +197,7 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox
bool sync_enqueue_impl(actor_state next, bool sync_enqueue_impl(actor_state next,
const actor_ptr& sender, const actor_ptr& sender,
any_tuple& msg, any_tuple& msg,
message_id_t id); message_id id);
bool m_has_pending_tout; bool m_has_pending_tout;
std::uint32_t m_pending_tout; std::uint32_t m_pending_tout;
......
...@@ -144,7 +144,7 @@ class scheduler { ...@@ -144,7 +144,7 @@ class scheduler {
template<typename Duration, typename... Data> template<typename Duration, typename... Data>
void delayed_reply(const actor_ptr& to, void delayed_reply(const actor_ptr& to,
const Duration& rel_time, const Duration& rel_time,
message_id_t id, message_id id,
any_tuple data ) { any_tuple data ) {
CPPA_REQUIRE(!id.valid() || id.is_response()); CPPA_REQUIRE(!id.valid() || id.is_response());
if (id.valid()) { if (id.valid()) {
......
...@@ -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 {
...@@ -61,25 +64,18 @@ class stacked : public Base { ...@@ -61,25 +64,18 @@ class stacked : public Base {
static constexpr auto receive_flag = detail::rp_nestable; static constexpr auto receive_flag = detail::rp_nestable;
virtual void dequeue(partial_function& fun) {
m_recv_policy.receive(dthis(), fun);
}
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_t 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) {
...@@ -91,55 +87,46 @@ class stacked : public Base { ...@@ -91,55 +87,46 @@ 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_t()); become_impl(std::move(bhvr), discard_old, message_id());
} }
virtual void become_waiting_for(behavior&& bhvr, message_id_t mid) { virtual void become_waiting_for(behavior bhvr, message_id mid) {
become_impl(std::move(bhvr), false, mid); become_impl(std::move(bhvr), false, mid);
} }
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;
void become_impl(behavior&& bhvr, bool discard_old, message_id_t mid) { private:
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_t 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,149 +28,142 @@ ...@@ -28,149 +28,142 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_INTRUSIVE_FWD_PTR_HPP #ifndef CPPA_THREADED_HPP
#define CPPA_INTRUSIVE_FWD_PTR_HPP #define CPPA_THREADED_HPP
#include <memory> #include <mutex>
#include <chrono>
#include <condition_variable>
#include "cppa/util/comparable.hpp" #include "cppa/mailbox_element.hpp"
#include "cppa/util/dptr.hpp"
#include "cppa/detail/sync_request_bouncer.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
namespace cppa { namespace detail { class receive_policy; } }
namespace cppa { namespace cppa {
/** template<class Base, class Subtype>
* @brief A reference counting smart pointer implementation that class threaded : public Base {
* can be used with forward declarated types.
* @warning libcppa assumes T is derived from ref_counted and friend class detail::receive_policy;
* implicitly converts intrusive_fwd_ptr to intrusive_ptr
* @relates intrusive_ptr typedef std::unique_lock<std::mutex> lock_type;
* @relates ref_counted
*/
template<typename T, typename Ref, typename Deref>
class intrusive_fwd_ptr : util::comparable<intrusive_fwd_ptr<T,Ref,Deref> >,
util::comparable<intrusive_fwd_ptr<T,Ref,Deref>, const T*>,
util::comparable<intrusive_fwd_ptr<T,Ref,Deref>, std::nullptr_t> {
public: public:
typedef T* pointer; template<typename... Ts>
typedef const T* const_pointer; threaded(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
typedef T element_type;
typedef T& reference;
typedef const T& const_reference;
intrusive_fwd_ptr(pointer raw_ptr = nullptr, Ref ref = Ref(), Deref deref = Deref()) inline void reset_timeout() { }
: m_ref(std::move(ref)), m_deref(std::move(deref)) { set_ptr(raw_ptr); }
intrusive_fwd_ptr(intrusive_fwd_ptr&& other) inline void request_timeout(const util::duration&) { }
: m_ref(std::move(other.m_ref))
, m_deref(std::move(m_deref))
, m_ptr(other.release()) { }
intrusive_fwd_ptr(const intrusive_fwd_ptr& other) inline void handle_timeout(behavior& bhvr) { bhvr.handle_timeout(); }
: m_ref(other.m_ref), m_deref(other.m_deref) { set_ptr(other.get()); }
~intrusive_fwd_ptr() { if (m_ptr) m_deref(m_ptr); } inline void pop_timeout() { }
inline void swap(intrusive_fwd_ptr& other) { inline void push_timeout() { }
std::swap(m_ptr, other.m_ptr);
}
/** inline bool waits_for_timeout(std::uint32_t) { return false; }
* @brief Returns the raw pointer without modifying reference count.
*/
pointer release() {
auto result = m_ptr;
m_ptr = nullptr;
return result;
}
/** mailbox_element* pop() {
* @brief Sets this pointer to @p ptr without modifying reference count. wait_for_data();
*/ return this->m_mailbox.try_pop();
void adopt(pointer ptr) {
reset();
m_ptr = ptr;
} }
void reset(pointer new_value = nullptr) { inline mailbox_element* try_pop() {
if (m_ptr) m_deref(m_ptr); return this->m_mailbox.try_pop();
set_ptr(new_value);
} }
template<typename... Args> template<typename TimePoint>
void emplace(Args&&... args) { mailbox_element* try_pop(const TimePoint& abs_time) {
reset(new T(std::forward<Args>(args)...)); return (timed_wait_for_data(abs_time)) ? try_pop() : nullptr;
} }
intrusive_fwd_ptr& operator=(pointer ptr) { bool push_back(mailbox_element* new_element) {
reset(ptr); switch (this->m_mailbox.enqueue(new_element)) {
return *this; case intrusive::first_enqueued: {
lock_type guard(m_mtx);
m_cv.notify_one();
return true;
}
default: return true;
case intrusive::queue_closed: return false;
} }
intrusive_fwd_ptr& operator=(intrusive_fwd_ptr&& other) {
swap(other);
return *this;
} }
intrusive_fwd_ptr& operator=(const intrusive_fwd_ptr& other) { void run_detached() {
intrusive_fwd_ptr tmp(other); auto dthis = util::dptr<Subtype>(this);
swap(tmp); dthis->init();
return *this; dthis->m_bhvr_stack.exec(dthis->m_recv_policy, dthis);
dthis->on_exit();
} }
inline pointer get() const { return m_ptr; } protected:
inline pointer operator->() const { return m_ptr; } typedef threaded combined_type;
inline reference operator*() const { return *m_ptr; } virtual void enqueue(const actor_ptr& sender, any_tuple msg) {
auto ptr = this->new_mailbox_element(sender, std::move(msg));
push_back(ptr);
}
inline bool operator!() const { return m_ptr == nullptr; } 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);
}
}
inline explicit operator bool() const { return m_ptr != nullptr; } typedef std::chrono::high_resolution_clock::time_point timeout_type;
inline ptrdiff_t compare(const_pointer ptr) const { timeout_type init_timeout(const util::duration& rel_time) {
return static_cast<ptrdiff_t>(get() - ptr); auto result = std::chrono::high_resolution_clock::now();
result += rel_time;
return result;
} }
inline ptrdiff_t compare(const intrusive_fwd_ptr& other) const { mailbox_element* await_message() {
return compare(other.get()); return pop();
} }
inline ptrdiff_t compare(std::nullptr_t) const { mailbox_element* await_message(const timeout_type& abs_time) {
return reinterpret_cast<ptrdiff_t>(get()); return try_pop(abs_time);
} }
private: private:
Ref m_ref; bool timed_wait_for_data(const timeout_type& abs_time) {
Deref m_deref; CPPA_REQUIRE(not this->m_mailbox.closed());
pointer m_ptr; 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;
}
inline void set_ptr(pointer raw_ptr) { void wait_for_data() {
m_ptr = raw_ptr; if (this->m_mailbox.empty()) {
if (raw_ptr) m_ref(raw_ptr); lock_type guard(m_mtx);
while (this->m_mailbox.empty()) m_cv.wait(guard);
}
} }
}; std::mutex m_mtx;
std::condition_variable m_cv;
/** };
* @relates intrusive_ptr
*/
template<typename T, typename Ref, typename Deref>
inline bool operator==(const intrusive_fwd_ptr<T,Ref,Deref>& lhs,
const intrusive_fwd_ptr<T,Ref,Deref>& rhs) {
return lhs.get() == rhs.get();
}
/**
* @relates intrusive_ptr
*/
template<typename T, typename Ref, typename Deref>
inline bool operator!=(const intrusive_fwd_ptr<T,Ref,Deref>& lhs,
const intrusive_fwd_ptr<T,Ref,Deref>& rhs) {
return !(lhs == rhs);
}
} // namespace cppa } // namespace cppa
#endif // CPPA_INTRUSIVE_FWD_PTR_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
...@@ -28,33 +28,43 @@ ...@@ -28,33 +28,43 @@
\******************************************************************************/ \******************************************************************************/
#include "cppa/cppa.hpp" #ifndef CPPA_IS_CALLABLE_HPP
#include "cppa/receive.hpp" #define CPPA_IS_CALLABLE_HPP
namespace cppa { #include "cppa/util/conjunction.hpp"
#include "cppa/util/callable_trait.hpp"
void receive_loop(behavior& rules) { namespace cppa { namespace util {
local_actor* sptr = self;
for (;;) { template<typename T>
sptr->dequeue(rules); struct is_callable {
}
}
void receive_loop(behavior&& rules) { template<typename C>
behavior tmp(std::move(rules)); static bool _fun(C*, typename callable_trait<C>::result_type* = nullptr) {
receive_loop(tmp); return true;
} }
void receive_loop(partial_function& rules) { template<typename C>
local_actor* sptr = self; static bool _fun(C*, typename callable_trait<decltype(&C::operator())>::result_type* = nullptr) {
for (;;) { return true;
sptr->dequeue(rules);
} }
}
void receive_loop(partial_function&& rules) { static void _fun(void*) { }
partial_function tmp(std::move(rules));
receive_loop(tmp); 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
} // namespace cppa #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
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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_STATIC_FOREACH_HPP
#define CPPA_STATIC_FOREACH_HPP
#include "cppa/get.hpp"
namespace cppa { namespace util {
template<bool BeginLessEnd, size_t Begin, size_t End>
struct static_foreach_impl {
template<typename Container, typename Fun, typename... Args>
static inline void _(const Container& c, Fun& f, Args&&... args) {
f(get<Begin>(c), std::forward<Args>(args)...);
static_foreach_impl<(Begin+1 < End), Begin+1, End>
::_(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline void _ref(Container& c, Fun& f, Args&&... args) {
f(get_ref<Begin>(c), std::forward<Args>(args)...);
static_foreach_impl<(Begin+1 < End), Begin+1, End>
::_ref(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline void _auto(Container& c, Fun& f, Args&&... args) {
_ref(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline void _auto(const Container& c, Fun& f, Args&&... args) {
_(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline bool eval(const Container& c, Fun& f, Args&&... args) {
return f(get<Begin>(c), std::forward<Args>(args)...)
&& static_foreach_impl<(Begin+1 < End), Begin+1, End>
::eval(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline bool eval_or(const Container& c, Fun& f, Args&&... args) {
return f(get<Begin>(c), std::forward<Args>(args)...)
|| static_foreach_impl<(Begin+1 < End), Begin+1, End>
::eval_or(c, f, std::forward<Args>(args)...);
}
};
template<size_t X, size_t Y>
struct static_foreach_impl<false, X, Y> {
template<typename... Args>
static inline void _(Args&&...) { }
template<typename... Args>
static inline void _ref(Args&&...) { }
template<typename... Args>
static inline void _auto(Args&&...) { }
template<typename... Args>
static inline bool eval(Args&&...) { return true; }
template<typename... Args>
static inline bool eval_or(Args&&...) { return false; }
};
/**
* @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
#endif // CPPA_STATIC_FOREACH_HPP
...@@ -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 {
......
...@@ -69,7 +69,7 @@ bool actor::chained_enqueue(const actor_ptr& sender, any_tuple msg) { ...@@ -69,7 +69,7 @@ bool actor::chained_enqueue(const actor_ptr& sender, any_tuple msg) {
return false; return false;
} }
bool actor::chained_sync_enqueue(const actor_ptr& ptr, message_id_t id, any_tuple msg) { bool actor::chained_sync_enqueue(const actor_ptr& ptr, message_id id, any_tuple msg) {
sync_enqueue(ptr, id, std::move(msg)); sync_enqueue(ptr, id, std::move(msg));
return false; return false;
} }
......
...@@ -62,7 +62,7 @@ struct behavior_stack_mover : iterator<output_iterator_tag,void,void,void,void>{ ...@@ -62,7 +62,7 @@ struct behavior_stack_mover : iterator<output_iterator_tag,void,void,void,void>{
inline behavior_stack_mover move_iter(behavior_stack* bs) { return {bs}; } inline behavior_stack_mover move_iter(behavior_stack* bs) { return {bs}; }
option<behavior&> behavior_stack::sync_handler(message_id_t expected_response) { option<behavior&> behavior_stack::sync_handler(message_id expected_response) {
if (expected_response.valid()) { if (expected_response.valid()) {
auto e = m_elements.rend(); auto e = m_elements.rend();
auto i = find_if(m_elements.rbegin(), e, [=](element_type& val) { auto i = find_if(m_elements.rbegin(), e, [=](element_type& val) {
......
...@@ -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) {
......
...@@ -42,11 +42,11 @@ using namespace std; ...@@ -42,11 +42,11 @@ using namespace std;
namespace cppa { namespace network { namespace cppa { namespace network {
inline sync_request_info* new_req_info(actor_ptr sptr, message_id_t id) { inline sync_request_info* new_req_info(actor_ptr sptr, message_id id) {
return detail::memory::create<sync_request_info>(std::move(sptr), id); return detail::memory::create<sync_request_info>(std::move(sptr), id);
} }
sync_request_info::sync_request_info(actor_ptr sptr, message_id_t id) sync_request_info::sync_request_info(actor_ptr sptr, message_id id)
: next(nullptr), sender(std::move(sptr)), mid(id) { } : next(nullptr), sender(std::move(sptr)), mid(id) { }
default_actor_proxy::default_actor_proxy(actor_id mid, default_actor_proxy::default_actor_proxy(actor_id mid,
...@@ -89,7 +89,7 @@ void default_actor_proxy::deliver(const network::message_header& hdr, any_tuple ...@@ -89,7 +89,7 @@ void default_actor_proxy::deliver(const network::message_header& hdr, any_tuple
void default_actor_proxy::forward_msg(const actor_ptr& sender, void default_actor_proxy::forward_msg(const actor_ptr& sender,
any_tuple msg, any_tuple msg,
message_id_t mid) { message_id mid) {
CPPA_LOG_TRACE(""); CPPA_LOG_TRACE("");
if (sender && mid.is_request()) { if (sender && mid.is_request()) {
switch (m_pending_requests.enqueue(new_req_info(sender, mid))) { switch (m_pending_requests.enqueue(new_req_info(sender, mid))) {
...@@ -147,7 +147,7 @@ void default_actor_proxy::enqueue(const actor_ptr& sender, any_tuple msg) { ...@@ -147,7 +147,7 @@ void default_actor_proxy::enqueue(const actor_ptr& sender, any_tuple msg) {
} }
void default_actor_proxy::sync_enqueue(const actor_ptr& sender, void default_actor_proxy::sync_enqueue(const actor_ptr& sender,
message_id_t mid, message_id mid,
any_tuple msg) { any_tuple msg) {
CPPA_LOG_TRACE(CPPA_TARG(sender, to_string) << ", " CPPA_LOG_TRACE(CPPA_TARG(sender, to_string) << ", "
<< CPPA_MARG(mid, integer_value) << ", " << CPPA_MARG(mid, integer_value) << ", "
......
...@@ -78,11 +78,7 @@ void event_based_actor::dequeue(behavior&) { ...@@ -78,11 +78,7 @@ void event_based_actor::dequeue(behavior&) {
quit(exit_reason::unallowed_function_call); quit(exit_reason::unallowed_function_call);
} }
void event_based_actor::dequeue(partial_function&) { void event_based_actor::dequeue_response(behavior&, message_id) {
quit(exit_reason::unallowed_function_call);
}
void event_based_actor::dequeue_response(behavior&, message_id_t) {
quit(exit_reason::unallowed_function_call); quit(exit_reason::unallowed_function_call);
} }
...@@ -142,7 +138,7 @@ resume_result event_based_actor::resume(util::fiber*, actor_ptr& next_job) { ...@@ -142,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()
...@@ -193,7 +189,7 @@ void event_based_actor::do_become(behavior&& bhvr, bool discard_old) { ...@@ -193,7 +189,7 @@ void event_based_actor::do_become(behavior&& bhvr, bool discard_old) {
m_bhvr_stack.push_back(std::move(bhvr)); m_bhvr_stack.push_back(std::move(bhvr));
} }
void event_based_actor::become_waiting_for(behavior&& bhvr, message_id_t mf) { void event_based_actor::become_waiting_for(behavior bhvr, message_id mf) {
if (bhvr.timeout().valid()) { if (bhvr.timeout().valid()) {
reset_timeout(); reset_timeout();
request_timeout(bhvr.timeout()); request_timeout(bhvr.timeout());
......
...@@ -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());
......
...@@ -75,11 +75,11 @@ local_actor::local_actor(bool sflag) ...@@ -75,11 +75,11 @@ local_actor::local_actor(bool sflag)
: m_chaining(sflag), m_trap_exit(false) : m_chaining(sflag), m_trap_exit(false)
, m_is_scheduled(sflag), m_dummy_node(), m_current_node(&m_dummy_node) { } , m_is_scheduled(sflag), m_dummy_node(), m_current_node(&m_dummy_node) { }
void local_actor::monitor(actor_ptr whom) { void local_actor::monitor(const actor_ptr& whom) {
if (whom) whom->attach(attachable_ptr{new down_observer(this, whom)}); if (whom) whom->attach(attachable_ptr{new down_observer(this, whom)});
} }
void local_actor::demonitor(actor_ptr whom) { void local_actor::demonitor(const actor_ptr& whom) {
attachable::token mtoken{typeid(down_observer), this}; attachable::token mtoken{typeid(down_observer), this};
if (whom) whom->detach(mtoken); if (whom) whom->detach(mtoken);
} }
...@@ -113,12 +113,12 @@ void local_actor::reply_message(any_tuple&& what) { ...@@ -113,12 +113,12 @@ void local_actor::reply_message(any_tuple&& what) {
} }
auto& id = m_current_node->mid; auto& id = m_current_node->mid;
if (id.valid() == false || id.is_response()) { if (id.valid() == false || id.is_response()) {
send_message(whom, std::move(what)); send_message(whom.get(), std::move(what));
} }
else if (!id.is_answered()) { else if (!id.is_answered()) {
if (chaining_enabled()) { if (chaining_enabled()) {
if (whom->chained_sync_enqueue(this, id.response_id(), std::move(what))) { if (whom->chained_sync_enqueue(this, id.response_id(), std::move(what))) {
m_chained_actor = whom; chained_actor(whom);
} }
} }
else { else {
...@@ -140,7 +140,7 @@ void local_actor::forward_message(const actor_ptr& new_receiver) { ...@@ -140,7 +140,7 @@ void local_actor::forward_message(const actor_ptr& new_receiver) {
else { else {
new_receiver->sync_enqueue(from.get(), id, m_current_node->msg); new_receiver->sync_enqueue(from.get(), id, m_current_node->msg);
// treat this message as asynchronous message from now on // treat this message as asynchronous message from now on
m_current_node->mid = message_id_t(); m_current_node->mid = message_id();
} }
} }
...@@ -151,7 +151,7 @@ response_handle local_actor::make_response_handle() { ...@@ -151,7 +151,7 @@ response_handle local_actor::make_response_handle() {
return std::move(result); return std::move(result);
} }
message_id_t local_actor::send_timed_sync_message(const actor_ptr& whom, message_id local_actor::send_timed_sync_message(const actor_ptr& whom,
const util::duration& rel_time, const util::duration& rel_time,
any_tuple&& what) { any_tuple&& what) {
auto mid = this->send_sync_message(whom, std::move(what)); auto mid = this->send_sync_message(whom, std::move(what));
...@@ -164,10 +164,6 @@ void local_actor::exec_behavior_stack() { ...@@ -164,10 +164,6 @@ void local_actor::exec_behavior_stack() {
// default implementation does nothing // default implementation does nothing
} }
sync_handle_helper local_actor::handle_response(const message_future& mf) {
return ::cppa::handle_response(mf);
}
void local_actor::cleanup(std::uint32_t reason) { void local_actor::cleanup(std::uint32_t reason) {
m_subscriptions.clear(); m_subscriptions.clear();
super::cleanup(reason); super::cleanup(reason);
......
...@@ -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_t 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;
} }
......
...@@ -34,7 +34,7 @@ namespace cppa { namespace network { ...@@ -34,7 +34,7 @@ namespace cppa { namespace network {
message_header::message_header(const actor_ptr& s, message_header::message_header(const actor_ptr& s,
const actor_ptr& r, const actor_ptr& r,
message_id_t mid ) message_id mid )
: sender(s), receiver(r), id(mid) { } : sender(s), receiver(r), id(mid) { }
message_header::message_header() : sender(nullptr), receiver(nullptr), id() { } message_header::message_header() : sender(nullptr), receiver(nullptr), id() { }
......
...@@ -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"
......
...@@ -34,14 +34,6 @@ ...@@ -34,14 +34,6 @@
namespace cppa { namespace network { namespace cppa { namespace network {
void protocol::ref_ftor::operator()(abstract_middleman* ptr) const {
if (ptr) ptr->ref();
}
void protocol::deref_ftor::operator()(abstract_middleman* ptr) const {
if (ptr) ptr->deref();
}
protocol::protocol(abstract_middleman* parent) : m_parent(parent) { protocol::protocol(abstract_middleman* parent) : m_parent(parent) {
CPPA_REQUIRE(parent != nullptr); CPPA_REQUIRE(parent != nullptr);
} }
......
...@@ -40,7 +40,7 @@ namespace cppa { ...@@ -40,7 +40,7 @@ namespace cppa {
response_handle::response_handle(const actor_ptr& from, response_handle::response_handle(const actor_ptr& from,
const actor_ptr& to, const actor_ptr& to,
const message_id_t& id) const message_id& id)
: m_from(from), m_to(to), m_id(id) { : m_from(from), m_to(to), m_id(id) {
CPPA_REQUIRE(id.is_response()); CPPA_REQUIRE(id.is_response());
} }
......
...@@ -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);
...@@ -133,7 +137,7 @@ bool scheduled_actor::enqueue(actor_state next_state, ...@@ -133,7 +137,7 @@ bool scheduled_actor::enqueue(actor_state next_state,
bool scheduled_actor::sync_enqueue_impl(actor_state next, bool scheduled_actor::sync_enqueue_impl(actor_state next,
const actor_ptr& sender, const actor_ptr& sender,
any_tuple& msg, any_tuple& msg,
message_id_t id) { message_id id) {
bool err = false; bool err = false;
auto ptr = new_mailbox_element(sender, std::move(msg), id); auto ptr = new_mailbox_element(sender, std::move(msg), id);
bool res = enqueue(next, &err, ptr); bool res = enqueue(next, &err, ptr);
...@@ -162,13 +166,13 @@ bool scheduled_actor::chained_enqueue(const actor_ptr& sender, any_tuple msg) { ...@@ -162,13 +166,13 @@ bool scheduled_actor::chained_enqueue(const actor_ptr& sender, any_tuple msg) {
} }
void scheduled_actor::sync_enqueue(const actor_ptr& sender, void scheduled_actor::sync_enqueue(const actor_ptr& sender,
message_id_t id, message_id id,
any_tuple msg) { any_tuple msg) {
sync_enqueue_impl(actor_state::ready, sender, msg, id); sync_enqueue_impl(actor_state::ready, sender, msg, id);
} }
bool scheduled_actor::chained_sync_enqueue(const actor_ptr& sender, bool scheduled_actor::chained_sync_enqueue(const actor_ptr& sender,
message_id_t id, message_id id,
any_tuple msg) { any_tuple msg) {
return sync_enqueue_impl(actor_state::pending, sender, msg, id); return sync_enqueue_impl(actor_state::pending, sender, msg, id);
} }
......
...@@ -38,14 +38,13 @@ scheduled_actor_dummy::scheduled_actor_dummy() ...@@ -38,14 +38,13 @@ scheduled_actor_dummy::scheduled_actor_dummy()
void scheduled_actor_dummy::enqueue(const actor_ptr&, any_tuple) { } void scheduled_actor_dummy::enqueue(const actor_ptr&, any_tuple) { }
void scheduled_actor_dummy::quit(std::uint32_t) { } void scheduled_actor_dummy::quit(std::uint32_t) { }
void scheduled_actor_dummy::dequeue(behavior&) { } void scheduled_actor_dummy::dequeue(behavior&) { }
void scheduled_actor_dummy::dequeue(partial_function&) { } void scheduled_actor_dummy::dequeue_response(behavior&, message_id) { }
void scheduled_actor_dummy::dequeue_response(behavior&, message_id_t) { }
void scheduled_actor_dummy::do_become(behavior&&, bool) { } void scheduled_actor_dummy::do_become(behavior&&, bool) { }
void scheduled_actor_dummy::become_waiting_for(behavior&&, message_id_t) { } void scheduled_actor_dummy::become_waiting_for(behavior, message_id) { }
bool scheduled_actor_dummy::has_behavior() { return false; } bool scheduled_actor_dummy::has_behavior() { return false; }
void scheduled_actor_dummy::sync_enqueue(const actor_ptr&, void scheduled_actor_dummy::sync_enqueue(const actor_ptr&,
message_id_t, message_id,
any_tuple) { } any_tuple) { }
resume_result scheduled_actor_dummy::resume(util::fiber*,actor_ptr&) { resume_result scheduled_actor_dummy::resume(util::fiber*,actor_ptr&) {
......
...@@ -68,13 +68,13 @@ class delayed_msg { ...@@ -68,13 +68,13 @@ class delayed_msg {
delayed_msg(const channel_ptr& arg0, delayed_msg(const channel_ptr& arg0,
const actor_ptr& arg1, const actor_ptr& arg1,
message_id_t, message_id,
any_tuple&& arg3) any_tuple&& arg3)
: ptr_a(arg0), from(arg1), msg(move(arg3)) { } : ptr_a(arg0), from(arg1), msg(move(arg3)) { }
delayed_msg(const actor_ptr& arg0, delayed_msg(const actor_ptr& arg0,
const actor_ptr& arg1, const actor_ptr& arg1,
message_id_t arg2, message_id arg2,
any_tuple&& arg3) any_tuple&& arg3)
: ptr_b(arg0), from(arg1), id(arg2), msg(move(arg3)) { } : ptr_b(arg0), from(arg1), id(arg2), msg(move(arg3)) { }
...@@ -94,7 +94,7 @@ class delayed_msg { ...@@ -94,7 +94,7 @@ class delayed_msg {
channel_ptr ptr_a; channel_ptr ptr_a;
actor_ptr ptr_b; actor_ptr ptr_b;
actor_ptr from; actor_ptr from;
message_id_t id; message_id id;
any_tuple msg; any_tuple msg;
}; };
...@@ -146,7 +146,7 @@ inline void insert_dmsg(Map& storage, ...@@ -146,7 +146,7 @@ inline void insert_dmsg(Map& storage,
const T& to, const T& to,
const actor_ptr& sender, const actor_ptr& sender,
any_tuple&& tup, any_tuple&& tup,
message_id_t id = message_id_t{}) { message_id id = message_id{}) {
auto tout = hrc::now(); auto tout = hrc::now();
tout += d; tout += d;
delayed_msg dmsg{to, sender, id, move(tup)}; delayed_msg dmsg{to, sender, id, move(tup)};
...@@ -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
...@@ -170,7 +169,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) { ...@@ -170,7 +169,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
}, },
on(atom("REPLY"), arg_match) >> [&](const util::duration& d, on(atom("REPLY"), arg_match) >> [&](const util::duration& d,
const actor_ptr& ptr, const actor_ptr& ptr,
message_id_t id, message_id id,
any_tuple& tup) { any_tuple& tup) {
insert_dmsg(messages, d, ptr, msg_ptr->sender, move(tup), id); insert_dmsg(messages, d, ptr, msg_ptr->sender, move(tup), id);
}, },
...@@ -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;
...@@ -60,7 +61,7 @@ void thread_mapped_actor::enqueue(const actor_ptr& sender, any_tuple msg) { ...@@ -60,7 +61,7 @@ void thread_mapped_actor::enqueue(const actor_ptr& sender, any_tuple msg) {
} }
void thread_mapped_actor::sync_enqueue(const actor_ptr& sender, void thread_mapped_actor::sync_enqueue(const actor_ptr& sender,
message_id_t id, message_id id,
any_tuple msg) { any_tuple msg) {
auto ptr = this->new_mailbox_element(sender, std::move(msg), id); auto ptr = this->new_mailbox_element(sender, std::move(msg), id);
if (!this->m_mailbox.push_back(ptr)) { if (!this->m_mailbox.push_back(ptr)) {
...@@ -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);
} }
......
...@@ -43,29 +43,27 @@ ...@@ -43,29 +43,27 @@
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/exception.hpp" #include "cppa/exception.hpp"
#include "cppa/singletons.hpp"
#include "cppa/exit_reason.hpp" #include "cppa/exit_reason.hpp"
#include "cppa/binary_serializer.hpp" #include "cppa/binary_serializer.hpp"
#include "cppa/binary_deserializer.hpp" #include "cppa/binary_deserializer.hpp"
#include "cppa/intrusive/single_reader_queue.hpp" #include "cppa/intrusive/single_reader_queue.hpp"
#include "cppa/network/acceptor.hpp"
#include "cppa/network/protocol.hpp"
#include "cppa/network/middleman.hpp" #include "cppa/network/middleman.hpp"
#include "cppa/network/ipv4_acceptor.hpp" #include "cppa/network/ipv4_acceptor.hpp"
#include "cppa/network/ipv4_io_stream.hpp" #include "cppa/network/ipv4_io_stream.hpp"
#include "cppa/detail/actor_registry.hpp"
#include "cppa/detail/singleton_manager.hpp"
namespace cppa { namespace cppa {
using namespace detail; using namespace detail;
using namespace network; using namespace network;
namespace { namespace { protocol_ptr proto() {
protocol* proto() { return get_middleman()->protocol(atom("DEFAULT")).get();
return singleton_manager::get_middleman()->protocol(atom("DEFAULT")).get(); } }
}
} // namespace <anonymous>
void publish(actor_ptr whom, std::unique_ptr<acceptor> aptr) { void publish(actor_ptr whom, std::unique_ptr<acceptor> aptr) {
proto()->publish(whom, move(aptr), {}); proto()->publish(whom, move(aptr), {});
......
...@@ -412,7 +412,7 @@ class msg_hdr_tinfo : public util::abstract_uniform_type_info<network::message_h ...@@ -412,7 +412,7 @@ class msg_hdr_tinfo : public util::abstract_uniform_type_info<network::message_h
actor_ptr_tinfo::s_deserialize(msg.sender, source, actor_ptr_name); actor_ptr_tinfo::s_deserialize(msg.sender, source, actor_ptr_name);
actor_ptr_tinfo::s_deserialize(msg.receiver, source, actor_ptr_name); actor_ptr_tinfo::s_deserialize(msg.receiver, source, actor_ptr_name);
auto msg_id = source->read<std::uint64_t>(); auto msg_id = source->read<std::uint64_t>();
msg.id = message_id_t::from_integer_value(msg_id); msg.id = message_id::from_integer_value(msg_id);
source->end_object(); source->end_object();
} }
......
...@@ -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);
...@@ -461,7 +477,7 @@ int main() { ...@@ -461,7 +477,7 @@ int main() {
self->become ( self->become (
on("hi") >> [&]() { on("hi") >> [&]() {
auto handle = sync_send(self->last_sender(), "whassup?"); auto handle = sync_send(self->last_sender(), "whassup?");
self->handle_response(handle) ( handle_response(handle) (
on_arg_match >> [&](const string& str) { on_arg_match >> [&](const string& str) {
CPPA_CHECK(self->last_sender() != nullptr); CPPA_CHECK(self->last_sender() != nullptr);
CPPA_CHECK_EQUAL(str, "nothing"); CPPA_CHECK_EQUAL(str, "nothing");
......
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