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>
behavior(const match_expr<Cases...>& arg0, const Arg1& arg1, const Args&... args)
: m_impl(detail::match_expr_concat(arg0, arg1, args...)) { }
inline void handle_timeout() { template<typename... Cases, typename... Ts>
m_impl->handle_timeout(); behavior(const match_expr<Cases...>& arg, const Ts&... args);
}
inline const util::duration& timeout() const { /**
return m_impl->timeout(); * @brief Invokes the timeout callback.
} */
inline void handle_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,any_tuple>::value, !std::is_convertible<T,std::string>::value
const actor_ostream&>::type && !std::is_convertible<T,any_tuple>::value,
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
......
This diff is collapsed.
...@@ -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;
......
This diff is collapsed.
...@@ -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); * @brief Returns @p true if this partial function is defined for the
* types of @p value, false otherwise.
inline bool undefined() const { */
return m_impl == nullptr; inline bool defined_at(const any_tuple& value);
}
/**
inline bool defined_at(const any_tuple& value) { * @brief Returns @p true if this partial function was applied to
return (m_impl) && m_impl->defined_at(value); * @p args, false otherwise.
} * @note This member function can return @p false even if
* {@link defined_at()} returns @p true, because {@link defined_at()}
template<typename T> * does <b>not</b> evaluate guards.
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)};
}
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
* implicitly converts intrusive_fwd_ptr to intrusive_ptr
* @relates intrusive_ptr
* @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: friend class detail::receive_policy;
typedef T* pointer; typedef std::unique_lock<std::mutex> lock_type;
typedef const T* const_pointer;
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()) public:
: m_ref(std::move(ref)), m_deref(std::move(deref)) { set_ptr(raw_ptr); }
intrusive_fwd_ptr(intrusive_fwd_ptr&& other) template<typename... Ts>
: m_ref(std::move(other.m_ref)) threaded(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
, m_deref(std::move(m_deref))
, m_ptr(other.release()) { }
intrusive_fwd_ptr(const intrusive_fwd_ptr& other) inline void reset_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 request_timeout(const util::duration&) { }
inline void swap(intrusive_fwd_ptr& other) { inline void handle_timeout(behavior& bhvr) { bhvr.handle_timeout(); }
std::swap(m_ptr, other.m_ptr);
}
/** inline void pop_timeout() { }
* @brief Returns the raw pointer without modifying reference count.
*/
pointer release() {
auto result = m_ptr;
m_ptr = nullptr;
return result;
}
/** inline void push_timeout() { }
* @brief Sets this pointer to @p ptr without modifying reference count.
*/ inline bool waits_for_timeout(std::uint32_t) { return false; }
void adopt(pointer ptr) {
reset();
m_ptr = ptr;
}
void reset(pointer new_value = nullptr) { mailbox_element* pop() {
if (m_ptr) m_deref(m_ptr); wait_for_data();
set_ptr(new_value); return this->m_mailbox.try_pop();
} }
template<typename... Args> inline mailbox_element* try_pop() {
void emplace(Args&&... args) { return this->m_mailbox.try_pop();
reset(new T(std::forward<Args>(args)...));
} }
intrusive_fwd_ptr& operator=(pointer ptr) { template<typename TimePoint>
reset(ptr); mailbox_element* try_pop(const TimePoint& abs_time) {
return *this; return (timed_wait_for_data(abs_time)) ? try_pop() : nullptr;
} }
intrusive_fwd_ptr& operator=(intrusive_fwd_ptr&& other) { bool push_back(mailbox_element* new_element) {
swap(other); 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=(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 {
......
This diff is collapsed.
...@@ -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
...@@ -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.
*/ */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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