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

allow event-based actors to become detached

this patch extends the `spawn` function to allow `spawn<Impl,blocking_api>(...)`
and thereby allow users to detach event-based actors using a class;
this patch also removes some unneeded headers, renames
`detail::recursive_queue_node` to `mailbox_element`, combines the two classes
`ge_reference_wrapper` and `ge_mutable_reference_wrapper` to simply
`rebindable_reference`, and does some maintenance and documentation
parent 48a29c72
......@@ -124,6 +124,7 @@ set(LIBCPPA_SRC
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,7 +138,6 @@ set(LIBCPPA_SRC
src/primitive_variant.cpp
src/process_information.cpp
src/protocol.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
......@@ -144,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
......@@ -167,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
......@@ -243,7 +240,7 @@ src/partial_function.cpp
src/primitive_variant.cpp
src/process_information.cpp
src/protocol.cpp
src/recursive_queue_node.cpp
src/mailbox_element.cpp
src/ref_counted.cpp
src/response_handle.cpp
src/ripemd_160.cpp
......@@ -289,3 +286,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
......@@ -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,26 +129,22 @@ 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 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&) {
......@@ -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"
......
......@@ -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"
......@@ -741,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));
}
......
......@@ -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 {
......@@ -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
......
......@@ -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,
......@@ -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) {
......
......@@ -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 {
......@@ -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,14 +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_response(behavior&, message_id);
resume_result resume(util::fiber*, actor_ptr&); //override
resume_result resume(util::fiber*, actor_ptr&);
/**
* @brief Initializes the actor.
......@@ -92,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.");
}
......@@ -102,31 +102,33 @@ 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 mf);
detail::receive_policy m_recv_policy;
private:
inline bool has_behavior() const {
......@@ -149,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 ...
......
......@@ -113,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) {
......@@ -207,9 +207,9 @@ inline bool operator!=(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs)
* @brief Constructs an object of type T which must be a derived type
* 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
......
......@@ -43,13 +43,13 @@
#include "cppa/match_expr.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/memory_cached.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/response_handle.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/detail/behavior_stack.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
namespace cppa {
......@@ -85,7 +85,7 @@ constexpr keep_behavior_t keep_behavior = keep_behavior_t{};
* @brief Base class for local running Actors.
* @extends actor
*/
class local_actor : public extend<actor,local_actor>::with<memory_cached> {
class local_actor : public extend<actor>::with<memory_cached> {
typedef combined_type super;
......@@ -329,11 +329,11 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
std::vector<message_id> m_pending_responses;
// "default value" for m_current_node
detail::recursive_queue_node m_dummy_node;
mailbox_element m_dummy_node;
// points to m_dummy_node if no callback is currently invoked,
// points to the node under processing otherwise
detail::recursive_queue_node* m_current_node;
mailbox_element* m_current_node;
// {group => subscription} map of all joined groups
std::map<group_ptr, group::subscription> m_subscriptions;
......
......@@ -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,24 +34,25 @@
#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
......@@ -59,26 +60,26 @@ class recursive_queue_node : public memory_cached<memory_managed,recursive_queue
any_tuple msg; // 'content field'
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 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.
......@@ -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);
}
/**
......@@ -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:
......
......@@ -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;
......
......@@ -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;
......
......@@ -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,
......
......@@ -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 {
......
......@@ -115,8 +115,8 @@ detail::receive_while_helper<Statement> receive_while(Statement&& stmt);
* @param bhvr Denotes the actor's response the next incoming message.
* @returns A functor providing the @c until member function.
*/
template<typename... Args>
detail::do_receive_helper do_receive(Args&&... args);
template<typename... Ts>
detail::do_receive_helper do_receive(Ts&&... args);
/**
* @}
......
......@@ -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,6 +117,8 @@ 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);
......@@ -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;
......
......@@ -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 {
......@@ -62,20 +65,17 @@ class stacked : public Base {
static constexpr auto receive_flag = detail::rp_nestable;
virtual void dequeue(behavior& bhvr) {
m_recv_policy.receive(dthis(), bhvr);
m_recv_policy.receive(util::dptr<Subtype>(this), bhvr);
}
virtual void dequeue_response(behavior& bhvr, message_id request_id) {
m_recv_policy.receive(dthis(), bhvr, 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) {
......@@ -87,11 +87,15 @@ 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());
......@@ -102,40 +106,27 @@ class stacked : public Base {
}
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;
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 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,71 +28,142 @@
\******************************************************************************/
#ifndef CPPA_STATIC_FOREACH_HPP
#define CPPA_STATIC_FOREACH_HPP
#include "cppa/get.hpp"
namespace cppa { namespace util {
template<bool BeginLessEnd, size_t Begin, size_t End>
struct static_foreach_impl {
template<typename Container, typename Fun, typename... Args>
static inline void _(const Container& c, Fun& f, Args&&... args) {
f(get<Begin>(c), std::forward<Args>(args)...);
static_foreach_impl<(Begin+1 < End), Begin+1, End>
::_(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline void _ref(Container& c, Fun& f, Args&&... args) {
f(get_ref<Begin>(c), std::forward<Args>(args)...);
static_foreach_impl<(Begin+1 < End), Begin+1, End>
::_ref(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline void _auto(Container& c, Fun& f, Args&&... args) {
_ref(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline void _auto(const Container& c, Fun& f, Args&&... args) {
_(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline bool eval(const Container& c, Fun& f, Args&&... args) {
return f(get<Begin>(c), std::forward<Args>(args)...)
&& static_foreach_impl<(Begin+1 < End), Begin+1, End>
::eval(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline bool eval_or(const Container& c, Fun& f, Args&&... args) {
return f(get<Begin>(c), std::forward<Args>(args)...)
|| static_foreach_impl<(Begin+1 < End), Begin+1, End>
::eval_or(c, f, std::forward<Args>(args)...);
#ifndef CPPA_THREADED_HPP
#define CPPA_THREADED_HPP
#include <mutex>
#include <chrono>
#include <condition_variable>
#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 {
template<class Base, class Subtype>
class threaded : public Base {
friend class detail::receive_policy;
typedef std::unique_lock<std::mutex> lock_type;
public:
template<typename... Ts>
threaded(Ts&&... args) : Base(std::forward<Ts>(args)...) { }
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; }
mailbox_element* pop() {
wait_for_data();
return this->m_mailbox.try_pop();
}
};
template<size_t X, size_t Y>
struct static_foreach_impl<false, X, Y> {
template<typename... Args>
static inline void _(Args&&...) { }
template<typename... Args>
static inline void _ref(Args&&...) { }
template<typename... Args>
static inline void _auto(Args&&...) { }
template<typename... Args>
static inline bool eval(Args&&...) { return true; }
template<typename... Args>
static inline bool eval_or(Args&&...) { return false; }
};
inline mailbox_element* try_pop() {
return this->m_mailbox.try_pop();
}
template<typename TimePoint>
mailbox_element* try_pop(const TimePoint& abs_time) {
return (timed_wait_for_data(abs_time)) ? try_pop() : nullptr;
}
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;
}
}
void run_detached() {
auto dthis = util::dptr<Subtype>(this);
dthis->init();
dthis->m_bhvr_stack.exec(dthis->m_recv_policy, dthis);
dthis->on_exit();
}
protected:
typedef threaded combined_type;
virtual void enqueue(const actor_ptr& sender, any_tuple msg) {
auto ptr = this->new_mailbox_element(sender, std::move(msg));
push_back(ptr);
}
virtual void sync_enqueue(const actor_ptr& sender, message_id id, any_tuple msg) {
auto ptr = this->new_mailbox_element(sender, std::move(msg), id);
if (!push_back(ptr)) {
detail::sync_request_bouncer f{this->exit_reason()};
f(sender, id);
}
}
typedef std::chrono::high_resolution_clock::time_point timeout_type;
timeout_type init_timeout(const util::duration& rel_time) {
auto result = std::chrono::high_resolution_clock::now();
result += rel_time;
return result;
}
mailbox_element* await_message() {
return pop();
}
mailbox_element* await_message(const timeout_type& abs_time) {
return try_pop(abs_time);
}
private:
bool timed_wait_for_data(const timeout_type& abs_time) {
CPPA_REQUIRE(not this->m_mailbox.closed());
if (this->m_mailbox.empty()) {
lock_type guard(m_mtx);
while (this->m_mailbox.empty()) {
if (m_cv.wait_until(guard, abs_time) == std::cv_status::timeout) {
return false;
}
}
}
return true;
}
void wait_for_data() {
if (this->m_mailbox.empty()) {
lock_type guard(m_mtx);
while (this->m_mailbox.empty()) m_cv.wait(guard);
}
}
std::mutex m_mtx;
std::condition_variable m_cv;
/**
* @ingroup MetaProgramming
* @brief A for loop that can be used with tuples.
*/
template<size_t Begin, size_t End>
struct static_foreach : static_foreach_impl<(Begin < End), Begin, End> {
};
} } // namespace cppa::util
} // namespace cppa
#endif // CPPA_STATIC_FOREACH_HPP
#endif // CPPA_THREADED_HPP
......@@ -43,22 +43,22 @@
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 {
......
......@@ -36,60 +36,63 @@
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/conjunction.hpp"
namespace cppa { namespace util {
template<typename Signature>
struct callable_trait;
// member function pointer (const)
template<class C, typename ResultType, typename... Args>
struct callable_trait<ResultType (C::*)(Args...) const> {
typedef ResultType result_type;
typedef type_list<Args...> arg_types;
// member const function pointer
template<class C, typename Result, typename... Ts>
struct callable_trait<Result (C::*)(Ts...) const> {
typedef Result result_type;
typedef type_list<Ts...> arg_types;
};
// member function pointer
template<class C, typename ResultType, typename... Args>
struct callable_trait<ResultType (C::*)(Args...)> {
typedef ResultType result_type;
typedef type_list<Args...> arg_types;
template<class C, typename Result, typename... Ts>
struct callable_trait<Result (C::*)(Ts...)> {
typedef Result result_type;
typedef type_list<Ts...> arg_types;
};
// good ol' function
template<typename ResultType, typename... Args>
struct callable_trait<ResultType (Args...)> {
typedef ResultType result_type;
typedef type_list<Args...> arg_types;
template<typename Result, typename... Ts>
struct callable_trait<Result (Ts...)> {
typedef Result result_type;
typedef type_list<Ts...> arg_types;
};
// good ol' function pointer
template<typename ResultType, typename... Args>
struct callable_trait<ResultType (*)(Args...)> {
typedef ResultType result_type;
typedef type_list<Args...> arg_types;
template<typename Result, typename... Ts>
struct callable_trait<Result (*)(Ts...)> {
typedef Result result_type;
typedef type_list<Ts...> arg_types;
};
template<bool IsFun, bool IsMemberFun, typename C>
// matches (IsFun || IsMemberFun)
template<bool IsFun, bool IsMemberFun, typename T>
struct get_callable_trait_helper {
typedef callable_trait<C> type;
typedef callable_trait<T> type;
};
// assume functor providing operator()
template<typename C>
struct get_callable_trait_helper<false, false, C> {
// assuming functor
typedef callable_trait<decltype(&C::operator())> type;
};
template<typename C>
template<typename T>
struct get_callable_trait {
typedef typename rm_ref<C>::type fun_type;
typedef typename
get_callable_trait_helper< ( std::is_function<fun_type>::value
|| std::is_function<typename std::remove_pointer<fun_type>::type>::value),
std::is_member_function_pointer<fun_type>::value,
fun_type>::type
// type without cv qualifiers
typedef typename rm_ref<T>::type bare_type;
// if type is a function pointer, this typedef identifies the function
typedef typename std::remove_pointer<bare_type>::type fun_type;
typedef typename get_callable_trait_helper<
std::is_function<bare_type>::value
|| std::is_function<fun_type>::value,
std::is_member_function_pointer<bare_type>::value,
bare_type
>::type
type;
typedef typename type::result_type result_type;
typedef typename type::arg_types arg_types;
......@@ -101,51 +104,6 @@ struct get_arg_types {
typedef typename trait_type::arg_types types;
};
template<typename T>
struct is_callable {
template<typename C>
static bool _fun(C*, typename callable_trait<C>::result_type* = nullptr) {
return true;
}
template<typename C>
static bool _fun(C*, typename callable_trait<decltype(&C::operator())>::result_type* = nullptr) {
return true;
}
static void _fun(void*) { }
typedef decltype(_fun(static_cast<typename rm_ref<T>::type*>(nullptr)))
result_type;
public:
static constexpr bool value = std::is_same<bool, result_type>::value;
};
template<typename... Ts>
struct all_callable {
static constexpr bool value = conjunction<is_callable<Ts>...>::value;
};
template<bool IsCallable, typename C>
struct get_result_type_impl {
typedef typename get_callable_trait<C>::type trait_type;
typedef typename trait_type::result_type type;
};
template<typename C>
struct get_result_type_impl<false, C> {
typedef void_type type;
};
template<typename C>
struct get_result_type {
typedef typename get_result_type_impl<is_callable<C>::value, C>::type type;
};
} } // namespace cppa::util
#endif // CPPA_UTIL_CALLABLE_TRAIT
......@@ -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
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_IS_CALLABLE_HPP
#define CPPA_IS_CALLABLE_HPP
#include "cppa/util/conjunction.hpp"
#include "cppa/util/callable_trait.hpp"
namespace cppa { namespace util {
template<typename T>
struct is_callable {
template<typename C>
static bool _fun(C*, typename callable_trait<C>::result_type* = nullptr) {
return true;
}
template<typename C>
static bool _fun(C*, typename callable_trait<decltype(&C::operator())>::result_type* = nullptr) {
return true;
}
static void _fun(void*) { }
typedef decltype(_fun(static_cast<typename rm_ref<T>::type*>(nullptr)))
result_type;
public:
static constexpr bool value = std::is_same<bool, result_type>::value;
};
template<typename... Ts>
struct all_callable {
static constexpr bool value = conjunction<is_callable<Ts>...>::value;
};
} } // namespace cppa::util
#endif // CPPA_IS_CALLABLE_HPP
......@@ -35,6 +35,7 @@
#include "cppa/guard_expr.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/rebindable_reference.hpp"
namespace cppa { namespace util {
......@@ -44,12 +45,12 @@ struct purge_refs_impl {
};
template<typename T>
struct purge_refs_impl<ge_reference_wrapper<T> > {
struct purge_refs_impl<util::rebindable_reference<T> > {
typedef T type;
};
template<typename T>
struct purge_refs_impl<ge_mutable_reference_wrapper<T> > {
struct purge_refs_impl<util::rebindable_reference<const T> > {
typedef T type;
};
......@@ -58,6 +59,11 @@ struct purge_refs_impl<std::reference_wrapper<T> > {
typedef T type;
};
template<typename T>
struct purge_refs_impl<std::reference_wrapper<const T> > {
typedef T type;
};
/**
* @brief Removes references and reference wrappers.
*/
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_REBINDABLE_REFERENCE_HPP
#define CPPA_REBINDABLE_REFERENCE_HPP
#include "cppa/config.hpp"
#include "cppa/util/get_result_type.hpp"
namespace cppa { namespace util {
template<typename T>
struct call_helper {
typedef typename get_result_type<T>::type result_type;
template<typename... Ts>
result_type operator()(T& f, const Ts&... args) const {
return f(std::forward<Ts>(args)...);
}
};
template<>
struct call_helper<bool> {
typedef bool result_type;
bool operator()(const bool& value) const {
return value;
}
};
template<>
struct call_helper<const bool> : call_helper<bool> { };
/**
* @brief A reference wrapper similar to std::reference_wrapper, but
* allows rebinding the reference. Note that this wrapper can
* be 'dangling', because it provides a default constructor.
*/
template<typename T>
class rebindable_reference {
public:
rebindable_reference() : m_ptr(nullptr) { }
rebindable_reference(T& value) : m_ptr(&value) { }
template<typename U>
rebindable_reference(const rebindable_reference<U>& other) : m_ptr(other.ptr()) { }
inline bool bound() const {
return m_ptr != nullptr;
}
inline void rebind(T& value) {
m_ptr = &value;
}
template<typename U>
inline void rebind(const rebindable_reference<U>& other) {
m_ptr = other.ptr();
}
inline T* ptr() const {
CPPA_REQUIRE(bound());
return m_ptr;
}
inline T& get() const {
CPPA_REQUIRE(bound());
return *m_ptr;
}
inline operator T&() const {
CPPA_REQUIRE(bound());
return *m_ptr;
}
template<typename... Ts>
typename call_helper<T>::result_type operator()(Ts&&... args) {
call_helper<T> f;
return f(get(), std::forward<Ts>(args)...);
}
private:
T* m_ptr;
};
} } // namespace cppa::util
#endif // CPPA_REBINDABLE_REFERENCE_HPP
......@@ -54,8 +54,7 @@ namespace cppa { namespace util {
template<typename What, typename With, typename... IfStmt>
struct replace_type {
static constexpr bool do_replace = disjunction<IfStmt::value...>::value;
typedef typename detail::replace_type<do_replace, What, With>::type
type;
typedef typename detail::replace_type<do_replace, What, With>::type type;
};
} } // namespace cppa::util
......
......@@ -36,7 +36,6 @@
#include "cppa/util/at.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/type_pair.hpp"
#include "cppa/util/void_type.hpp"
......@@ -911,10 +910,10 @@ struct tl_is_zipped {
*/
template<class List, typename What = void_type>
struct tl_trim {
typedef typename util::if_else<
std::is_same<typename tl_back<List>::type, What>,
typedef typename std::conditional<
std::is_same<typename tl_back<List>::type,What>::value,
typename tl_trim<typename tl_pop_back<List>::type, What>::type,
util::wrapped<List>
List
>::type
type;
};
......
......@@ -35,7 +35,7 @@ namespace cppa { namespace util {
/**
* @ingroup MetaProgramming
* @brief A type wrapper as used in {@link cppa::util::if_else if_else}.
* @brief A simple type wrapper.
*/
template<typename T>
struct wrapped {
......
......@@ -48,12 +48,12 @@ auto context_switching_actor::init_timeout(const util::duration& tout) -> timeou
return {};
}
detail::recursive_queue_node* context_switching_actor::await_message(const timeout_type&) {
mailbox_element* context_switching_actor::await_message(const timeout_type&) {
// receives requested timeout message if timeout occured
return await_message();
}
detail::recursive_queue_node* context_switching_actor::await_message() {
mailbox_element* context_switching_actor::await_message() {
auto e = m_mailbox.try_pop();
while (e == nullptr) {
if (m_mailbox.can_fetch_more() == false) {
......
......@@ -138,7 +138,7 @@ resume_result event_based_actor::resume(util::fiber*, actor_ptr& next_job) {
}
else {
CPPA_LOG_DEBUG("try to invoke message: " << to_string(e->msg));
if (m_bhvr_stack.invoke(m_policy, this, e)) {
if (m_bhvr_stack.invoke(m_recv_policy, this, e)) {
CPPA_LOG_DEBUG_IF(m_chained_actor,
"set actor with ID "
<< m_chained_actor->id()
......
......@@ -182,9 +182,9 @@ class local_group_proxy : public local_group {
public:
template<typename... Args>
local_group_proxy(actor_ptr remote_broker, Args&&... args)
: super(false, forward<Args>(args)...) {
template<typename... Ts>
local_group_proxy(actor_ptr remote_broker, Ts&&... args)
: super(false, forward<Ts>(args)...) {
CPPA_REQUIRE(m_broker == nullptr);
CPPA_REQUIRE(remote_broker != nullptr);
CPPA_REQUIRE(remote_broker->is_proxy());
......
......@@ -33,8 +33,6 @@
#include <fstream>
#include <algorithm>
#include <execinfo.h> //DEL_ME
#ifndef CPPA_WINDOWS
#include <unistd.h>
#include <sys/types.h>
......
......@@ -28,13 +28,13 @@
\******************************************************************************/
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/mailbox_element.hpp"
namespace cppa { namespace detail {
namespace cppa {
recursive_queue_node::recursive_queue_node(const actor_ptr& sptr,
mailbox_element::mailbox_element(const actor_ptr& sptr,
any_tuple data,
message_id id)
: next(nullptr), marked(false), sender(sptr), msg(std::move(data)), mid(id) { }
} } // namespace cppa::detail
} // namespace cppa
......@@ -32,7 +32,7 @@
#include <typeinfo>
#include "cppa/detail/memory.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/mailbox_element.hpp"
using namespace std;
......@@ -64,8 +64,8 @@ cache_map& get_cache_map() {
cache = new cache_map;
pthread_setspecific(s_key, cache);
// insert default types
unique_ptr<memory_cache> tmp(new basic_memory_cache<recursive_queue_node>);
cache->insert(make_pair(&typeid(recursive_queue_node), move(tmp)));
unique_ptr<memory_cache> tmp(new basic_memory_cache<mailbox_element>);
cache->insert(make_pair(&typeid(mailbox_element), move(tmp)));
}
return *cache;
}
......
......@@ -40,7 +40,6 @@
#include "cppa/actor.hpp"
#include "cppa/match.hpp"
#include "cppa/config.hpp"
#include "cppa/either.hpp"
#include "cppa/logging.hpp"
#include "cppa/to_string.hpp"
#include "cppa/actor_proxy.hpp"
......
......@@ -80,6 +80,10 @@ scheduled_actor::~scheduled_actor() {
}
}
void scheduled_actor::run_detached() {
throw std::logic_error("scheduled_actor::run_detached called");
}
void scheduled_actor::cleanup(std::uint32_t reason) {
detail::sync_request_bouncer f{reason};
m_mailbox.close(f);
......
......@@ -157,8 +157,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
// setup & local variables
self.set(m_self.get());
bool done = false;
auto& queue = m_self->m_mailbox;
std::unique_ptr<detail::recursive_queue_node,detail::disposer> msg_ptr;
std::unique_ptr<mailbox_element,detail::disposer> msg_ptr;
auto tout = hrc::now();
std::multimap<decltype(tout),delayed_msg> messages;
// message handling rules
......@@ -188,7 +187,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
// loop
while (!done) {
while (!msg_ptr) {
if (messages.empty()) msg_ptr.reset(queue.pop());
if (messages.empty()) msg_ptr.reset(m_self->pop());
else {
tout = hrc::now();
// handle timeouts (send messages)
......@@ -200,7 +199,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
}
// wait for next message or next timeout
if (it != messages.end()) {
msg_ptr.reset(queue.try_pop(it->first));
msg_ptr.reset(m_self->try_pop(it->first));
}
}
}
......
......@@ -48,6 +48,7 @@ thread_mapped_actor::thread_mapped_actor() : super(std::function<void()>{}), m_i
thread_mapped_actor::thread_mapped_actor(std::function<void()> fun)
: super(std::move(fun)), m_initialized(false) { }
/*
auto thread_mapped_actor::init_timeout(const util::duration& rel_time) -> timeout_type {
auto result = std::chrono::high_resolution_clock::now();
result += rel_time;
......@@ -68,14 +69,7 @@ void thread_mapped_actor::sync_enqueue(const actor_ptr& sender,
f(sender, id);
}
}
detail::recursive_queue_node* thread_mapped_actor::await_message() {
return m_mailbox.pop();
}
detail::recursive_queue_node* thread_mapped_actor::await_message(const timeout_type& abs_time) {
return m_mailbox.try_pop(abs_time);
}
*/
bool thread_mapped_actor::initialized() const {
return m_initialized;
......
......@@ -204,8 +204,7 @@ actor_ptr thread_pool_scheduler::exec(spawn_options os, scheduled_actor_ptr p) {
bool is_hidden = has_hide_flag(os);
if (has_detach_flag(os)) {
exec_as_thread(is_hidden, p, [p] {
p->exec_behavior_stack();
p->on_exit();
p->run_detached();
});
return std::move(p);
}
......
......@@ -302,9 +302,24 @@ int main() {
);
CPPA_CHECKPOINT();
CPPA_PRINT("test mirror"); {
auto mirror = spawn<simple_mirror,monitored>();
send(mirror, "hello mirror");
receive (
on("hello mirror") >> CPPA_CHECKPOINT_CB(),
others() >> CPPA_UNEXPECTED_MSG_CB()
);
quit_actor(mirror, exit_reason::user_defined);
receive (
on(atom("DOWN"), exit_reason::user_defined) >> CPPA_CHECKPOINT_CB(),
others() >> CPPA_UNEXPECTED_MSG_CB()
);
await_all_others_done();
CPPA_CHECKPOINT();
}
CPPA_PRINT("test mirror");
CPPA_PRINT("test detached mirror"); {
auto mirror = spawn<simple_mirror,monitored+detached>();
send(mirror, "hello mirror");
receive (
on("hello mirror") >> CPPA_CHECKPOINT_CB(),
......@@ -317,6 +332,7 @@ int main() {
);
await_all_others_done();
CPPA_CHECKPOINT();
}
CPPA_PRINT("test echo actor");
auto mecho = spawn(echo_actor);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment