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
src/ipv4_io_stream.cpp
src/local_actor.cpp
src/logging.cpp
src/mailbox_element.cpp
src/match.cpp
src/memory.cpp
src/memory_managed.cpp
......@@ -137,8 +138,6 @@ set(LIBCPPA_SRC
src/primitive_variant.cpp
src/process_information.cpp
src/protocol.cpp
src/receive.cpp
src/recursive_queue_node.cpp
src/ref_counted.cpp
src/response_handle.cpp
src/ripemd_160.cpp
......
......@@ -24,7 +24,6 @@ cppa/detail/atom_val.hpp
cppa/detail/behavior_impl.hpp
cppa/detail/behavior_stack.hpp
cppa/detail/boxed.hpp
cppa/detail/channel.hpp
cppa/detail/container_tuple_view.hpp
cppa/detail/decorated_names_map.hpp
cppa/detail/decorated_tuple.hpp
......@@ -48,7 +47,8 @@ cppa/detail/pseudo_tuple.hpp
cppa/detail/ptype_to_type.hpp
cppa/detail/receive_loop_helper.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/serialize_tuple.hpp
cppa/detail/singleton_manager.hpp
......@@ -68,7 +68,6 @@ cppa/detail/unboxed.hpp
cppa/detail/uniform_type_info_map.hpp
cppa/detail/value_guard.hpp
cppa/detail/yield_interface.hpp
cppa/either.hpp
cppa/enable_weak_ptr.hpp
cppa/event_based_actor.hpp
cppa/exception.hpp
......@@ -80,7 +79,6 @@ cppa/group.hpp
cppa/guard_expr.hpp
cppa/intrusive/blocking_single_reader_queue.hpp
cppa/intrusive/single_reader_queue.hpp
cppa/intrusive_fwd_ptr.hpp
cppa/intrusive_ptr.hpp
cppa/local_actor.hpp
cppa/logging.hpp
......@@ -145,7 +143,6 @@ cppa/util/duration.hpp
cppa/util/element_at.hpp
cppa/util/fiber.hpp
cppa/util/fixed_vector.hpp
cppa/util/if_else.hpp
cppa/util/int_list.hpp
cppa/util/is_array_of.hpp
cppa/util/is_builtin.hpp
......@@ -168,7 +165,6 @@ cppa/util/rm_ref.hpp
cppa/util/scope_guard.hpp
cppa/util/shared_lock_guard.hpp
cppa/util/shared_spinlock.hpp
cppa/util/static_foreach.hpp
cppa/util/tbind.hpp
cppa/util/type_list.hpp
cppa/util/type_pair.hpp
......@@ -244,8 +240,7 @@ src/partial_function.cpp
src/primitive_variant.cpp
src/process_information.cpp
src/protocol.cpp
src/receive.cpp
src/recursive_queue_node.cpp
src/mailbox_element.cpp
src/ref_counted.cpp
src/response_handle.cpp
src/ripemd_160.cpp
......@@ -302,3 +297,8 @@ cppa/extend.hpp
cppa/detail/sync_request_bouncer.hpp
cppa/memory_cached.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 {
* @pre <tt>id.valid()</tt>
*/
virtual void sync_enqueue(const actor_ptr& sender,
message_id_t id,
message_id id,
any_tuple msg) = 0;
/**
......@@ -96,7 +96,7 @@ class actor : public channel {
* its state to @p pending in response to the enqueue operation.
*/
virtual bool chained_sync_enqueue(const actor_ptr& sender,
message_id_t id,
message_id id,
any_tuple msg);
/**
......@@ -110,7 +110,7 @@ class actor : public channel {
* otherwise (actor already exited) @p false.
* @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
......@@ -129,7 +129,7 @@ class actor : public channel {
/**
* @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.
......
......@@ -59,10 +59,10 @@ class actor_companion_mixin : public Base {
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>
actor_companion_mixin(Args&&... args) : super(std::forward<Args>(args)...) {
template<typename... Ts>
actor_companion_mixin(Ts&&... args) : super(std::forward<Ts>(args)...) {
m_self.reset(detail::memory::create<companion>(this));
}
......@@ -89,9 +89,9 @@ class actor_companion_mixin : public Base {
* @note While the message handler is invoked, @p self will point
* to the companion object to enable send() and reply().
*/
template<typename... Args>
void set_message_handler(Args&&... matchExpressions) {
m_message_handler = match_expr_convert(std::forward<Args>(matchExpressions)...);
template<typename... Ts>
void set_message_handler(Ts&&... args) {
m_message_handler = match_expr_convert(std::forward<Ts>(args)...);
}
/**
......@@ -112,8 +112,8 @@ class actor_companion_mixin : public Base {
class companion : public local_actor {
friend class actor_companion_mixin;
typedef util::shared_spinlock lock_type;
typedef std::unique_ptr<detail::recursive_queue_node,detail::disposer> node_ptr;
public:
......@@ -129,37 +129,33 @@ class actor_companion_mixin : public Base {
void enqueue(const actor_ptr& sender, any_tuple msg) {
util::shared_lock_guard<lock_type> guard(m_lock);
if (m_parent) {
m_parent->new_message(new_node_ptr(sender, std::move(msg)));
}
if (m_parent) push_message(sender, std::move(msg));
}
void sync_enqueue(const actor_ptr& sender,
message_id_t id,
message_id id,
any_tuple msg) {
util::shared_lock_guard<lock_type> guard(m_lock);
if (m_parent) {
m_parent->new_message(new_node_ptr(sender, std::move(msg), id));
}
if (m_parent) push_message(sender, std::move(msg), id);
}
bool initialized() const { return true; }
void quit(std::uint32_t) {
throw std::runtime_error("ActorWidgetMixin::Gateway::exit "
"is forbidden, use Qt's widget "
"management instead!");
throw std::runtime_error("Using actor_companion_mixin::quit "
"is prohibited; use Qt's widget "
"management instead.");
}
void dequeue(behavior&) { throw_no_recv(); }
void dequeue(partial_function&) { throw_no_recv(); }
void dequeue(behavior&) {
throw_no_recv();
}
void dequeue_response(behavior&, message_id_t) {
void dequeue_response(behavior&, message_id) {
throw_no_recv();
}
void become_waiting_for(behavior&&, message_id_t) {
void become_waiting_for(behavior, message_id) {
throw_no_become();
}
......@@ -169,9 +165,11 @@ class actor_companion_mixin : public Base {
private:
template<typename... Args>
node_ptr new_node_ptr(Args&&... args) {
return node_ptr(detail::memory::create<detail::recursive_queue_node>(std::forward<Args>(args)...));
template<typename... Ts>
void push_message(Ts&&... 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() {
......@@ -186,12 +184,18 @@ class actor_companion_mixin : public Base {
"receive() API");
}
// guards access to m_parent
lock_type m_lock;
// set to nullptr if this companion became detached
actor_companion_mixin* m_parent;
};
// used as 'self' before calling message handler
intrusive_ptr<companion> m_self;
// user-defined message handler for incoming messages
partial_function m_message_handler;
};
......
......@@ -46,7 +46,7 @@ class actor_proxy_cache;
* @brief Represents a remote 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;
......
......@@ -108,9 +108,9 @@ bool announce(const std::type_info& tinfo, uniform_type_info* utype);
* @see {@link announce_4.cpp announce example 4}
* @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>*>
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...)};
}
......@@ -123,9 +123,9 @@ compound_member(C Parent::*c_ptr, const Args&... args) {
* @see {@link announce_4.cpp announce example 4}
* @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>*>
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...)};
}
......@@ -140,12 +140,12 @@ compound_member(C& (Parent::*getter)(), const Args&... args) {
* @returns A pair of @p c_ptr and the created meta informations.
*/
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)>,
util::abstract_uniform_type_info<typename util::rm_ref<GRes>::type>*>
compound_member(const std::pair<GRes (Parent::*)() const,
SRes (Parent::*)(SArg) >& gspair,
const Args&... args) {
const Ts&... args) {
typedef typename util::rm_ref<GRes>::type mtype;
return {gspair, new detail::default_uniform_type_info_impl<mtype>(args...)};
}
......@@ -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,
* @c false otherwise.
*/
template<typename T, typename... Args>
inline bool announce(const Args&... args) {
return announce(typeid(T),
new detail::default_uniform_type_info_impl<T>(args...));
template<typename T, typename... Ts>
inline bool announce(const Ts&... args) {
return announce(typeid(T), new detail::default_uniform_type_info_impl<T>(args...));
}
/**
......
......@@ -74,14 +74,14 @@ class any_tuple {
/**
* @brief Creates a tuple from @p t.
*/
template<typename... Args>
any_tuple(const cow_tuple<Args...>& t) : m_vals(t.vals()) { }
template<typename... Ts>
any_tuple(const cow_tuple<Ts...>& arg) : m_vals(arg.vals()) { }
/**
* @brief Creates a tuple and moves the content from @p t.
*/
template<typename... Args>
any_tuple(cow_tuple<Args...>&& t) : m_vals(std::move(t.m_vals)) { }
template<typename... Ts>
any_tuple(cow_tuple<Ts...>&& arg) : m_vals(std::move(arg.m_vals)) { }
/**
* @brief Move constructor.
......@@ -181,10 +181,13 @@ class any_tuple {
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;
/** @cond PRIVATE */
template<typename T>
static inline any_tuple view(T&& value);
......@@ -194,6 +197,8 @@ class any_tuple {
explicit any_tuple(detail::abstract_tuple*);
/** @endcond */
private:
data_ptr m_vals;
......@@ -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.
* @param args Values to initialize the tuple elements.
*/
template<typename... Args>
inline any_tuple make_any_tuple(Args&&... args) {
return make_cow_tuple(std::forward<Args>(args)...);
template<typename... Ts>
inline any_tuple make_any_tuple(Ts&&... args) {
return make_cow_tuple(std::forward<Ts>(args)...);
}
/******************************************************************************
......
......@@ -40,7 +40,11 @@ namespace cppa {
/**
* @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.
......
......@@ -39,7 +39,6 @@
#include "cppa/util/tbind.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/util/type_list.hpp"
......@@ -56,10 +55,18 @@ class behavior {
public:
/** @cond PRIVATE */
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;
/** @endcond */
behavior() = default;
behavior(behavior&&) = default;
behavior(const behavior&) = default;
......@@ -68,49 +75,39 @@ class behavior {
behavior(const partial_function& fun);
inline behavior(impl_ptr ptr) : m_impl(std::move(ptr)) { }
template<typename F>
behavior(const timeout_definition<F>& arg)
: m_impl(detail::new_default_behavior_impl(detail::dummy_match_expr{},
arg.timeout,
arg.handler) ) { }
behavior(const timeout_definition<F>& arg);
template<typename 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(), []() { })) { }
behavior(util::duration d, F f);
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...)) { }
template<typename... Cases, typename... Ts>
behavior(const match_expr<Cases...>& arg, const Ts&... args);
inline void handle_timeout() {
m_impl->handle_timeout();
}
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>
inline bool operator()(T&& arg) {
return (m_impl) && m_impl->invoke(std::forward<T>(arg));
}
inline bool operator()(T&& arg);
/**
* @brief Adds a continuation to this behavior that is executed
* whenever this behavior was successfully applied to
* a message.
*/
template<typename F>
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; }
inline behavior add_continuation(F fun);
private:
......@@ -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) {
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
#endif // CPPA_BEHAVIOR_HPP
......@@ -67,12 +67,6 @@ class channel : public ref_counted {
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;
/**
* @brief Convenience alias.
*/
template<typename T>
using enable_if_channel = std::enable_if<std::is_base_of<channel,T>::value>;
template<typename T, typename R = void>
using enable_if_channel = std::enable_if<std::is_base_of<channel,T>::value,R>;
} // namespace cppa
......
......@@ -34,7 +34,6 @@
#include <stack>
#include "cppa/config.hpp"
#include "cppa/either.hpp"
#include "cppa/extend.hpp"
#include "cppa/stacked.hpp"
#include "cppa/scheduled_actor.hpp"
......@@ -64,22 +63,22 @@ class context_switching_actor : public extend<scheduled_actor,context_switching_
*/
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();
protected:
typedef std::chrono::high_resolution_clock::time_point timeout_type;
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:
detail::recursive_queue_node* receive_node();
// required by util::fiber
static void trampoline(void* _this);
......
......@@ -86,6 +86,7 @@ class cow_tuple<Head, Tail...> {
public:
typedef util::type_list<Head, Tail...> types;
typedef cow_ptr<detail::abstract_tuple> cow_ptr_type;
static constexpr size_t num_elements = sizeof...(Tail) + 1;
......@@ -96,33 +97,24 @@ class cow_tuple<Head, Tail...> {
* @brief Initializes the cow_tuple with @p args.
* @param args Initialization values.
*/
template<typename... Args>
cow_tuple(const Head& arg0, Args&&... args)
: m_vals(new data_type(arg0, std::forward<Args>(args)...)) { }
template<typename... Ts>
cow_tuple(const Head& arg, Ts&&... args)
: m_vals(new data_type(arg, std::forward<Ts>(args)...)) { }
/**
* @brief Initializes the cow_tuple with @p args.
* @param args Initialization values.
*/
template<typename... Args>
cow_tuple(Head&& arg0, Args&&... args)
: m_vals(new data_type(std::move(arg0), std::forward<Args>(args)...)) { }
template<typename... Ts>
cow_tuple(Head&& arg, Ts&&... args)
: m_vals(new data_type(std::move(arg), std::forward<Ts>(args)...)) { }
cow_tuple(cow_tuple&&) = default;
cow_tuple(const cow_tuple&) = default;
cow_tuple& operator=(cow_tuple&&) = default;
cow_tuple& operator=(const cow_tuple&) = default;
inline static cow_tuple from(cow_ptr_type ptr) {
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) {
static cow_tuple offset_subtuple(cow_ptr_type ptr, size_t offset) {
CPPA_REQUIRE(offset > 0);
return {priv_ctor{}, decorated_type::create(std::move(ptr), offset)};
}
......@@ -156,10 +148,23 @@ class cow_tuple<Head, Tail...> {
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 {
return m_vals;
}
/** @endcond */
};
template<typename TypeList>
......@@ -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.
* @relates cow_tuple
*/
template<typename... Args>
cow_tuple<typename detail::strip_and_convert<Args>::type...>
make_cow_tuple(Args&&... args) {
return {std::forward<Args>(args)...};
template<typename... Ts>
cow_tuple<typename detail::strip_and_convert<Ts>::type...>
make_cow_tuple(Ts&&... args) {
return {std::forward<Ts>(args)...};
}
/**
......
......@@ -48,6 +48,7 @@
#include "cppa/behavior.hpp"
#include "cppa/announce.hpp"
#include "cppa/sb_actor.hpp"
#include "cppa/threaded.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/to_string.hpp"
#include "cppa/any_tuple.hpp"
......@@ -191,11 +192,20 @@
*
* @defgroup MessageHandling Message handling.
*
* This is the beating heart of @p libcppa. Actor programming is all about
* message handling.
* @brief This is the beating heart of @p libcppa. Actor programming is
* all about message handling.
*
* 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
*
......@@ -414,15 +424,14 @@ namespace cppa {
namespace detail {
template<typename T>
inline void send_impl(T* whom, any_tuple&& what) {
if (whom) self->send_message(whom, std::move(what));
inline void send_impl(T* ptr, any_tuple&& arg) {
if (ptr) self->send_message(ptr, std::move(arg));
}
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");
if (whom) self->send_message(whom,
make_any_tuple(std::forward<Ts>(what)...));
if (ptr) self->send_message(ptr, make_any_tuple(std::forward<Ts>(args)...));
}
} // namespace detail
......@@ -438,7 +447,7 @@ inline void send_tpl_impl(T* whom, Ts&&... what) {
* @param what Message content as tuple.
*/
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) {
detail::send_impl(whom.get(), std::move(what));
}
......@@ -450,9 +459,9 @@ send_tuple(const intrusive_ptr<C>& whom, any_tuple what) {
* @pre <tt>sizeof...(Ts) > 0</tt>
*/
template<class C, typename... Ts>
inline typename std::enable_if<std::is_base_of<channel, C>::value>::type
send(const intrusive_ptr<C>& whom, Ts&&... what) {
detail::send_tpl_impl(whom.get(), std::forward<Ts>(what)...);
inline typename enable_if_channel<C>::type
send(const intrusive_ptr<C>& whom, Ts&&... args) {
detail::send_tpl_impl(whom.get(), std::forward<Ts>(args)...);
}
/**
......@@ -464,7 +473,7 @@ send(const intrusive_ptr<C>& whom, Ts&&... what) {
* @pre <tt>sizeof...(Ts) > 0</tt>
*/
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) {
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
* @pre <tt>sizeof...(Ts) > 0</tt>
*/
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_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) {
* @returns @p whom.
*/
template<class C>
inline typename std::enable_if<std::is_base_of<channel, C>::value,
const intrusive_ptr<C>& >::type
inline typename enable_if_channel<C,const intrusive_ptr<C>&>::type
operator<<(const intrusive_ptr<C>& whom, any_tuple what) {
send_tuple(whom, std::move(what));
return whom;
......@@ -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)...));
}
/** @} */
/**
* @}
*/
// 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));
}
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)...);
}
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;
}
inline actor_ptr eval_sopts(spawn_options opts, actor_ptr ptr) {
......@@ -732,7 +742,14 @@ actor_ptr spawn(Ts&&... args) {
*/
template<class Impl, spawn_options Options = no_spawn_options, typename... Ts>
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));
}
......@@ -844,15 +861,24 @@ void shutdown(); // note: implemented in singleton_manager.cpp
*/
inline void quit_actor(const actor_ptr& whom, std::uint32_t reason) {
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>
inline void become(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 {
......@@ -883,9 +909,11 @@ inline const actor_ostream& operator<<(const actor_ostream& o, const any_tuple&
}
template<typename T>
inline typename std::enable_if< !std::is_convertible<T,std::string>::value
inline typename std::enable_if<
!std::is_convertible<T,std::string>::value
&& !std::is_convertible<T,any_tuple>::value,
const actor_ostream&>::type
const actor_ostream&
>::type
operator<<(const actor_ostream& o, T&& arg) {
return o.write(std::to_string(std::forward<T>(arg)));
}
......
......@@ -40,7 +40,7 @@
#include "cppa/config.hpp"
#include "cppa/behavior.hpp"
#include "cppa/message_id.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/mailbox_element.hpp"
namespace cppa { namespace detail {
......@@ -54,14 +54,14 @@ class behavior_stack
behavior_stack(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:
behavior_stack() = default;
// @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
void pop_async_back();
......@@ -69,7 +69,7 @@ class behavior_stack
void clear();
// 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; });
}
......@@ -81,7 +81,7 @@ class behavior_stack
}
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);
}
......@@ -90,7 +90,7 @@ class behavior_stack
}
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(client != nullptr);
CPPA_REQUIRE(node != nullptr);
......@@ -122,7 +122,7 @@ class behavior_stack
template<class Policy, class Client>
void exec(Policy& policy, Client* client) {
while (!empty()) {
invoke(policy, client, client->await_message());
invoke(policy, client, policy.fetch_message(client));
cleanup();
}
}
......
......@@ -434,44 +434,44 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
// terminates recursion
inline void push_back() { }
template<typename R, class C, typename... Args>
void push_back(R C::* memptr, Args&&... args) {
template<typename R, class C, typename... Ts>
void push_back(R C::* memptr, Ts&&... args) {
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.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,
Args&&... args) {
Ts&&... args) {
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.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,
Args&&... args) {
Ts&&... args) {
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.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,
Args&&... args) {
Ts&&... args) {
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:
template<typename... Args>
default_uniform_type_info_impl(Args&&... args) {
push_back(std::forward<Args>(args)...);
template<typename... Ts>
default_uniform_type_info_impl(Ts&&... args) {
push_back(std::forward<Ts>(args)...);
}
default_uniform_type_info_impl() {
......
......@@ -59,8 +59,8 @@ class empty_tuple : public singleton_mixin<empty_tuple,abstract_tuple> {
empty_tuple();
inline void initialize() /*override*/ { ref(); }
inline void destroy() /*override*/ { deref(); }
inline void initialize() { ref(); }
inline void destroy() { deref(); }
};
......
......@@ -47,10 +47,10 @@ class event_based_actor_impl : public event_based_actor {
public:
template<typename... Args>
event_based_actor_impl(InitFun fun, CleanupFun cfun, Args&&... args)
template<typename... Ts>
event_based_actor_impl(InitFun fun, CleanupFun cfun, Ts&&... args)
: 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); }
......@@ -71,9 +71,9 @@ class event_based_actor_impl : public event_based_actor {
f(args...);
}
template<typename F, typename... Args>
void apply(F& f, Args... args) {
apply(f, args..., &get_ref<sizeof...(Args)>(m_members));
template<typename F, typename... Ts>
void apply(F& f, Ts... args) {
apply(f, args..., &get_ref<sizeof...(Ts)>(m_members));
}
typedef std::integral_constant<size_t, 0> zero_t;
......@@ -102,11 +102,9 @@ class event_based_actor_factory {
event_based_actor_factory(InitFun fun, CleanupFun cfun)
: m_init(std::move(fun)), m_on_exit(std::move(cfun)) { }
template<typename... Args>
actor_ptr spawn(Args&&... args) {
auto ptr = memory::create<impl>(m_init,
m_on_exit,
std::forward<Args>(args)...);
template<typename... Ts>
actor_ptr spawn(Ts&&... args) {
auto ptr = memory::create<impl>(m_init, m_on_exit, std::forward<Ts>(args)...);
return get_scheduler()->exec(no_spawn_options, ptr);
}
......
......@@ -43,7 +43,7 @@
namespace cppa { namespace detail {
// 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 {
F m_fun;
......@@ -56,15 +56,15 @@ class ftor_behavior : public scheduled_actor {
};
template<typename F, typename... Args>
class ftor_behavior<true, true, F, Args...> : public scheduled_actor {
template<typename F, typename... Ts>
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;
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
tdata_type;
......@@ -72,7 +72,7 @@ class ftor_behavior<true, true, F, Args...> : public scheduled_actor {
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() {
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 {
};
template<typename F, typename... Args>
class ftor_behavior<false, true, F, Args...> : public scheduled_actor {
template<typename F, typename... Ts>
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;
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
tdata_type;
......@@ -111,10 +111,10 @@ class ftor_behavior<false, true, F, Args...> : public scheduled_actor {
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...) {
}
......@@ -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));
}
template<typename F, typename Arg0, typename... Args>
scheduled_actor* get_behavior(std::integral_constant<bool,true>,
F fptr,
const Arg0& arg0,
const Args&... args) {
static_assert(std::is_convertible<decltype(fptr(arg0, args...)), scheduled_actor*>::value == false,
template<typename F, typename T, typename... Ts>
scheduled_actor* get_behavior(std::true_type, F fptr, const T& arg, const Ts&... args) {
static_assert(std::is_convertible<decltype(fptr(arg, args...)), scheduled_actor*>::value == false,
"Spawning a function returning an actor_behavior? "
"Are you sure that you do not want to spawn the behavior "
"returned by that function?");
typedef ftor_behavior<true, true, F, Arg0, Args...> impl;
return new impl(fptr, arg0, args...);
typedef ftor_behavior<true, true, F, T, Ts...> impl;
return new impl(fptr, arg, args...);
}
template<typename F, typename Arg0, typename... Args>
scheduled_actor* get_behavior(std::integral_constant<bool,false>,
F ftor,
const Arg0& arg0,
const Args&... args) {
static_assert(std::is_convertible<decltype(ftor(arg0, args...)), scheduled_actor*>::value == false,
template<typename F, typename T, typename... Ts>
scheduled_actor* get_behavior(std::false_type, F ftor, const T& arg, const Ts&... args) {
static_assert(std::is_convertible<decltype(ftor(arg, args...)), scheduled_actor*>::value == false,
"Spawning a functor returning an actor_behavior? "
"Are you sure that you do not want to spawn the behavior "
"returned by that functor?");
typedef typename util::rm_ref<F>::type ftype;
typedef ftor_behavior<false, true, ftype, Arg0, Args...> impl;
return new impl(std::forward<F>(ftor), arg0, args...);
typedef ftor_behavior<false, true, ftype, T, Ts...> impl;
return new impl(std::forward<F>(ftor), arg, args...);
}
} } // namespace cppa::detail
......
......@@ -33,6 +33,7 @@
#include <new>
#include <vector>
#include <memory>
#include <utility>
#include <typeinfo>
#include <iostream>
......@@ -40,6 +41,8 @@
#include "cppa/config.hpp"
#include "cppa/ref_counted.hpp"
namespace cppa { class mailbox_element; }
namespace cppa { namespace detail {
namespace {
......@@ -49,8 +52,6 @@ constexpr size_t s_cache_size = 10240; // cache about 10kb per thread
} // namespace <anonymous>
class recursive_queue_node;
class instance_wrapper {
public:
......@@ -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 {
memory() = delete;
......@@ -171,11 +178,11 @@ class memory {
* @brief Allocates storage, initializes a new object, and returns
* the new instance.
*/
template<typename T, typename... Args>
static inline T* create(Args&&... args) {
template<typename T, typename... Ts>
static T* create(Ts&&... args) {
auto mc = get_or_set_cache_map_entry<T>();
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;
return result;
}
......@@ -198,12 +205,6 @@ class memory {
};
struct disposer {
inline void operator()(memory_managed* ptr) const {
ptr->request_deletion();
}
};
} } // namespace cppa::detail
#endif // CPPA_MEMORY_HPP
......@@ -39,6 +39,7 @@
#include "cppa/util/type_list.hpp"
#include "cppa/util/apply_args.hpp"
#include "cppa/util/left_or_right.hpp"
#include "cppa/util/get_result_type.hpp"
#include "cppa/detail/tdata.hpp"
......@@ -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)...);
}
template<typename ProjectionFuns, typename... Args>
template<typename ProjectionFuns, typename... Ts>
struct collected_args_tuple {
typedef typename tdata_from_type_list<
typename util::tl_zip<
......@@ -59,7 +60,7 @@ struct collected_args_tuple {
util::rm_option
>::type,
typename util::tl_map<
util::type_list<Args...>,
util::type_list<Ts...>,
mutable_gref_wrapped
>::type,
util::left_or_right
......@@ -71,7 +72,7 @@ struct collected_args_tuple {
/**
* @brief Projection implemented by a set of functors.
*/
template<class ProjectionFuns, typename... Args>
template<class ProjectionFuns, typename... Ts>
class projection {
public:
......@@ -90,10 +91,10 @@ class projection {
* @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
* the result of @p fun in @p result.
*/
template<class PartialFun>
bool invoke(PartialFun& fun, typename PartialFun::result_type& result, Args... args) const {
typename collected_args_tuple<ProjectionFuns,Args...>::type pargs;
if (collect(pargs, m_funs, std::forward<Args>(args)...)) {
template<class PartFun>
bool invoke(PartFun& fun, typename PartFun::result_type& result, Ts... args) const {
typename collected_args_tuple<ProjectionFuns,Ts...>::type pargs;
if (collect(pargs, m_funs, std::forward<Ts>(args)...)) {
auto indices = util::get_indices(pargs);
if (is_defined_at(fun, pargs, indices)) {
result = util::apply_args(fun, pargs, indices);
......@@ -106,11 +107,11 @@ class projection {
/**
* @brief Invokes @p fun with a projection of <tt>args...</tt>.
*/
template<class PartialFun>
bool operator()(PartialFun& fun, Args... args) const {
typename collected_args_tuple<ProjectionFuns,Args...>::type pargs;
template<class PartFun>
bool operator()(PartFun& fun, Ts... args) const {
typename collected_args_tuple<ProjectionFuns,Ts...>::type 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)) {
util::apply_args(fun, pargs, indices);
return true;
......@@ -123,13 +124,13 @@ class projection {
* @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
* the result of @p fun in @p result.
*/
template<class PartialFun>
inline bool operator()(PartialFun& fun, typename PartialFun::result_type& result, Args... args) const {
template<class PartFun>
inline bool operator()(PartFun& fun, typename PartFun::result_type& result, Ts... args) const {
return invoke(fun, result, args...);
}
template<class PartialFun>
inline bool operator()(PartialFun& fun, const util::void_type&, Args... args) const {
template<class PartFun>
inline bool operator()(PartFun& fun, const util::void_type&, Ts... args) const {
return (*this)(fun, args...);
}
......@@ -166,11 +167,11 @@ class projection {
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,
T0&& arg0, Ts&&... args) {
return store(td.head, fetch(tr.head, std::forward<T0>(arg0)))
&& collect(td.tail(), tr.tail(), std::forward<Ts>(args)...);
U&& arg, Us&&... args) {
return store(td.head, fetch(tr.head, std::forward<U>(arg)))
&& collect(td.tail(), tr.tail(), std::forward<Us>(args)...);
}
fun_container m_funs;
......@@ -186,8 +187,8 @@ class projection<util::empty_type_list> {
projection(const tdata<>&) { }
projection(const projection&) = default;
template<class PartialFun>
bool operator()(PartialFun& fun) const {
template<class PartFun>
bool operator()(PartFun& fun) const {
if (fun.defined_at()) {
fun();
return true;
......@@ -195,8 +196,8 @@ class projection<util::empty_type_list> {
return false;
}
template<class PartialFun>
bool operator()(PartialFun& fun, const util::void_type&) const {
template<class PartFun>
bool operator()(PartFun& fun, const util::void_type&) const {
if (fun.defined_at()) {
fun();
return true;
......@@ -204,8 +205,8 @@ class projection<util::empty_type_list> {
return false;
}
template<class PartialFun>
bool operator()(PartialFun& fun, typename PartialFun::result_type& res) const {
template<class PartFun>
bool operator()(PartFun& fun, typename PartFun::result_type& res) const {
if (fun.defined_at()) {
res = fun();
return true;
......@@ -218,9 +219,9 @@ class projection<util::empty_type_list> {
template<class ProjectionFuns, class List>
struct projection_from_type_list;
template<class ProjectionFuns, typename... Args>
struct projection_from_type_list<ProjectionFuns, util::type_list<Args...> > {
typedef projection<ProjectionFuns, Args...> type;
template<class ProjectionFuns, typename... Ts>
struct projection_from_type_list<ProjectionFuns, util::type_list<Ts...> > {
typedef projection<ProjectionFuns, Ts...> type;
};
} } // namespace cppa::detail
......
......@@ -35,35 +35,33 @@
#include "cppa/primitive_type.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/wrapped.hpp"
namespace cppa { namespace detail {
// maps the primitive_type PT to the corresponding type
template<primitive_type PT>
struct ptype_to_type :
// signed integers
util::if_else_c<PT == pt_int8, std::int8_t,
util::if_else_c<PT == pt_int16, std::int16_t,
util::if_else_c<PT == pt_int32, std::int32_t,
util::if_else_c<PT == pt_int64, std::int64_t,
util::if_else_c<PT == pt_uint8, std::uint8_t,
// unsigned integers
util::if_else_c<PT == pt_uint16, std::uint16_t,
util::if_else_c<PT == pt_uint32, std::uint32_t,
util::if_else_c<PT == pt_uint64, std::uint64_t,
// floating points
util::if_else_c<PT == pt_float, float,
util::if_else_c<PT == pt_double, double,
util::if_else_c<PT == pt_long_double, long double,
// strings
util::if_else_c<PT == pt_u8string, std::string,
util::if_else_c<PT == pt_u16string, std::u16string,
util::if_else_c<PT == pt_u32string, std::u32string,
// default case
void > > > > > > > > > > > > > > {
};
struct ptype_to_type : util::wrapped<void> { };
// integer types
template<> struct ptype_to_type<pt_int8 > : util::wrapped<std::int8_t > { };
template<> struct ptype_to_type<pt_uint8 > : util::wrapped<std::uint8_t > { };
template<> struct ptype_to_type<pt_int16 > : util::wrapped<std::int16_t > { };
template<> struct ptype_to_type<pt_uint16> : util::wrapped<std::uint16_t> { };
template<> struct ptype_to_type<pt_int32 > : util::wrapped<std::int32_t > { };
template<> struct ptype_to_type<pt_uint32> : util::wrapped<std::uint32_t> { };
template<> struct ptype_to_type<pt_int64 > : util::wrapped<std::int64_t > { };
template<> struct ptype_to_type<pt_uint64> : util::wrapped<std::uint64_t> { };
// floating points
template<> struct ptype_to_type<pt_float> : util::wrapped<float> { };
template<> struct ptype_to_type<pt_double> : util::wrapped<double> { };
template<> struct ptype_to_type<pt_long_double> : util::wrapped<long double> { };
// strings
template<> struct ptype_to_type<pt_u8string > : util::wrapped<std::string > { };
template<> struct ptype_to_type<pt_u16string> : util::wrapped<std::u16string> { };
template<> struct ptype_to_type<pt_u32string> : util::wrapped<std::u32string> { };
} } // namespace cppa::detail
......
......@@ -51,24 +51,15 @@ struct receive_while_helper {
template<typename S>
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;
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>
......@@ -81,21 +72,11 @@ class receive_for_helper {
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;
for ( ; begin != end; ++begin) sptr->dequeue(bhvr);
}
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);
for ( ; begin != end; ++begin) sptr->dequeue(tmp);
}
};
......@@ -106,10 +87,7 @@ class do_receive_helper {
public:
template<typename... Args>
do_receive_helper(Args&&... args)
: m_bhvr(match_expr_convert(std::forward<Args>(args)...)) {
}
inline do_receive_helper(behavior&& bhvr) : m_bhvr(std::move(bhvr)) { }
do_receive_helper(do_receive_helper&&) = default;
......
......@@ -41,10 +41,10 @@
#include "cppa/to_string.hpp"
#include "cppa/message_id.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/detail/memory.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
namespace cppa { namespace detail {
......@@ -62,8 +62,8 @@ class receive_policy {
public:
typedef recursive_queue_node* pointer;
typedef std::unique_ptr<recursive_queue_node,disposer> smart_pointer;
typedef mailbox_element* pointer;
typedef std::unique_ptr<mailbox_element,disposer> smart_pointer;
enum handle_message_result {
hm_timeout_msg,
......@@ -76,7 +76,7 @@ class receive_policy {
template<class Client, class Fun>
bool invoke_from_cache(Client* client,
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;
auto i = m_cache.begin();
auto e = m_cache.end();
......@@ -108,7 +108,7 @@ class receive_policy {
bool invoke(Client* client,
pointer node_ptr,
Fun& fun,
message_id_t awaited_response = message_id_t()) {
message_id awaited_response = message_id()) {
smart_pointer node(node_ptr);
std::integral_constant<receive_policy_flag,Client::receive_flag> policy;
switch (this->handle_message(client, node.get(), fun,
......@@ -176,7 +176,7 @@ class receive_policy {
}
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());
if (!invoke_from_cache(client, bhvr, mid)) {
if (bhvr.timeout().valid()) {
......@@ -195,12 +195,17 @@ class receive_policy {
}
}
template<class Client>
mailbox_element* fetch_message(Client* client) {
return client->await_message();
}
private:
typedef typename rp_flag<rp_nestable>::type nestable;
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>
inline void handle_timeout(Client* client, behavior& bhvr) {
......@@ -231,7 +236,7 @@ class receive_policy {
template<class Client>
filter_result filter_msg(Client* client, pointer node) {
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;
if ( msg.size() == 2
&& msg.type_at(0) == arr[0]
......@@ -239,7 +244,7 @@ class receive_policy {
auto v0 = msg.get_as<atom_value>(0);
auto v1 = msg.get_as<std::uint32_t>(1);
if (v0 == atom("EXIT")) {
CPPA_REQUIRE(!message_id.valid());
CPPA_REQUIRE(!mid.valid());
if (client->m_trap_exit == false) {
if (v1 != exit_reason::normal) {
client->quit(v1);
......@@ -249,7 +254,7 @@ class receive_policy {
}
}
else if (v0 == atom("SYNC_TOUT")) {
CPPA_REQUIRE(!message_id.valid());
CPPA_REQUIRE(!mid.valid());
return client->waits_for_timeout(v1) ? timeout_message
: expired_timeout_message;
}
......@@ -257,11 +262,11 @@ class receive_policy {
else if ( msg.size() == 1
&& msg.type_at(0) == arr[0]
&& msg.get_as<atom_value>(0) == atom("TIMEOUT")
&& message_id.is_response()) {
&& mid.is_response()) {
return timeout_response_message;
}
if (message_id.is_response()) {
return (client->awaits(message_id)) ? sync_response
if (mid.is_response()) {
return (client->awaits(mid)) ? sync_response
: expired_sync_response;
}
return ordinary_message;
......@@ -340,7 +345,7 @@ class receive_policy {
handle_message_result handle_message(Client* client,
pointer node,
Fun& fun,
message_id_t awaited_response,
message_id awaited_response,
Policy policy ) {
bool handle_sync_failure_on_mismatch = true;
if (hm_should_skip(node, policy)) {
......
......@@ -38,14 +38,13 @@ namespace cppa { namespace detail {
struct scheduled_actor_dummy : scheduled_actor {
scheduled_actor_dummy();
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&);
void quit(std::uint32_t);
void dequeue(behavior&);
void dequeue(partial_function&);
void dequeue_response(behavior&, message_id_t);
void dequeue_response(behavior&, message_id);
void do_become(behavior&&, bool);
void become_waiting_for(behavior&&, message_id_t);
void become_waiting_for(behavior, message_id);
bool has_behavior();
scheduled_actor_type impl_type();
};
......
......@@ -50,8 +50,8 @@ class singleton_mixin : public Base {
protected:
template<typename... Args>
singleton_mixin(Args&&... args) : Base(std::forward<Args>(args)...) { }
template<typename... Ts>
singleton_mixin(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
virtual ~singleton_mixin() { }
......
......@@ -37,7 +37,7 @@
#include "cppa/any_tuple.hpp"
#include "cppa/message_id.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/mailbox_element.hpp"
namespace cppa { namespace detail {
......@@ -45,7 +45,7 @@ struct sync_request_bouncer {
std::uint32_t rsn;
constexpr sync_request_bouncer(std::uint32_t 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);
if (mid.is_request() && sender != nullptr) {
actor_ptr nobody;
......@@ -54,7 +54,7 @@ struct sync_request_bouncer {
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);
}
};
......
......@@ -42,6 +42,7 @@
#include "cppa/util/wrapped.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/arg_match_t.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/boxed.hpp"
#include "cppa/detail/types_array.hpp"
......@@ -113,6 +114,11 @@ struct unbox_ref<std::reference_wrapper<T> > {
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
*/
......@@ -136,9 +142,9 @@ struct tdata<> {
constexpr tdata() { }
// swallow any number of additional boxed or void_type arguments silently
template<typename... Args>
tdata(Args&&...) {
typedef util::type_list<typename util::rm_ref<Args>::type...> incoming;
template<typename... Ts>
tdata(Ts&&...) {
typedef util::type_list<typename util::rm_ref<Ts>::type...> incoming;
typedef typename util::tl_filter_not_type<incoming, tdata>::type iargs;
static_assert(util::tl_forall<iargs, boxed_or_void>::value,
"Additional unboxed arguments provided");
......@@ -239,9 +245,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
typedef Head head_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,
util::wrapped<Head>
Head
>::type
back_type;
......@@ -252,10 +259,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
tdata(const Head& arg) : super(), head(arg) { }
tdata(Head&& arg) : super(), head(std::move(arg)) { }
template<typename Arg0, typename Arg1, typename... Args>
tdata(Arg0&& arg0, Arg1&& arg1, Args&&... args)
: super(std::forward<Arg1>(arg1), std::forward<Args>(args)...)
, head(td_filter<Head>(std::forward<Arg0>(arg0))) {
template<typename T0, typename T1, typename... Ts>
tdata(T0&& arg0, T1&& arg1, Ts&&... args)
: super(std::forward<T1>(arg1), std::forward<Ts>(args)...)
, head(td_filter<Head>(std::forward<T0>(arg0))) {
}
tdata(const tdata&) = default;
......@@ -285,10 +292,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
return *this;
}
template<typename Arg0, typename... Args>
inline void set(Arg0&& arg0, Args&&... args) {
head = std::forward<Arg0>(arg0);
super::set(std::forward<Args>(args)...);
template<typename T, typename... Ts>
inline void set(T&& arg, Ts&&... args) {
head = std::forward<T>(arg);
super::set(std::forward<Ts>(args)...);
}
inline size_t size() const { return num_elements; }
......@@ -317,10 +324,8 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
case 2: return ptr_to(super::super::head);
case 3: return ptr_to(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::at(p - 1);
default: return super::super::super::super::super::at(p - 5);
}
//return (p == 0) ? ptr_to(head) : super::at(p - 1);
}
inline void* mutable_at(size_t p) {
......@@ -335,40 +340,47 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
# else
return const_cast<void*>(at(p));
# endif
}
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;
}
template<size_t Pos>
back_type& _back(std::integral_constant<size_t, Pos>) {
std::integral_constant<size_t, Pos - 1> token;
back_type& _back(std::integral_constant<size_t,Pos>) {
std::integral_constant<size_t,Pos-1> token;
return super::_back(token);
}
back_type& back() {
std::integral_constant<size_t, sizeof...(Tail)> token;
std::integral_constant<size_t,sizeof...(Tail)> 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;
}
template<size_t Pos>
const back_type& _back(std::integral_constant<size_t, Pos>) const {
std::integral_constant<size_t, Pos - 1> token;
const back_type& _back(std::integral_constant<size_t,Pos>) const {
std::integral_constant<size_t,Pos-1> token;
return super::_back(token);
}
const back_type& back() const {
std::integral_constant<size_t, sizeof...(Tail)> token;
std::integral_constant<size_t,sizeof...(Tail)> token;
return _back(token);
}
};
......@@ -398,35 +410,39 @@ struct tdata_upcast_helper<0, Head, Tail...> {
template<typename T>
struct tdata_from_type_list;
template<typename... T>
struct tdata_from_type_list<util::type_list<T...>> {
typedef tdata<T...> type;
template<typename... Ts>
struct tdata_from_type_list<util::type_list<Ts...>> {
typedef tdata<Ts...> type;
};
template<typename... T>
inline void collect_tdata(tdata<T...>&) { }
template<typename T, typename U>
inline void rebind_value(T& lhs, U& rhs) {
lhs = rhs;
}
template<typename Storage, typename... Args>
void collect_tdata(Storage& storage, const tdata<>&, const Args&... args) {
collect_tdata(storage, args...);
template<typename T, typename U>
inline void rebind_value(util::rebindable_reference<T>& lhs, U& rhs) {
lhs.rebind(rhs);
}
template<typename Storage, typename Arg0, typename... Args>
void collect_tdata(Storage& storage, const Arg0& arg0, const Args&... args) {
storage.head = arg0.head;
collect_tdata(storage.tail(), arg0.tail(), args...);
template<typename... Ts>
inline void rebind_tdata(tdata<Ts...>&) { }
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 {
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>
const typename util::at<N, Ts...>::type& get(const detail::tdata<Ts...>& tv) {
static_assert(N < sizeof...(Ts), "N >= tv.size()");
......
......@@ -58,9 +58,8 @@ class tuple_vals : public abstract_tuple {
tuple_vals(const tuple_vals&) = default;
template<typename... Args>
tuple_vals(Args&&... args) : super(false)
, m_data(std::forward<Args>(args)...) { }
template<typename... Us>
tuple_vals(Us&&... args) : super(false), m_data(std::forward<Us>(args)...) { }
const void* native_data() const {
return &m_data;
......
......@@ -31,7 +31,9 @@
#ifndef 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/abstract_tuple.hpp"
......@@ -58,7 +60,7 @@ class tuple_view : public abstract_tuple {
public:
typedef tdata<Ts*...> data_type;
typedef tdata<util::rebindable_reference<Ts>...> data_type;
typedef types_array<Ts...> element_types;
......@@ -83,20 +85,17 @@ class tuple_view : public abstract_tuple {
}
abstract_tuple* copy() const {
auto result = new tuple_vals<Ts...>;
tuple_view_copy_helper f{result};
util::static_foreach<0, sizeof...(Ts)>::_(m_data, f);
return result;
return new tuple_vals<Ts...>{m_data};
}
const void* at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_data.at(pos);
return m_data.at(pos).get_ptr();
}
void* mutable_at(size_t pos) {
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 {
......@@ -114,6 +113,8 @@ class tuple_view : public abstract_tuple {
static types_array<Ts...> m_types;
tuple_view(const data_type& data) : m_data(data) { }
};
template<typename... Ts>
......
......@@ -37,59 +37,43 @@
#include "cppa/primitive_type.hpp"
namespace cppa { namespace detail {
// 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;
};
#include "cppa/util/rm_ref.hpp"
template<primitive_type PT, class Else>
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> { };
namespace cppa { namespace detail {
template<primitive_type PT>
struct wrapped_ptype { static const primitive_type ptype = PT; };
// maps type T the the corresponding fundamental_type
template<typename T>
struct type_to_ptype_impl :
// signed integers
if_else_ptype<std::is_same<T, std::int8_t>, pt_int8,
if_else_ptype<std::is_same<T, std::int16_t>, pt_int16,
if_else_ptype<std::is_same<T, std::int32_t>, pt_int32,
if_else_ptype<std::is_same<T, std::int64_t>, pt_int64,
// unsigned integers
if_else_ptype<std::is_same<T, std::uint8_t>, pt_uint8,
if_else_ptype<std::is_same<T, std::uint16_t>, pt_uint16,
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> > > > > > > > > > > > > > > {
struct type_to_ptype_impl {
static constexpr primitive_type ptype =
std::is_convertible<T,std::string>::value
? pt_u8string
: (std::is_convertible<T,std::u16string>::value
? pt_u16string
: (std::is_convertible<T,std::u32string>::value
? pt_u32string
: pt_null));
};
template<typename T>
struct type_to_ptype {
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
static const primitive_type ptype = type_to_ptype_impl<type>::ptype;
// integers
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 > { };
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> { };
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
......
......@@ -42,30 +42,20 @@
namespace cppa { namespace detail {
template<bool IsFun, typename T>
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; }
};
// 'absorbs' callables and instances of `anything`
template<typename T>
struct vg_fwd_<true, T> {
template<typename Arg>
static inline util::void_type _(Arg&&) { return {}; }
};
const T& vg_fwd(const T& arg, typename std::enable_if<not util::is_callable<T>::value>::type* = 0) {
return arg;
}
template<>
struct vg_fwd_<false,anything> {
static inline util::void_type _(const anything&) { return {}; }
};
inline util::void_type vg_fwd(const anything&) {
return {};
}
// absorbs callables and instances of `anything`
template<typename T>
struct vg_fwd
: vg_fwd_<util::is_callable<typename util::rm_ref<T>::type>::value,
typename util::rm_ref<T>::type> {
};
util::void_type vg_fwd(const T&, typename std::enable_if<util::is_callable<T>::value>::type* = 0) {
return {};
}
template<typename T>
struct vg_cmp {
......@@ -91,11 +81,11 @@ class value_guard {
value_guard() = default;
value_guard(const value_guard&) = default;
template<typename... Args>
value_guard(const Args&... args) : m_args(vg_fwd<Args>::_(args)...) { }
template<typename... Ts>
value_guard(const Ts&... args) : m_args(vg_fwd(args)...) { }
template<typename... Args>
inline bool operator()(const Args&... args) const {
template<typename... Ts>
inline bool operator()(const Ts&... args) const {
return _eval(m_args.head, m_args.tail(), args...);
}
......@@ -117,17 +107,17 @@ class value_guard {
return true;
}
template<typename T0, typename Arg0, typename... Args>
static inline bool _eval(const T0& head, const tdata<>&,
const Arg0& arg0, const Args&...) {
return cmp(head, arg0);
template<typename T, typename U, typename... Us>
static inline bool _eval(const T& head, const tdata<>&,
const U& arg, const Us&...) {
return cmp(head, arg);
}
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,
const Arg0& arg0, const Args&... args) {
return cmp(head, arg0) && _eval(tail.head, tail.tail(), args...);
const U& arg, const Us&... 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 {
typedef enable_weak_ptr combined_type;
template<typename... Args>
enable_weak_ptr(Args&&... args)
: Base(std::forward<Args>(args)...)
template<typename... Ts>
enable_weak_ptr(Ts&&... args)
: Base(std::forward<Ts>(args)...)
, m_anchor(new weak_ptr_anchor(this)) { }
void request_deletion() {
......
......@@ -37,7 +37,6 @@
#include <vector>
#include "cppa/config.hpp"
#include "cppa/either.hpp"
#include "cppa/extend.hpp"
#include "cppa/behavior.hpp"
#include "cppa/scheduled_actor.hpp"
......@@ -60,19 +59,14 @@ class event_based_actor : public scheduled_actor {
* @brief Finishes execution with exit reason
* {@link exit_reason::unallowed_function_call unallowed_function_call}.
*/
void dequeue(behavior&); //override
void dequeue(behavior&);
/**
* @copydoc dequeue(behavior&)
*/
void dequeue(partial_function&); //override
void dequeue_response(behavior&, message_id);
/**
* @copydoc dequeue(behavior&)
*/
void dequeue_response(behavior&, message_id_t);
resume_result resume(util::fiber*, actor_ptr&); //override
resume_result resume(util::fiber*, actor_ptr&);
/**
* @brief Initializes the actor.
......@@ -97,9 +91,10 @@ class event_based_actor : public scheduled_actor {
* @brief Provokes a compiler error to ensure that an event-based actor
* does not accidently uses receive() instead of become().
*/
template<typename... Args>
void receive(Args&&...) {
static_assert((sizeof...(Args) + 1) < 1,
template<typename... Ts>
void receive(Ts&&...) {
// this asssertion always fails
static_assert((sizeof...(Ts) + 1) < 1,
"You shall not use receive in an event-based actor. "
"Use become() instead.");
}
......@@ -107,30 +102,32 @@ class event_based_actor : public scheduled_actor {
/**
* @brief Provokes a compiler error.
*/
template<typename... Args>
void receive_loop(Args&&... args) {
receive(std::forward<Args>(args)...);
template<typename... Ts>
void receive_loop(Ts&&... args) {
receive(std::forward<Ts>(args)...);
}
/**
* @brief Provokes a compiler error.
*/
template<typename... Args>
void receive_while(Args&&... args) {
receive(std::forward<Args>(args)...);
template<typename... Ts>
void receive_while(Ts&&... args) {
receive(std::forward<Ts>(args)...);
}
/**
* @brief Provokes a compiler error.
*/
template<typename... Args>
void do_receive(Args&&... args) {
receive(std::forward<Args>(args)...);
template<typename... Ts>
void do_receive(Ts&&... args) {
receive(std::forward<Ts>(args)...);
}
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:
......@@ -154,8 +151,6 @@ class event_based_actor : public scheduled_actor {
}
}
detail::receive_policy m_policy;
};
} // namespace cppa
......
......@@ -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
* 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 {
/**
* @brief An alias for the result type.
* @brief Identifies the combined type.
*/
template<template<class,class> class... Mixins>
using with = typename detail::extend_helper<Derived,Base,Mixins...>::type;
......
......@@ -44,6 +44,7 @@
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/apply_args.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/tdata.hpp"
......@@ -96,8 +97,8 @@ struct guard_expr {
guard_expr(const guard_expr&) = default;
guard_expr(guard_expr&& other) : m_args(std::move(other.m_args)) { }
template<typename... Args>
bool operator()(const Args&... args) const;
template<typename... Ts>
bool operator()(const Ts&... args) const;
};
......@@ -109,58 +110,16 @@ struct guard_expr {
SubMacro (greater_eq_op, >=) SubMacro (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>
* that could be used in guard expressions or to enforce lazy evaluation.
*/
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
......@@ -385,7 +344,7 @@ template<typename T, class Tuple>
struct ge_unbound { typedef T type; };
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>
struct ge_unbound<std::reference_wrapper<T>, Tuple> { typedef T type; };
......@@ -418,7 +377,7 @@ struct is_ge_type<guard_placeholder<X> > {
};
template<typename T>
struct is_ge_type<ge_reference_wrapper<T> > {
struct is_ge_type<util::rebindable_reference<T> > {
static constexpr bool value = true;
};
......@@ -553,7 +512,7 @@ inline const T& ge_resolve(const Tuple&, const std::reference_wrapper<const 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();
}
......@@ -644,19 +603,19 @@ auto ge_resolve(const Tuple& tup,
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,
const detail::tdata<Args...>& tup)
-> typename ge_result<OP, First, Second, detail::tdata<Args...>>::type {
const detail::tdata<Ts...>& tup)
-> typename ge_result<OP, First, Second, detail::tdata<Ts...>>::type {
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,
const Args&... args)
const Ts&... args)
-> typename ge_result<OP, First, Second,
detail::tdata<std::reference_wrapper<const Args>...>>::type {
detail::tdata<std::reference_wrapper<const Args>...> tup{args...};
detail::tdata<std::reference_wrapper<const Ts>...>>::type {
detail::tdata<std::reference_wrapper<const Ts>...> tup{args...};
return ge_invoke_step2(ge, tup);
}
......@@ -664,9 +623,9 @@ template<class GuardExpr>
struct ge_invoke_helper {
const GuardExpr& ge;
ge_invoke_helper(const GuardExpr& arg) : ge(arg) { }
template<typename... Args>
bool operator()(Args&&... args) const {
return ge_invoke(ge, std::forward<Args>(args)...);
template<typename... Ts>
bool operator()(Ts&&... args) const {
return ge_invoke(ge, std::forward<Ts>(args)...);
}
};
......@@ -687,10 +646,10 @@ ge_invoke_any(const guard_expr<OP, First, Second>& ge,
>::type
result_type;
using namespace util;
typename if_else<
std::is_same<typename TupleTypes::back, anything>,
typename std::conditional<
std::is_same<typename TupleTypes::back,anything>::value,
TupleTypes,
wrapped<typename tl_push_back<TupleTypes, anything>::type>
wrapped<typename tl_push_back<TupleTypes,anything>::type>
>::type
cast_token;
auto x = tuple_cast(tup, cast_token);
......@@ -700,8 +659,8 @@ ge_invoke_any(const guard_expr<OP, First, Second>& ge,
}
template<operator_id OP, typename First, typename Second>
template<typename... Args>
bool guard_expr<OP, First, Second>::operator()(const Args&... args) const {
template<typename... Ts>
bool guard_expr<OP, First, Second>::operator()(const Ts&... args) const {
static_assert(std::is_same<decltype(ge_invoke(*this, args...)), bool>::value,
"guard expression does not return a boolean");
return ge_invoke(*this, args...);
......@@ -711,17 +670,17 @@ bool guard_expr<OP, First, Second>::operator()(const Args&... args) const {
template<typename T>
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>
struct mutable_gref_wrapped {
typedef ge_mutable_reference_wrapper<T> type;
typedef util::rebindable_reference<T> type;
};
template<typename T>
struct mutable_gref_wrapped<T&> {
typedef ge_mutable_reference_wrapper<T> type;
typedef util::rebindable_reference<T> type;
};
// finally ...
......
......@@ -36,7 +36,6 @@
#include <stdexcept>
#include <type_traits>
#include "cppa/intrusive_fwd_ptr.hpp"
#include "cppa/util/comparable.hpp"
namespace cppa {
......@@ -73,12 +72,6 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >,
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>
intrusive_ptr(intrusive_ptr<Y> other) : m_ptr(other.release()) {
static_assert(std::is_convertible<Y*, T*>::value,
......@@ -120,9 +113,9 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >,
set_ptr(new_value);
}
template<typename... Args>
void emplace(Args&&... args) {
reset(new T(std::forward<Args>(args)...));
template<typename... Ts>
void emplace(Ts&&... args) {
reset(new T(std::forward<Ts>(args)...));
}
intrusive_ptr& operator=(pointer ptr) {
......@@ -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
* of {@link ref_counted} and wraps it in an {@link intrusive_ptr}.
*/
template<typename T, typename... Args>
intrusive_ptr<T> make_counted(Args&&... args) {
return {new T(std::forward<Args>(args)...)};
template<typename T, typename... Ts>
intrusive_ptr<T> make_counted(Ts&&... args) {
return {new T(std::forward<Ts>(args)...)};
}
} // namespace cppa
......
This diff is collapsed.
......@@ -33,10 +33,9 @@
#include <type_traits>
#include "cppa/mailbox_element.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/blocking_single_reader_queue.hpp"
namespace cppa {
......@@ -61,14 +60,7 @@ class mailbox_based : public Base {
typedef mailbox_based combined_type;
typedef detail::recursive_queue_node mailbox_element;
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;
typedef intrusive::single_reader_queue<mailbox_element,del> mailbox_type;
template<typename... Ts>
mailbox_based(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
......@@ -86,10 +78,6 @@ class mailbox_based : public Base {
mailbox_type m_mailbox;
private:
inline Subtype* dthis() { return static_cast<Subtype*>(this); }
};
} // namespace cppa
......
......@@ -34,51 +34,52 @@
#include <cstdint>
#include "cppa/actor.hpp"
#include "cppa/extend.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message_id.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/memory_cached.hpp"
// 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 ::cppa::local_actor;
friend class local_actor;
friend class detail::memory;
public:
typedef recursive_queue_node* pointer;
typedef mailbox_element* pointer;
pointer next; // intrusive next pointer
bool marked; // denotes if this node is currently processed
actor_ptr sender; // points to the sender of msg
any_tuple msg; // 'content field'
message_id_t mid;
message_id mid;
recursive_queue_node(recursive_queue_node&&) = delete;
recursive_queue_node(const recursive_queue_node&) = delete;
recursive_queue_node& operator=(recursive_queue_node&&) = delete;
recursive_queue_node& operator=(const recursive_queue_node&) = delete;
mailbox_element(mailbox_element&&) = delete;
mailbox_element(const mailbox_element&) = delete;
mailbox_element& operator=(mailbox_element&&) = delete;
mailbox_element& operator=(const mailbox_element&) = delete;
template<typename... Ts>
inline static recursive_queue_node* create(Ts&&... args) {
return memory::create<recursive_queue_node>(std::forward<Ts>(args)...);
inline static mailbox_element* create(Ts&&... args) {
return detail::memory::create<mailbox_element>(std::forward<Ts>(args)...);
}
private:
recursive_queue_node() = default;
mailbox_element() = default;
recursive_queue_node(const actor_ptr& sptr,
mailbox_element(const actor_ptr& sptr,
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
......@@ -51,16 +51,10 @@ struct match_helper {
any_tuple tup;
match_helper(any_tuple t) : tup(std::move(t)) { }
match_helper(match_helper&&) = default;
/*
void operator()(partial_function&& arg) {
partial_function tmp{std::move(arg)};
tmp(tup);
}
*/
template<class Arg0, class... Args>
bool operator()(Arg0&& arg0, Args&&... args) {
auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...);
template<typename... Ts>
bool operator()(Ts&&... args) {
static_assert(sizeof...(Ts) > 0, "at least one argument required");
auto tmp = match_expr_convert(std::forward<Ts>(args)...);
static_assert(std::is_same<partial_function, decltype(tmp)>::value,
"match statement contains timeout");
return tmp(tup);
......@@ -86,20 +80,15 @@ class match_each_helper {
match_each_helper(Iterator first, Iterator last, Projection proj)
: i(first), e(last), p(proj) { }
template<typename... Cases>
void operator()(match_expr<Cases...> expr) {
template<typename... Ts>
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) {
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:
Iterator i;
......@@ -126,20 +115,15 @@ class match_for_helper {
match_for_helper(Iterator first, Predicate p, Advance a = Advance(), Projection pj = Projection())
: i(first), adv(a), pred(p), proj(pj) { }
template<typename... Cases>
void operator()(match_expr<Cases...> expr) {
template<typename... Ts>
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)) {
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:
Iterator i;
......@@ -199,8 +183,8 @@ struct unwind_and_call<Size, Size> {
return target.first.invoke(target.second, sub_result, std::forward<Unwinded>(args)...);
}
template<typename T, typename... Args>
static inline bool _(std::vector<T>&, Args&&...) { return false; }
template<typename T, typename... Ts>
static inline bool _(std::vector<T>&, Ts&&...) { return false; }
};
......@@ -272,34 +256,18 @@ class stream_matcher {
stream_matcher(iter first, iter last) : m_pos(first), m_end(last) { }
template<typename... Cases>
bool operator()(match_expr<Cases...>& expr) {
template<typename... Ts>
bool operator()(Ts&&... args) {
auto expr = match_expr_collect(std::forward<Ts>(args)...);
typedef decltype(expr) expr_type;
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 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:
iter m_pos;
......
This diff is collapsed.
......@@ -56,7 +56,7 @@ class message_future {
public:
inline continue_helper(message_id_t mid) : m_mid(mid) { }
inline continue_helper(message_id mid) : m_mid(mid) { }
template<typename F>
void continue_with(F fun) {
......@@ -71,7 +71,7 @@ class message_future {
private:
message_id_t m_mid;
message_id m_mid;
};
......@@ -80,20 +80,20 @@ class message_future {
/**
* @brief Sets @p mexpr as event-handler for the response message.
*/
template<typename... Cases, typename... Args>
continue_helper then(const match_expr<Cases...>& a0, const Args&... as) {
template<typename... Cs, typename... Ts>
continue_helper then(const match_expr<Cs...>& arg, const Ts&... args) {
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};
}
/**
* @brief Blocks until the response arrives and then executes @p mexpr.
*/
template<typename... Cases, typename... Args>
void await(const match_expr<Cases...>& arg0, const Args&... args) {
template<typename... Cs, typename... Ts>
void await(const match_expr<Cs...>& arg, const Ts&... args) {
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 {
/**
* @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& 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:
message_id_t m_mid;
message_id m_mid;
template<typename... Fs>
behavior fs2bhvr(Fs... fs) {
......@@ -169,9 +169,9 @@ class sync_handle_helper {
inline sync_handle_helper(const message_future& mf) : m_mf(mf) { }
template<typename... Args>
inline message_future::continue_helper operator()(Args&&... args) {
return m_mf.then(std::forward<Args>(args)...);
template<typename... Ts>
inline message_future::continue_helper operator()(Ts&&... args) {
return m_mf.then(std::forward<Ts>(args)...);
}
private:
......@@ -186,9 +186,9 @@ class sync_receive_helper {
inline sync_receive_helper(const message_future& mf) : m_mf(mf) { }
template<typename... Args>
inline void operator()(Args&&... args) {
m_mf.await(std::forward<Args>(args)...);
template<typename... Ts>
inline void operator()(Ts&&... args) {
m_mf.await(std::forward<Ts>(args)...);
}
private:
......
......@@ -42,7 +42,7 @@ struct invalid_message_id { constexpr invalid_message_id() { } };
* @brief
* @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 answered_flag_mask = 0x4000000000000000;
......@@ -50,14 +50,14 @@ class message_id_t : util::comparable<message_id_t> {
public:
constexpr message_id_t() : m_value(0) { }
constexpr message_id() : m_value(0) { }
message_id_t(message_id_t&&) = default;
message_id_t(const message_id_t&) = default;
message_id_t& operator=(message_id_t&&) = default;
message_id_t& operator=(const message_id_t&) = default;
message_id(message_id&&) = default;
message_id(const message_id&) = default;
message_id& operator=(message_id&&) = default;
message_id& operator=(const message_id&) = default;
inline message_id_t& operator++() {
inline message_id& operator++() {
++m_value;
return *this;
}
......@@ -78,12 +78,12 @@ class message_id_t : util::comparable<message_id_t> {
return valid() && !is_response();
}
inline message_id_t response_id() const {
return message_id_t(valid() ? m_value | response_flag_mask : 0);
inline message_id response_id() const {
return message_id(valid() ? m_value | response_flag_mask : 0);
}
inline message_id_t request_id() const {
return message_id_t(m_value & request_id_mask);
inline message_id request_id() const {
return message_id(m_value & request_id_mask);
}
inline void mark_as_answered() {
......@@ -94,24 +94,24 @@ class message_id_t : util::comparable<message_id_t> {
return m_value;
}
static inline message_id_t from_integer_value(std::uint64_t value) {
message_id_t result;
static inline message_id from_integer_value(std::uint64_t value) {
message_id result;
result.m_value = value;
return result;
}
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)
? 0 : ((m_value < other.m_value) ? -1 : 1);
}
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;
......
......@@ -36,8 +36,6 @@
#include "cppa/config.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/network/protocol.hpp"
namespace cppa { namespace network {
class middleman;
......
......@@ -48,8 +48,7 @@ class basic_memory_cache;
namespace cppa { namespace network {
class sync_request_info : public extend<memory_managed,sync_request_info>::
with<memory_cached> {
class sync_request_info : public extend<memory_managed>::with<memory_cached> {
friend class detail::memory;
......@@ -59,11 +58,11 @@ class sync_request_info : public extend<memory_managed,sync_request_info>::
pointer next; // intrusive next pointer
actor_ptr sender; // points to the sender of the message
message_id_t mid; // sync message ID
message_id mid; // sync message ID
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 {
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);
......@@ -107,7 +106,7 @@ class default_actor_proxy : public actor_proxy {
void forward_msg(const actor_ptr& sender,
any_tuple msg,
message_id_t mid = message_id_t());
message_id mid = message_id());
default_protocol_ptr m_proto;
process_information_ptr m_pinf;
......
......@@ -45,9 +45,9 @@ class default_message_queue : public ref_counted {
typedef value_type& reference;
template<typename... Args>
void emplace(Args&&... args) {
m_impl.emplace_back(std::forward<Args>(args)...);
template<typename... Ts>
void emplace(Ts&&... args) {
m_impl.emplace_back(std::forward<Ts>(args)...);
}
inline bool empty() const { return m_impl.empty(); }
......
......@@ -146,15 +146,6 @@ class default_peer : public continuable_io {
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;
......
......@@ -49,13 +49,13 @@ class message_header {
actor_ptr sender;
actor_ptr receiver;
message_id_t id;
message_id id;
message_header();
message_header(const actor_ptr& sender,
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 {
if (receiver) {
......
......@@ -36,15 +36,16 @@
#include <memory>
#include <functional>
#include "cppa/network/protocol.hpp"
#include "cppa/network/acceptor.hpp"
#include "cppa/network/continuable_reader.hpp"
#include "cppa/network/continuable_io.hpp"
namespace cppa { namespace detail { class singleton_manager; } }
namespace cppa { namespace network {
class protocol;
typedef intrusive_ptr<protocol> protocol_ptr;
/**
* @brief Multiplexes asynchronous IO.
*/
......
......@@ -39,9 +39,9 @@
#include "cppa/actor.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/intrusive_fwd_ptr.hpp"
#include "cppa/network/acceptor.hpp"
#include "cppa/network/middleman.hpp"
namespace cppa { class actor_addressing; }
......@@ -83,14 +83,6 @@ class protocol : public ref_counted {
void run_later(std::function<void()> fun);
struct ref_ftor {
void operator()(abstract_middleman*) const;
};
struct deref_ftor {
void operator()(abstract_middleman*) const;
};
protected:
// note: not thread-safe; call only in run_later functor!
......@@ -111,7 +103,7 @@ class protocol : public ref_counted {
private:
intrusive_fwd_ptr<abstract_middleman,ref_ftor,deref_ftor> m_parent;
intrusive_ptr<abstract_middleman> m_parent;
};
......
......@@ -119,7 +119,7 @@ class object {
/**
* @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);
......
......@@ -136,8 +136,8 @@ struct rvalue_builder {
rvalue_builder() = default;
template<typename... Args>
rvalue_builder(rvalue_builder_args_ctor, const Args&... args)
template<typename... Ts>
rvalue_builder(rvalue_builder_args_ctor, const Ts&... args)
: m_guard(args...)
, m_funs(args...) {
}
......@@ -262,8 +262,8 @@ __unspecified__ 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}.
*/
template<typename Arg0, typename... Args>
__unspecified__ on(const Arg0& arg0, const Args&... args);
template<typename T, typename... Ts>
__unspecified__ on(const T& arg, const Ts&... args);
/**
* @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;
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::value_guard<
typename util::tl_filter_not<
typename util::tl_trim<
typename util::tl_map<
util::type_list<Arg0, Args...>,
util::type_list<T,Ts...>,
detail::boxed_and_callable_to_void,
detail::implicit_conversions
>::type
......@@ -312,13 +312,13 @@ detail::rvalue_builder<
>::type
>,
typename util::tl_map<
util::type_list<Arg0, Args...>,
util::type_list<T,Ts...>,
detail::boxed_and_not_callable_to_void
>::type,
util::type_list<typename detail::pattern_type<Arg0>::type,
typename detail::pattern_type<Args>::type...> >
on(const Arg0& arg0, const Args&... args) {
return {detail::rvalue_builder_args_ctor{}, arg0, args...};
util::type_list<typename detail::pattern_type<T>::type,
typename detail::pattern_type<Ts>::type...> >
on(const T& arg, const Ts&... args) {
return {detail::rvalue_builder_args_ctor{}, arg, args...};
}
inline detail::rvalue_builder<detail::empty_value_guard,
......
......@@ -61,60 +61,54 @@ class partial_function {
public:
/** @cond PRIVATE */
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;
/** @endcond */
partial_function() = default;
partial_function(partial_function&&) = default;
partial_function(const partial_function&) = default;
partial_function& operator=(partial_function&&) = default;
partial_function& operator=(const partial_function&) = default;
template<typename... Cases>
partial_function(const match_expr<Cases...>& mexpr)
: m_impl(mexpr.as_behavior_impl()) { }
partial_function(impl_ptr ptr);
inline bool undefined() const {
return m_impl == nullptr;
}
inline bool defined_at(const any_tuple& value) {
return (m_impl) && m_impl->defined_at(value);
}
template<typename T>
inline bool operator()(T&& arg) {
return (m_impl) && m_impl->invoke(std::forward<T>(arg));
}
inline partial_function or_else(const partial_function& other) const {
return m_impl->or_else(other.m_impl);
}
inline behavior or_else(const behavior& other) const {
return behavior{m_impl->or_else(other.m_impl)};
}
template<typename... Cs>
partial_function(const match_expr<Cs...>& mexpr);
/**
* @brief Returns @p true if this partial function is defined for the
* types of @p value, false otherwise.
*/
inline bool defined_at(const any_tuple& value);
/**
* @brief Returns @p true if this partial function was applied to
* @p args, false otherwise.
* @note This member function can return @p false even if
* {@link defined_at()} returns @p true, because {@link defined_at()}
* does <b>not</b> evaluate guards.
*/
template<typename T>
typename std::conditional<T::may_have_timeout,behavior,partial_function>::type
or_else(const T& arg) const;
inline bool operator()(T&& arg);
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<
util::disjunction<
T0::may_have_timeout,
T1::may_have_timeout,
Ts::may_have_timeout...
>::value,
util::disjunction<Ts::may_have_timeout...>::value,
behavior,
partial_function
>::type
or_else(const T0& arg0, const T1& arg1, const Ts&... args) const;
inline const impl_ptr& as_behavior_impl() const;
or_else(Ts&&... args) const;
private:
......@@ -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<
util::disjunction<
T::may_have_timeout,
T0::may_have_timeout,
T1::may_have_timeout,
Ts::may_have_timeout...
>::value,
behavior,
partial_function
>::type
match_expr_convert(const T& arg0, const Ts&... args) {
return detail::match_expr_concat(arg0, args...);
match_expr_convert(const T0& arg0, const T1& arg1, const Ts&... args) {
return detail::match_expr_concat(arg0, arg1, args...);
}
/******************************************************************************
* inline and template member function implementations *
******************************************************************************/
inline const partial_function::impl_ptr& partial_function::as_behavior_impl() const {
return m_impl;
template<typename... Cs>
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>
typename std::conditional<T::may_have_timeout,behavior,partial_function>::type
partial_function::or_else(const T& arg) const {
return m_impl->or_else(arg.as_behavior_impl());
inline bool partial_function::operator()(T&& arg) {
return (m_impl) && m_impl->invoke(std::forward<T>(arg));
}
template<typename T0, typename T1, typename... Ts>
template<typename... Ts>
typename std::conditional<
util::disjunction<
T0::may_have_timeout,
T1::may_have_timeout,
Ts::may_have_timeout...
>::value,
util::disjunction<Ts::may_have_timeout...>::value,
behavior,
partial_function
>::type
partial_function::or_else(const T0& arg0, const T1& arg1, const Ts&... args) const {
return m_impl->or_else(match_expr_convert(arg0, arg1, args...).as_behavior_impl());
partial_function::or_else(Ts&&... args) const {
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
......
......@@ -47,8 +47,8 @@ class actor_widget_mixin : public actor_companion_mixin<Base> {
public:
template<typename... Args>
actor_widget_mixin(Args&&... args) : super(std::forward<Args>(args)...) { }
template<typename... Ts>
actor_widget_mixin(Ts&&... args) : super(std::forward<Ts>(args)...) { }
struct event_type : public QEvent {
......
......@@ -38,62 +38,64 @@
namespace cppa {
#ifdef CPPA_DOCUMENTATION
/**
* @ingroup BlockingAPI
* @{
*/
/**
* @brief Dequeues the next message from the mailbox that's matched
* by @p bhvr and executes the corresponding callback.
* @param bhvr Denotes the actor's response the next incoming message.
* @brief Dequeues the next message from the mailbox that
* is matched by given behavior.
*/
void receive(behavior& bhvr);
template<typename... Ts>
void receive(Ts&&... args);
/**
* @brief Receives messages in an endless loop.
*
* Semantically equal to: <tt>for (;;) { receive(bhvr); }</tt>
* @param bhvr Denotes the actor's response the next incoming message.
* Semantically equal to: <tt>for (;;) { receive(...); }</tt>
*/
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>
* @code
* int i = 0;
* receive_while([&]() { return (++i <= 10); })
* (
* on<int>() >> int_fun,
* on<float>() >> float_fun
* receive_for(i, 10) (
* on(atom("get")) >> [&]() { reply("result", i); }
* );
* @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.
*/
template<typename Statement>
auto receive_while(Statement&& stmt);
template<typename T>
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>
* @code
* 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
* @param begin First value in range.
* @param end Last value in range (excluded).
* @param stmt Lambda expression, functor or function returning a @c bool.
* @returns A functor implementing the loop.
*/
template<typename T>
auto receive_for(T& begin, const T& end);
template<typename Statement>
detail::receive_while_helper<Statement> receive_while(Statement&& stmt);
/**
* @brief Receives messages until @p stmt returns true.
......@@ -113,32 +115,34 @@ auto receive_for(T& begin, const T& end);
* @param bhvr Denotes the actor's response the next incoming message.
* @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>
void receive(Arg0&& arg0, Args&&... args) {
auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...);
receive(tmp);
template<typename... Ts>
void receive(Ts&&... args) {
static_assert(sizeof...(Ts), "receive() requires at least one argument");
self->dequeue(match_expr_convert(std::forward<Ts>(args)...));
}
void receive_loop(behavior& rules);
void receive_loop(behavior&& rules);
void receive_loop(partial_function& rules);
void receive_loop(partial_function&& rules);
inline void receive_loop(behavior rules) {
local_actor* sptr = self;
for (;;) sptr->dequeue(rules);
}
template<typename Arg0, typename... Args>
void receive_loop(Arg0&& arg0, Args&&... args) {
auto tmp = match_expr_convert(std::forward<Arg0>(arg0),
std::forward<Args>(args)...);
receive_loop(tmp);
template<typename... Ts>
void receive_loop(Ts&&... args) {
behavior bhvr = match_expr_convert(std::forward<Ts>(args)...);
local_actor* sptr = self;
for (;;) sptr->dequeue(bhvr);
}
template<typename T>
......@@ -153,13 +157,12 @@ detail::receive_while_helper<Statement> receive_while(Statement&& stmt) {
return std::move(stmt);
}
template<typename... Args>
detail::do_receive_helper do_receive(Args&&... args) {
return detail::do_receive_helper(std::forward<Args>(args)...);
template<typename... Ts>
detail::do_receive_helper do_receive(Ts&&... args) {
behavior bhvr = match_expr_convert(std::forward<Ts>(args)...);
return detail::do_receive_helper(std::move(bhvr));
}
#endif // CPPA_DOCUMENTATION
} // namespace cppa
#endif // CPPA_RECEIVE_HPP
......@@ -52,7 +52,7 @@ class response_handle {
response_handle(const actor_ptr& from,
const actor_ptr& to,
const message_id_t& response_id);
const message_id& response_id);
/**
* @brief Queries whether response message is still outstanding.
......@@ -73,7 +73,7 @@ class response_handle {
/**
* @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.
......@@ -89,7 +89,7 @@ class response_handle {
actor_ptr m_from;
actor_ptr m_to;
message_id_t m_id;
message_id m_id;
};
......
......@@ -66,8 +66,8 @@ class sb_actor : public Base {
protected:
template<typename... Args>
sb_actor(Args&&... args) : Base(std::forward<Args>(args)...) { }
template<typename... Ts>
sb_actor(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
};
......
......@@ -38,9 +38,11 @@
#include "cppa/actor_state.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/mailbox_based.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/detail/memory.hpp"
#include "cppa/detail/receive_policy.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
namespace cppa {
......@@ -68,7 +70,7 @@ struct has_blocking_receive<scheduled_actor> : std::true_type { };
* @brief A base class for cooperatively scheduled actors.
* @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;
......@@ -115,13 +117,15 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox
*/
inline bool is_hidden() const;
virtual void run_detached();
void 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);
......@@ -160,8 +164,6 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox
void cleanup(std::uint32_t reason);
typedef detail::recursive_queue_node mailbox_element;
typedef intrusive::single_reader_queue<mailbox_element,detail::disposer>
mailbox_type;
......@@ -195,7 +197,7 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox
bool sync_enqueue_impl(actor_state next,
const actor_ptr& sender,
any_tuple& msg,
message_id_t id);
message_id id);
bool m_has_pending_tout;
std::uint32_t m_pending_tout;
......
......@@ -144,7 +144,7 @@ class scheduler {
template<typename Duration, typename... Data>
void delayed_reply(const actor_ptr& to,
const Duration& rel_time,
message_id_t id,
message_id id,
any_tuple data ) {
CPPA_REQUIRE(!id.valid() || id.is_response());
if (id.valid()) {
......
......@@ -37,15 +37,18 @@
#include "cppa/behavior.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/receive_policy.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
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>
class stacked : public Base {
......@@ -61,25 +64,18 @@ class stacked : public Base {
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) {
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) {
m_recv_policy.receive(dthis(), bhvr, request_id);
virtual void dequeue_response(behavior& bhvr, message_id request_id) {
m_recv_policy.receive(util::dptr<Subtype>(this), bhvr, request_id);
}
virtual void run() {
if (!dthis()->m_bhvr_stack.empty()) {
dthis()->exec_behavior_stack();
}
if (m_behavior) {
m_behavior();
}
auto dthis = util::dptr<Subtype>(this);
if (!dthis->m_bhvr_stack.empty()) dthis->exec_behavior_stack();
if (m_behavior) m_behavior();
}
inline void set_behavior(std::function<void()> fun) {
......@@ -91,55 +87,46 @@ class stacked : public Base {
throw actor_exited(reason);
}
virtual void exec_behavior_stack() {
this->m_bhvr_stack.exec(m_recv_policy, util::dptr<Subtype>(this));
}
protected:
template<typename... Args>
stacked(std::function<void()> fun, Args&&... args)
: Base(std::forward<Args>(args)...), m_behavior(std::move(fun)) { }
template<typename... Ts>
stacked(std::function<void()> fun, Ts&&... args)
: Base(std::forward<Ts>(args)...), m_behavior(std::move(fun)) { }
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);
}
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;
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()) {
dthis()->reset_timeout();
dthis()->request_timeout(bhvr.timeout());
dthis->reset_timeout();
dthis->request_timeout(bhvr.timeout());
}
if (!dthis()->m_bhvr_stack.empty() && discard_old) {
dthis()->m_bhvr_stack.pop_async_back();
if (!dthis->m_bhvr_stack.empty() && discard_old) {
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
......
......@@ -43,18 +43,16 @@
#include <cstdint>
#include "cppa/atom.hpp"
#include "cppa/either.hpp"
#include "cppa/extend.hpp"
#include "cppa/stacked.hpp"
#include "cppa/threaded.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/mailbox_based.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/detail/receive_policy.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/intrusive/blocking_single_reader_queue.hpp"
namespace cppa {
......@@ -66,10 +64,10 @@ template<>
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
*/
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 scheduler_helper; // needs access to mailbox
......@@ -88,40 +86,14 @@ class thread_mapped_actor : public extend<local_actor,thread_mapped_actor>::with
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:
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);
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;
protected:
mailbox_type m_mailbox;
};
typedef intrusive_ptr<thread_mapped_actor> thread_mapped_actor_ptr;
......
......@@ -28,149 +28,142 @@
\******************************************************************************/
#ifndef CPPA_INTRUSIVE_FWD_PTR_HPP
#define CPPA_INTRUSIVE_FWD_PTR_HPP
#ifndef CPPA_THREADED_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 {
/**
* @brief A reference counting smart pointer implementation that
* 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> {
template<class Base, class Subtype>
class threaded : public Base {
friend class detail::receive_policy;
typedef std::unique_lock<std::mutex> lock_type;
public:
typedef T* pointer;
typedef const T* const_pointer;
typedef T element_type;
typedef T& reference;
typedef const T& const_reference;
template<typename... Ts>
threaded(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
intrusive_fwd_ptr(pointer raw_ptr = nullptr, Ref ref = Ref(), Deref deref = Deref())
: m_ref(std::move(ref)), m_deref(std::move(deref)) { set_ptr(raw_ptr); }
inline void reset_timeout() { }
intrusive_fwd_ptr(intrusive_fwd_ptr&& other)
: m_ref(std::move(other.m_ref))
, m_deref(std::move(m_deref))
, m_ptr(other.release()) { }
inline void request_timeout(const util::duration&) { }
intrusive_fwd_ptr(const intrusive_fwd_ptr& other)
: m_ref(other.m_ref), m_deref(other.m_deref) { set_ptr(other.get()); }
inline void handle_timeout(behavior& bhvr) { bhvr.handle_timeout(); }
~intrusive_fwd_ptr() { if (m_ptr) m_deref(m_ptr); }
inline void pop_timeout() { }
inline void swap(intrusive_fwd_ptr& other) {
std::swap(m_ptr, other.m_ptr);
}
inline void push_timeout() { }
/**
* @brief Returns the raw pointer without modifying reference count.
*/
pointer release() {
auto result = m_ptr;
m_ptr = nullptr;
return result;
}
inline bool waits_for_timeout(std::uint32_t) { return false; }
/**
* @brief Sets this pointer to @p ptr without modifying reference count.
*/
void adopt(pointer ptr) {
reset();
m_ptr = ptr;
mailbox_element* pop() {
wait_for_data();
return this->m_mailbox.try_pop();
}
void reset(pointer new_value = nullptr) {
if (m_ptr) m_deref(m_ptr);
set_ptr(new_value);
inline mailbox_element* try_pop() {
return this->m_mailbox.try_pop();
}
template<typename... Args>
void emplace(Args&&... args) {
reset(new T(std::forward<Args>(args)...));
template<typename TimePoint>
mailbox_element* try_pop(const TimePoint& abs_time) {
return (timed_wait_for_data(abs_time)) ? try_pop() : nullptr;
}
intrusive_fwd_ptr& operator=(pointer ptr) {
reset(ptr);
return *this;
bool push_back(mailbox_element* new_element) {
switch (this->m_mailbox.enqueue(new_element)) {
case intrusive::first_enqueued: {
lock_type guard(m_mtx);
m_cv.notify_one();
return true;
}
default: return true;
case intrusive::queue_closed: return false;
}
intrusive_fwd_ptr& operator=(intrusive_fwd_ptr&& other) {
swap(other);
return *this;
}
intrusive_fwd_ptr& operator=(const intrusive_fwd_ptr& other) {
intrusive_fwd_ptr tmp(other);
swap(tmp);
return *this;
void run_detached() {
auto dthis = util::dptr<Subtype>(this);
dthis->init();
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 {
return static_cast<ptrdiff_t>(get() - ptr);
timeout_type init_timeout(const util::duration& rel_time) {
auto result = std::chrono::high_resolution_clock::now();
result += rel_time;
return result;
}
inline ptrdiff_t compare(const intrusive_fwd_ptr& other) const {
return compare(other.get());
mailbox_element* await_message() {
return pop();
}
inline ptrdiff_t compare(std::nullptr_t) const {
return reinterpret_cast<ptrdiff_t>(get());
mailbox_element* await_message(const timeout_type& abs_time) {
return try_pop(abs_time);
}
private:
Ref m_ref;
Deref m_deref;
pointer m_ptr;
bool timed_wait_for_data(const timeout_type& abs_time) {
CPPA_REQUIRE(not this->m_mailbox.closed());
if (this->m_mailbox.empty()) {
lock_type guard(m_mtx);
while (this->m_mailbox.empty()) {
if (m_cv.wait_until(guard, abs_time) == std::cv_status::timeout) {
return false;
}
}
}
return true;
}
inline void set_ptr(pointer raw_ptr) {
m_ptr = raw_ptr;
if (raw_ptr) m_ref(raw_ptr);
void wait_for_data() {
if (this->m_mailbox.empty()) {
lock_type guard(m_mtx);
while (this->m_mailbox.empty()) m_cv.wait(guard);
}
}
};
std::mutex m_mtx;
std::condition_variable m_cv;
/**
* @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
#endif // CPPA_INTRUSIVE_FWD_PTR_HPP
#endif // CPPA_THREADED_HPP
......@@ -43,22 +43,22 @@
namespace cppa {
template<class Expr, class Guard, typename Result, typename... Args>
template<class Expr, class Guard, typename Result, typename... Ts>
class tpartial_function {
typedef typename util::get_callable_trait<Expr>::type ctrait;
typedef typename ctrait::arg_types ctrait_args;
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,
"partial functions using rvalue arguments are not supported");
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 =
util::tl_exists<arg_types, util::is_mutable_ref>::value;
......@@ -78,11 +78,11 @@ class tpartial_function {
tpartial_function(const tpartial_function&) = default;
bool defined_at(Args... args) const {
bool defined_at(Ts... args) const {
return m_guard(args...);
}
result_type operator()(Args... args) const {
result_type operator()(Ts... args) const {
auto targs = std::forward_as_tuple(args...);
auto indices = util::get_right_indices<num_expr_args>(targs);
return util::apply_args(m_expr, targs, indices);
......@@ -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>
struct get_tpartial_function;
template<class Expr, class Guard, typename... Args, typename Result>
struct get_tpartial_function<Expr, Guard, util::type_list<Args...>, Result, 1> {
typedef tpartial_function<Expr, Guard, Result, Args...> type;
template<class Expr, class Guard, typename... Ts, typename Result>
struct get_tpartial_function<Expr, Guard, util::type_list<Ts...>, Result, 1> {
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,
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 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");
typedef typename get_tpartial_function<
Expr,
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_pad_left<
typename ctrait::arg_types,
sizeof...(Args)
sizeof...(Ts)
>::type,
util::type_list<const Args&...>,
util::type_list<const Ts&...>,
util::left_or_right
>::type,
typename ctrait::result_type,
......
......@@ -44,16 +44,16 @@ inline auto apply_args(F& f, Tuple& tup, util::int_list<Is...>)
return f(get_cv_aware<Is>(tup)...);
}
template<typename F, class Tuple, long... Is, typename... Args>
inline auto apply_args_prefixed(F& f, Tuple& tup, util::int_list<Is...>, Args&&... args)
-> decltype(f(std::forward<Args>(args)..., get_cv_aware<Is>(tup)...)) {
return f(std::forward<Args>(args)..., get_cv_aware<Is>(tup)...);
template<typename F, class Tuple, long... Is, typename... Ts>
inline auto apply_args_prefixed(F& f, Tuple& tup, util::int_list<Is...>, Ts&&... args)
-> decltype(f(std::forward<Ts>(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>
inline auto apply_args_suffxied(F& f, Tuple& tup, util::int_list<Is...>, Args&&... args)
-> decltype(f(get_cv_aware<Is>(tup)..., std::forward<Args>(args)...)) {
return f(get_cv_aware<Is>(tup)..., std::forward<Args>(args)...);
template<typename F, class Tuple, long... Is, typename... Ts>
inline auto apply_args_suffxied(F& f, Tuple& tup, util::int_list<Is...>, Ts&&... args)
-> decltype(f(get_cv_aware<Is>(tup)..., std::forward<Ts>(args)...)) {
return f(get_cv_aware<Is>(tup)..., std::forward<Ts>(args)...);
}
} } // namespace cppa::util
......
......@@ -45,7 +45,7 @@ enum buffer_write_policy {
};
/**
*
* @brief
*/
class buffer {
......
This diff is collapsed.
......@@ -28,34 +28,33 @@
\******************************************************************************/
#ifndef CPPA_IF_ELSE_HPP
#define CPPA_IF_ELSE_HPP
#ifndef CPPA_DTHIS_HPP
#define CPPA_DTHIS_HPP
#include "cppa/util/wrapped.hpp"
#include <type_traits>
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
* nested statements (unlike std::conditional).
*
* @c type is defined as @p T if <tt>IfStmt == true</tt>;
* otherwise @c type is defined as @p Else::type.
* @brief Returns <tt>static_cast<Subtype*>(ptr)</tt> if @p Subtype is a
* derived type of @p MixinType, returns @p ptr without cast otherwise.
*/
template<class Stmt, typename T, class Else>
struct if_else : if_else_c<Stmt::value, T, Else> { };
template<class Subtype, class MixinType>
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
#endif // CPPA_IF_ELSE_HPP
#endif // CPPA_DTHIS_HPP
......@@ -28,20 +28,30 @@
\******************************************************************************/
#ifndef CPPA_CHANNEL_HPP
#define CPPA_CHANNEL_HPP
#ifndef CPPA_GET_RESULT_TYPE_HPP
#define CPPA_GET_RESULT_TYPE_HPP
#include "cppa/ref_counted.hpp"
#include "cppa/util/is_callable.hpp"
#include "cppa/util/callable_trait.hpp"
namespace cppa { class message; }
namespace cppa { namespace util {
namespace cppa { namespace detail {
template<bool IsCallable, typename C>
struct get_result_type_impl {
typedef typename get_callable_trait<C>::type trait_type;
typedef typename trait_type::result_type type;
};
template<typename C>
struct get_result_type_impl<false, C> {
typedef void_type type;
};
// public part of the actor interface
struct channel : ref_counted {
virtual void enqueue_msg(const message& msg) = 0;
template<typename C>
struct get_result_type {
typedef typename get_result_type_impl<is_callable<C>::value, C>::type type;
};
} } // namespace cppa::detail
} } // namespace cppa::util
#endif // CPPA_CHANNEL_HPP
#endif // CPPA_GET_RESULT_TYPE_HPP
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.
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