Commit 880c838d authored by neverlord's avatar neverlord

maintenance

parent c8cb7827
...@@ -22,7 +22,6 @@ cppa/detail/tuple_vals.hpp ...@@ -22,7 +22,6 @@ cppa/detail/tuple_vals.hpp
cppa/match.hpp cppa/match.hpp
cppa/detail/decorated_tuple.hpp cppa/detail/decorated_tuple.hpp
cppa/cow_ptr.hpp cppa/cow_ptr.hpp
cppa/util/detach.hpp
cppa/detail/ref_counted_impl.hpp cppa/detail/ref_counted_impl.hpp
cppa/intrusive_ptr.hpp cppa/intrusive_ptr.hpp
unit_testing/test__spawn.cpp unit_testing/test__spawn.cpp
...@@ -184,3 +183,7 @@ src/native_socket.cpp ...@@ -184,3 +183,7 @@ src/native_socket.cpp
cppa/detail/post_office.hpp cppa/detail/post_office.hpp
src/post_office.cpp src/post_office.cpp
cppa/detail/buffer.hpp cppa/detail/buffer.hpp
cppa/detail/task_scheduler.hpp
src/task_scheduler.cpp
cppa/detail/actor_count.hpp
src/actor_count.cpp
...@@ -15,6 +15,9 @@ namespace cppa { ...@@ -15,6 +15,9 @@ namespace cppa {
class attachable class attachable
{ {
attachable(const attachable&) = delete;
attachable& operator=(const attachable&) = delete;
protected: protected:
attachable() = default; attachable() = default;
......
...@@ -35,7 +35,7 @@ class context : public actor ...@@ -35,7 +35,7 @@ class context : public actor
* *
* Calls <code>mailbox().enqueue(msg)</code>. * Calls <code>mailbox().enqueue(msg)</code>.
*/ */
virtual void enqueue /*[[override]]*/ (const message& msg); virtual void enqueue(const message& msg) /*override*/;
void trap_exit(bool new_value); void trap_exit(bool new_value);
......
...@@ -2,73 +2,109 @@ ...@@ -2,73 +2,109 @@
#define COW_PTR_HPP #define COW_PTR_HPP
#include <stdexcept> #include <stdexcept>
#include "cppa/util/detach.hpp" #include <type_traits>
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/util/is_copyable.hpp"
#include "cppa/util/has_copy_member_fun.hpp"
namespace cppa { namespace detail {
template<typename T>
constexpr int copy_method()
{
return util::has_copy_member_fun<T>::value
? 2
: (util::is_copyable<T>::value ? 1 : 0);
}
// is_copyable
template<typename T>
T* copy_of(const T* what, std::integral_constant<int, 1>)
{
return new T(*what);
}
// has_copy_member_fun
template<typename T>
T* copy_of(const T* what, std::integral_constant<int, 2>)
{
return what->copy();
}
} } // namespace cppa::detail
namespace cppa { namespace cppa {
template<typename T> template<typename T>
class cow_ptr class cow_ptr
{ {
intrusive_ptr<T> m_ptr; static_assert(detail::copy_method<T>() != 0, "T is not copyable");
T* do_detach() typedef std::integral_constant<int, detail::copy_method<T>()> copy_of_token;
{
T* ptr = m_ptr.get(); intrusive_ptr<T> m_ptr;
if (!ptr->unique())
{ T* detach_ptr()
T* new_ptr = util::detach(ptr); {
cow_ptr tmp(new_ptr); T* ptr = m_ptr.get();
swap(tmp); if (!ptr->unique())
return new_ptr; {
} T* new_ptr = detail::copy_of(ptr, copy_of_token());
return ptr; cow_ptr tmp(new_ptr);
} swap(tmp);
return new_ptr;
}
return ptr;
}
public: public:
template<typename Y> template<typename Y>
cow_ptr(Y* raw_ptr) : m_ptr(raw_ptr) { } cow_ptr(Y* raw_ptr) : m_ptr(raw_ptr) { }
cow_ptr(T* raw_ptr) : m_ptr(raw_ptr) { }
cow_ptr(T* raw_ptr) : m_ptr(raw_ptr) { } cow_ptr(const cow_ptr& other) : m_ptr(other.m_ptr) { }
cow_ptr(const cow_ptr& other) : m_ptr(other.m_ptr) { } template<typename Y>
cow_ptr(const cow_ptr<Y>& other) : m_ptr(const_cast<Y*>(other.get())) { }
template<typename Y> inline void swap(cow_ptr& other)
cow_ptr(const cow_ptr<Y>& other) : m_ptr(const_cast<Y*>(other.get())) { } {
m_ptr.swap(other.m_ptr);
}
const T* get() const { return m_ptr.get(); } cow_ptr& operator=(const cow_ptr& other)
{
cow_ptr tmp(other);
swap(tmp);
return *this;
}
inline void swap(cow_ptr& other) template<typename Y>
{ cow_ptr& operator=(const cow_ptr<Y>& other)
m_ptr.swap(other.m_ptr); {
} cow_ptr tmp(other);
swap(tmp);
return *this;
}
cow_ptr& operator=(const cow_ptr& other) inline T* get() { return detach_ptr(); }
{
cow_ptr tmp(other);
swap(tmp);
return *this;
}
template<typename Y> inline const T* get() const { return m_ptr.get(); }
cow_ptr& operator=(const cow_ptr<Y>& other)
{
cow_ptr tmp(other);
swap(tmp);
return *this;
}
T* operator->() { return do_detach(); } inline T* operator->() { return detach_ptr(); }
T& operator*() { return do_detach(); } inline T& operator*() { return detach_ptr(); }
const T* operator->() const { return m_ptr.get(); } inline const T* operator->() const { return m_ptr.get(); }
const T& operator*() const { return *m_ptr.get(); } inline const T& operator*() const { return *m_ptr.get(); }
explicit operator bool() const { return m_ptr.get() != nullptr; } inline explicit operator bool() const { return static_cast<bool>(m_ptr); }
}; };
......
...@@ -140,7 +140,7 @@ class abstract_actor /*[[base_check]]*/ : public Base ...@@ -140,7 +140,7 @@ class abstract_actor /*[[base_check]]*/ : public Base
public: public:
bool attach /*[[override]]*/ (attachable* ptr) bool attach(attachable* ptr) /*override*/
{ {
if (ptr == nullptr) if (ptr == nullptr)
{ {
...@@ -166,7 +166,7 @@ class abstract_actor /*[[base_check]]*/ : public Base ...@@ -166,7 +166,7 @@ class abstract_actor /*[[base_check]]*/ : public Base
} }
} }
void detach /*[[override]]*/ (const attachable::token& what) void detach(const attachable::token& what) /*override*/
{ {
attachable_ptr uptr; attachable_ptr uptr;
// lifetime scope of guard // lifetime scope of guard
...@@ -186,17 +186,17 @@ class abstract_actor /*[[base_check]]*/ : public Base ...@@ -186,17 +186,17 @@ class abstract_actor /*[[base_check]]*/ : public Base
// uptr will be destroyed here, without locked mutex // uptr will be destroyed here, without locked mutex
} }
void link_to /*[[override]]*/ (intrusive_ptr<actor>& other) void link_to(intrusive_ptr<actor>& other) /*override*/
{ {
(void) link_to_impl(other); (void) link_to_impl(other);
} }
void unlink_from /*[[override]]*/ (intrusive_ptr<actor>& other) void unlink_from(intrusive_ptr<actor>& other) /*override*/
{ {
(void) unlink_from_impl(other); (void) unlink_from_impl(other);
} }
bool remove_backlink /*[[override]]*/ (intrusive_ptr<actor>& other) bool remove_backlink(intrusive_ptr<actor>& other) /*override*/
{ {
if (other && other != this) if (other && other != this)
{ {
...@@ -206,7 +206,7 @@ class abstract_actor /*[[base_check]]*/ : public Base ...@@ -206,7 +206,7 @@ class abstract_actor /*[[base_check]]*/ : public Base
return false; return false;
} }
bool establish_backlink /*[[override]]*/ (intrusive_ptr<actor>& other) bool establish_backlink(intrusive_ptr<actor>& other) /*override*/
{ {
bool result = false; bool result = false;
std::uint32_t reason = exit_reason::not_exited; std::uint32_t reason = exit_reason::not_exited;
......
#ifndef ACTOR_COUNT_HPP
#define ACTOR_COUNT_HPP
namespace cppa { namespace detail {
void inc_actor_count();
void dec_actor_count();
// @pre expected <= 1
void actor_count_wait_until(size_t expected);
} } // namespace cppa::detail
#endif // ACTOR_COUNT_HPP
...@@ -28,17 +28,17 @@ class blocking_message_queue : public message_queue ...@@ -28,17 +28,17 @@ class blocking_message_queue : public message_queue
virtual void trap_exit(bool new_value); virtual void trap_exit(bool new_value);
virtual void enqueue /*[[override]]*/ (const message& msg); virtual void enqueue(const message& msg) /*override*/;
virtual const message& dequeue /*[[override]]*/ (); virtual const message& dequeue() /*override*/;
virtual void dequeue /*[[override]]*/ (invoke_rules& rules); virtual void dequeue(invoke_rules& rules) /*override*/;
virtual bool try_dequeue /*[[override]]*/ (message& msg); virtual bool try_dequeue(message& msg) /*override*/;
virtual bool try_dequeue /*[[override]]*/ (invoke_rules& rules); virtual bool try_dequeue(invoke_rules& rules) /*override*/;
virtual const message& last_dequeued /*[[override]]*/ (); virtual const message& last_dequeued() /*override*/;
}; };
......
...@@ -28,12 +28,12 @@ class converted_thread_context : public abstract_actor<context> ...@@ -28,12 +28,12 @@ class converted_thread_context : public abstract_actor<context>
public: public:
message_queue& mailbox /*[[override]]*/ (); message_queue& mailbox() /*override*/;
// called if the converted thread finished execution // called if the converted thread finished execution
void cleanup(std::uint32_t reason = exit_reason::normal); void cleanup(std::uint32_t reason = exit_reason::normal);
void quit /*[[override]]*/ (std::uint32_t reason); void quit(std::uint32_t reason) /*override*/;
}; };
......
...@@ -35,7 +35,7 @@ class list_member : public util::abstract_uniform_type_info<List> ...@@ -35,7 +35,7 @@ class list_member : public util::abstract_uniform_type_info<List>
for (size_t i = 0; i < ls_size; ++i) for (size_t i = 0; i < ls_size; ++i)
{ {
primitive_variant val = d->read_value(vptype); primitive_variant val = d->read_value(vptype);
ls.push_back(std::move(get<value_type>(val))); ls.push_back(std::move(get_ref<value_type>(val)));
} }
d->end_sequence(); d->end_sequence();
} }
......
#ifndef TASK_SCHEDULER_HPP
#define TASK_SCHEDULER_HPP
#include "cppa/scheduler.hpp"
namespace cppa { namespace detail {
class task_scheduler : public scheduler
{
public:
void await_others_done();
void register_converted_context(context*);
//void unregister_converted_context(context*);
actor_ptr spawn(actor_behavior*, scheduling_hint);
attachable* register_hidden_context();
};
} } // namespace cppa::detail
#endif // TASK_SCHEDULER_HPP
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
namespace cppa { namespace cppa {
/**
* @brief A multicast group.
*/
class group : public channel class group : public channel
{ {
...@@ -28,6 +31,7 @@ class group : public channel ...@@ -28,6 +31,7 @@ class group : public channel
class unsubscriber; class unsubscriber;
// needs access to unsubscribe()
friend class unsubscriber; friend class unsubscriber;
// unsubscribes its channel from the group on destruction // unsubscribes its channel from the group on destruction
...@@ -39,15 +43,11 @@ class group : public channel ...@@ -39,15 +43,11 @@ class group : public channel
channel_ptr m_self; channel_ptr m_self;
intrusive_ptr<group> m_group; intrusive_ptr<group> m_group;
unsubscriber() = delete;
unsubscriber(const unsubscriber&) = delete;
unsubscriber& operator=(const unsubscriber&) = delete;
public: public:
unsubscriber(const channel_ptr& s, const intrusive_ptr<group>& g); unsubscriber(const channel_ptr& s, const intrusive_ptr<group>& g);
// matches on group // matches on m_group
bool matches(const attachable::token& what); bool matches(const attachable::token& what);
virtual ~unsubscriber(); virtual ~unsubscriber();
...@@ -56,25 +56,69 @@ class group : public channel ...@@ -56,25 +56,69 @@ class group : public channel
typedef std::unique_ptr<unsubscriber> subscription; typedef std::unique_ptr<unsubscriber> subscription;
/**
* @brief Module interface.
*/
class module class module
{ {
std::string m_name;
protected:
module(std::string&& module_name);
module(const std::string& module_name);
public: public:
virtual const std::string& name() = 0; /**
* @brief Get the name of this module implementation.
* @return The name of this module implementation.
* @threadsafe
*/
const std::string& name();
/**
* @brief Get a pointer to the group associated with
* the name @p group_name.
* @threadsafe
*/
virtual intrusive_ptr<group> get(const std::string& group_name) = 0; virtual intrusive_ptr<group> get(const std::string& group_name) = 0;
}; };
/**
* @brief A string representation of the group identifier.
* @return The group identifier as string (e.g. "224.0.0.1" for IPv4
* multicast or a user-defined string for local groups).
*/
const std::string& identifier() const; const std::string& identifier() const;
/**
* @brief The name of the module.
* @return The module name of this group (e.g. "local").
*/
const std::string& module_name() const; const std::string& module_name() const;
/**
* @brief Subscribe @p who to this group.
* @return A {@link subscription} object that unsubscribes @p who
* if the lifetime of @p who ends.
*/
virtual subscription subscribe(const channel_ptr& who) = 0; virtual subscription subscribe(const channel_ptr& who) = 0;
/**
* @brief Get a pointer to the group associated with
* @p group_identifier from the module @p module_name.
* @threadsafe
*/
static intrusive_ptr<group> get(const std::string& module_name, static intrusive_ptr<group> get(const std::string& module_name,
const std::string& group_name); const std::string& group_identifier);
/**
* @brief Add a new group module to the libcppa group management.
* @threadsafe
*/
static void add_module(module*); static void add_module(module*);
}; };
......
...@@ -61,9 +61,9 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, const T*>, ...@@ -61,9 +61,9 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, const T*>,
} }
} }
T* get() { return m_ptr; } inline T* get() { return m_ptr; }
const T* get() const { return m_ptr; } inline const T* get() const { return m_ptr; }
T* take() T* take()
{ {
...@@ -123,13 +123,13 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, const T*>, ...@@ -123,13 +123,13 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T>, const T*>,
return *this; return *this;
} }
T* operator->() { return m_ptr; } inline T* operator->() { return m_ptr; }
T& operator*() { return *m_ptr; } inline T& operator*() { return *m_ptr; }
const T* operator->() const { return m_ptr; } inline const T* operator->() const { return m_ptr; }
const T& operator*() const { return *m_ptr; } inline const T& operator*() const { return *m_ptr; }
inline explicit operator bool() const { return m_ptr != nullptr; } inline explicit operator bool() const { return m_ptr != nullptr; }
...@@ -166,9 +166,9 @@ bool operator==(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs) ...@@ -166,9 +166,9 @@ bool operator==(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs)
} }
template<typename X, typename Y> template<typename X, typename Y>
bool operator!=(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs) inline bool operator!=(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs)
{ {
return lhs.get() != rhs.get(); return !(lhs == rhs);
} }
} // namespace cppa } // namespace cppa
......
...@@ -244,6 +244,20 @@ const typename detail::ptype_to_type<PT>::type& get(const primitive_variant& pv) ...@@ -244,6 +244,20 @@ const typename detail::ptype_to_type<PT>::type& get(const primitive_variant& pv)
return pv.get_as<PT>(); return pv.get_as<PT>();
} }
template<typename T>
T& get_ref(primitive_variant& pv)
{
static const primitive_type ptype = detail::type_to_ptype<T>::ptype;
return pv.get_as<ptype>();
}
template<primitive_type PT>
typename detail::ptype_to_type<PT>::type& get_ref(primitive_variant& pv)
{
static_assert(PT != pt_null, "PT == pt_null");
return pv.get_as<PT>();
}
template<typename T> template<typename T>
typename util::enable_if<util::is_primitive<T>, bool>::type typename util::enable_if<util::is_primitive<T>, bool>::type
operator==(const T& lhs, const primitive_variant& rhs) operator==(const T& lhs, const primitive_variant& rhs)
......
...@@ -39,6 +39,7 @@ class scheduler ...@@ -39,6 +39,7 @@ class scheduler
/** /**
* @brief Informs the scheduler about a converted context * @brief Informs the scheduler about a converted context
* (a thread that acts as actor). * (a thread that acts as actor).
* @note Calls <tt>what->attach(...)</tt>.
*/ */
virtual void register_converted_context(context* what) = 0; virtual void register_converted_context(context* what) = 0;
...@@ -61,7 +62,7 @@ class scheduler ...@@ -61,7 +62,7 @@ class scheduler
/** /**
* @brief Gets the actual used scheduler implementation. * @brief Gets the actual used scheduler implementation.
* @return The active scheduler or @c nullptr. * @return The active scheduler (default constructed).
*/ */
scheduler* get_scheduler(); scheduler* get_scheduler();
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include "cppa/util/compare_tuples.hpp" #include "cppa/util/compare_tuples.hpp"
#include "cppa/util/concat_type_lists.hpp" #include "cppa/util/concat_type_lists.hpp"
#include "cppa/util/conjunction.hpp" #include "cppa/util/conjunction.hpp"
#include "cppa/util/detach.hpp"
#include "cppa/util/disjunction.hpp" #include "cppa/util/disjunction.hpp"
#include "cppa/util/enable_if.hpp" #include "cppa/util/enable_if.hpp"
#include "cppa/util/eval_first_n.hpp" #include "cppa/util/eval_first_n.hpp"
......
#ifndef DETACH_HPP
#define DETACH_HPP
#include "cppa/util/is_copyable.hpp"
#include "cppa/util/has_copy_member_fun.hpp"
namespace cppa { namespace detail {
template<bool IsCopyable, bool HasCpyMemFun>
struct detach_;
template<bool HasCpyMemFun>
struct detach_<true, HasCpyMemFun>
{
template<typename T>
inline static T* cpy(const T* what)
{
return new T(*what);
}
};
template<>
struct detach_<false, true>
{
template<typename T>
inline static T* cpy(const T* what)
{
return what->copy();
}
};
} } // namespace cppa::detail
namespace cppa { namespace util {
template<typename T>
inline T* detach(const T* what)
{
return detail::detach_<is_copyable<T>::value,
has_copy_member_fun<T>::value>::cpy(what);
}
} } // namespace cppa::util
#endif // DETACH_HPP
...@@ -43,13 +43,8 @@ class is_copyable_<true, T> ...@@ -43,13 +43,8 @@ class is_copyable_<true, T>
namespace cppa { namespace util { namespace cppa { namespace util {
template<typename T> template<typename T>
struct is_copyable struct is_copyable : std::integral_constant<bool, detail::is_copyable_<std::is_abstract<T>::value, T>::value>
{ {
public:
static const bool value = detail::is_copyable_<std::is_abstract<T>::value, T>::value;
}; };
} } // namespace cppa::util } } // namespace cppa::util
......
#include <limits>
#include <atomic>
#include <stdexcept>
#include <boost/thread.hpp>
#include "cppa/detail/actor_count.hpp"
namespace {
boost::mutex s_ra_mtx;
boost::condition_variable s_ra_cv;
std::atomic<size_t> s_running_actors(0);
typedef boost::unique_lock<boost::mutex> guard_type;
} // namespace <anonymous>
namespace cppa { namespace detail {
void inc_actor_count()
{
++s_running_actors;
}
void dec_actor_count()
{
size_t new_val = --s_running_actors;
if (new_val == std::numeric_limits<size_t>::max())
{
throw std::underflow_error("dec_actor_count()");
}
else if (new_val <= 1)
{
guard_type guard(s_ra_mtx);
s_ra_cv.notify_all();
}
}
void actor_count_wait_until(size_t expected)
{
guard_type lock(s_ra_mtx);
while (s_running_actors.load() != expected)
{
s_ra_cv.wait(lock);
}
}
} } // namespace cppa::detail
...@@ -18,19 +18,20 @@ namespace { ...@@ -18,19 +18,20 @@ namespace {
typedef std::map< std::string, std::unique_ptr<group::module> > modules_map; typedef std::map< std::string, std::unique_ptr<group::module> > modules_map;
typedef std::lock_guard<util::shared_spinlock> exclusive_guard; typedef util::shared_spinlock shared_mutex_type;
typedef util::shared_lock_guard<util::shared_spinlock> shared_guard; typedef std::lock_guard<shared_mutex_type> exclusive_guard;
typedef util::upgrade_lock_guard<util::shared_spinlock> upgrade_guard; typedef util::shared_lock_guard<shared_mutex_type> shared_guard;
typedef util::upgrade_lock_guard<shared_mutex_type> upgrade_guard;
std::mutex s_mtx;
modules_map s_mmap; modules_map s_mmap;
std::mutex s_mmap_mtx;
class local_group : public group class local_group : public group
{ {
friend class local_group_module; friend class local_group_module;
util::shared_spinlock m_mtx; shared_mutex_type m_shared_mtx;
std::set<channel_ptr> m_subscribers; std::set<channel_ptr> m_subscribers;
// allow access to local_group_module only // allow access to local_group_module only
...@@ -42,7 +43,7 @@ class local_group : public group ...@@ -42,7 +43,7 @@ class local_group : public group
virtual void enqueue(const message& msg) virtual void enqueue(const message& msg)
{ {
shared_guard guard(m_mtx); shared_guard guard(m_shared_mtx);
for (auto i = m_subscribers.begin(); i != m_subscribers.end(); ++i) for (auto i = m_subscribers.begin(); i != m_subscribers.end(); ++i)
{ {
const_cast<channel_ptr&>(*i)->enqueue(msg); const_cast<channel_ptr&>(*i)->enqueue(msg);
...@@ -52,7 +53,7 @@ class local_group : public group ...@@ -52,7 +53,7 @@ class local_group : public group
virtual group::subscription subscribe(const channel_ptr& who) virtual group::subscription subscribe(const channel_ptr& who)
{ {
group::subscription result; group::subscription result;
exclusive_guard guard(m_mtx); exclusive_guard guard(m_shared_mtx);
if (m_subscribers.insert(who).second) if (m_subscribers.insert(who).second)
{ {
result.reset(new group::unsubscriber(who, this)); result.reset(new group::unsubscriber(who, this));
...@@ -62,7 +63,7 @@ class local_group : public group ...@@ -62,7 +63,7 @@ class local_group : public group
virtual void unsubscribe(const channel_ptr& who) virtual void unsubscribe(const channel_ptr& who)
{ {
exclusive_guard guard(m_mtx); exclusive_guard guard(m_shared_mtx);
m_subscribers.erase(who); m_subscribers.erase(who);
} }
...@@ -71,20 +72,16 @@ class local_group : public group ...@@ -71,20 +72,16 @@ class local_group : public group
class local_group_module : public group::module class local_group_module : public group::module
{ {
std::string m_name; typedef group::module super;
util::shared_spinlock m_mtx; util::shared_spinlock m_mtx;
std::map<std::string, group_ptr> m_instances; std::map<std::string, group_ptr> m_instances;
public: public:
local_group_module() : m_name("local") local_group_module() : super("local")
{
}
const std::string& name()
{ {
return m_name;
} }
group_ptr get(const std::string& group_name) group_ptr get(const std::string& group_name)
...@@ -110,6 +107,7 @@ class local_group_module : public group::module ...@@ -110,6 +107,7 @@ class local_group_module : public group::module
}; };
// @pre: s_mmap_mtx is locked
modules_map& mmap() modules_map& mmap()
{ {
if (s_mmap.empty()) if (s_mmap.empty())
...@@ -128,7 +126,7 @@ intrusive_ptr<group> group::get(const std::string& module_name, ...@@ -128,7 +126,7 @@ intrusive_ptr<group> group::get(const std::string& module_name,
{ {
// lifetime scope of guard // lifetime scope of guard
{ {
std::lock_guard<std::mutex> guard(s_mtx); std::lock_guard<std::mutex> guard(s_mmap_mtx);
auto& mmref = mmap(); auto& mmref = mmap();
auto i = mmref.find(module_name); auto i = mmref.find(module_name);
if (i != mmref.end()) if (i != mmref.end())
...@@ -148,7 +146,7 @@ void group::add_module(group::module* ptr) ...@@ -148,7 +146,7 @@ void group::add_module(group::module* ptr)
std::unique_ptr<group::module> mptr(ptr); std::unique_ptr<group::module> mptr(ptr);
// lifetime scope of guard // lifetime scope of guard
{ {
std::lock_guard<std::mutex> guard(s_mtx); std::lock_guard<std::mutex> guard(s_mmap_mtx);
if (mmap().insert(std::make_pair(mname, std::move(mptr))).second) if (mmap().insert(std::make_pair(mname, std::move(mptr))).second)
{ {
return; // success; don't throw exception return; // success; don't throw exception
...@@ -172,6 +170,19 @@ group::unsubscriber::~unsubscriber() ...@@ -172,6 +170,19 @@ group::unsubscriber::~unsubscriber()
if (m_group) m_group->unsubscribe(m_self); if (m_group) m_group->unsubscribe(m_self);
} }
group::module::module(const std::string& name) : m_name(name)
{
}
group::module::module(std::string&& name) : m_name(std::move(name))
{
}
const std::string& group::module::name()
{
return m_name;
}
bool group::unsubscriber::matches(const attachable::token& what) bool group::unsubscriber::matches(const attachable::token& what)
{ {
if (what.subtype == typeid(group::unsubscriber)) if (what.subtype == typeid(group::unsubscriber))
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "cppa/attachable.hpp" #include "cppa/attachable.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/invoke_rules.hpp"
#include "cppa/actor_behavior.hpp" #include "cppa/actor_behavior.hpp"
#include "cppa/detail/actor_count.hpp"
#include "cppa/detail/mock_scheduler.hpp" #include "cppa/detail/mock_scheduler.hpp"
#include "cppa/detail/to_uniform_name.hpp" #include "cppa/detail/to_uniform_name.hpp"
#include "cppa/detail/converted_thread_context.hpp" #include "cppa/detail/converted_thread_context.hpp"
...@@ -21,26 +22,6 @@ using std::endl; ...@@ -21,26 +22,6 @@ using std::endl;
namespace { namespace {
boost::mutex s_ra_mtx;
boost::condition_variable s_ra_cv;
std::atomic<int> s_running_actors(0);
typedef boost::unique_lock<boost::mutex> guard_type;
void inc_actor_count()
{
++s_running_actors;
}
void dec_actor_count()
{
if (--s_running_actors <= 1)
{
guard_type guard(s_ra_mtx);
s_ra_cv.notify_all();
}
}
void run_actor(cppa::intrusive_ptr<cppa::context> m_self, void run_actor(cppa::intrusive_ptr<cppa::context> m_self,
cppa::actor_behavior* behavior) cppa::actor_behavior* behavior)
{ {
...@@ -53,14 +34,14 @@ void run_actor(cppa::intrusive_ptr<cppa::context> m_self, ...@@ -53,14 +34,14 @@ void run_actor(cppa::intrusive_ptr<cppa::context> m_self,
catch (...) { } catch (...) { }
delete behavior; delete behavior;
} }
dec_actor_count(); cppa::detail::dec_actor_count();
} }
struct exit_observer : cppa::attachable struct exit_observer : cppa::attachable
{ {
~exit_observer() ~exit_observer()
{ {
dec_actor_count(); cppa::detail::dec_actor_count();
} }
}; };
...@@ -93,12 +74,7 @@ attachable* mock_scheduler::register_hidden_context() ...@@ -93,12 +74,7 @@ attachable* mock_scheduler::register_hidden_context()
void mock_scheduler::await_others_done() void mock_scheduler::await_others_done()
{ {
auto expected = (unchecked_self() == nullptr) ? 0 : 1; actor_count_wait_until((unchecked_self() == nullptr) ? 0 : 1);
guard_type lock(s_ra_mtx);
while (s_running_actors.load() != expected)
{
s_ra_cv.wait(lock);
}
} }
} } // namespace detail } } // namespace detail
This diff is collapsed.
#include "cppa/detail/task_scheduler.hpp"
namespace cppa { namespace detail {
void task_scheduler::await_others_done()
{
}
void task_scheduler::register_converted_context(context*)
{
}
actor_ptr task_scheduler::spawn(actor_behavior*, scheduling_hint)
{
return nullptr;
}
attachable* task_scheduler::register_hidden_context()
{
return nullptr;
}
} } // namespace cppa::detail
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