Commit 8a7b70c9 authored by Dominik Charousset's avatar Dominik Charousset

refactored ref_counted: prohibit destructor calls and enforce use of...

refactored ref_counted: prohibit destructor calls and enforce use of request_deletion member function
parent e1a21a76
...@@ -54,13 +54,15 @@ class channel : public ref_counted { ...@@ -54,13 +54,15 @@ class channel : public ref_counted {
public: public:
virtual ~channel();
/** /**
* @brief Enqueues @p msg to the list of received messages. * @brief Enqueues @p msg to the list of received messages.
*/ */
virtual void enqueue(actor* sender, any_tuple msg) = 0; virtual void enqueue(actor* sender, any_tuple msg) = 0;
protected:
virtual ~channel();
private: private:
// channel is a sealed class and the only // channel is a sealed class and the only
......
...@@ -84,9 +84,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >, ...@@ -84,9 +84,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >,
set_ptr(from.convert()); set_ptr(from.convert());
} }
~intrusive_ptr() { ~intrusive_ptr() { if (m_ptr) m_ptr->deref(); }
if (m_ptr && !m_ptr->deref()) delete m_ptr;
}
inline void swap(intrusive_ptr& other) { inline void swap(intrusive_ptr& other) {
std::swap(m_ptr, other.m_ptr); std::swap(m_ptr, other.m_ptr);
...@@ -110,7 +108,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >, ...@@ -110,7 +108,7 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >,
} }
void reset(pointer new_value = nullptr) { void reset(pointer new_value = nullptr) {
if (m_ptr && !m_ptr->deref()) delete m_ptr; if (m_ptr) m_ptr->deref();
set_ptr(new_value); set_ptr(new_value);
} }
......
...@@ -56,20 +56,27 @@ class ref_counted { ...@@ -56,20 +56,27 @@ class ref_counted {
inline void ref() { ++m_rc; } inline void ref() { ++m_rc; }
/** /**
* @brief Decreases reference cound by one. * @brief Decreases reference count by one and calls
* @returns @p true if there are still references to this object * @p request_deletion when it drops to zero.
* (reference count > 0); otherwise @p false.
*/ */
inline bool deref() { return --m_rc > 0; } inline void deref() { if (--m_rc == 0) request_deletion(); }
/** /**
* @brief Queries if there is exactly one reference. * @brief Queries whether there is exactly one reference.
* @returns @p true if reference count is one; otherwise @p false.
*/ */
inline bool unique() { return m_rc == 1; } inline bool unique() { return m_rc == 1; }
protected:
virtual ~ref_counted(); virtual ~ref_counted();
/**
* @brief Default implementations calls <tt>delete this</tt>, but can
* be overriden in case deletion depends on more than the
* reference count alone.
*/
virtual void request_deletion();
private: private:
std::atomic<size_t> m_rc; std::atomic<size_t> m_rc;
......
...@@ -35,4 +35,6 @@ namespace cppa { ...@@ -35,4 +35,6 @@ namespace cppa {
ref_counted::~ref_counted() { } ref_counted::~ref_counted() { }
void ref_counted::request_deletion() { delete this; }
} // namespace cppa } // namespace cppa
...@@ -115,7 +115,7 @@ void self_type::cleanup_fun(cppa::local_actor* what) { ...@@ -115,7 +115,7 @@ void self_type::cleanup_fun(cppa::local_actor* what) {
// make sure "unspawned" actors quit properly // make sure "unspawned" actors quit properly
ptr->cleanup(cppa::exit_reason::normal); ptr->cleanup(cppa::exit_reason::normal);
} }
if (what->deref() == false) delete what; what->deref();
} }
} }
......
...@@ -107,7 +107,7 @@ void singleton_manager::shutdown() { ...@@ -107,7 +107,7 @@ void singleton_manager::shutdown() {
delete s_group_manager.load(); delete s_group_manager.load();
s_group_manager = nullptr; s_group_manager = nullptr;
auto et = s_empty_tuple.load(); auto et = s_empty_tuple.load();
if (et && !et->deref()) delete et; if (et) et->deref();
s_empty_tuple = nullptr; s_empty_tuple = nullptr;
delete s_uniform_type_info_map.load(); delete s_uniform_type_info_map.load();
s_uniform_type_info_map = nullptr; s_uniform_type_info_map = nullptr;
......
...@@ -138,7 +138,7 @@ struct thread_pool_scheduler::worker { ...@@ -138,7 +138,7 @@ struct thread_pool_scheduler::worker {
case resume_result::actor_done: { case resume_result::actor_done: {
auto pending = fetch_pending(); auto pending = fetch_pending();
bool hidden = job->is_hidden(); bool hidden = job->is_hidden();
if (!job->deref()) delete job; job->deref();
std::atomic_thread_fence(std::memory_order_seq_cst); std::atomic_thread_fence(std::memory_order_seq_cst);
if (!hidden) dec_actor_count(); if (!hidden) dec_actor_count();
job = pending; job = pending;
...@@ -189,7 +189,7 @@ void thread_pool_scheduler::stop() { ...@@ -189,7 +189,7 @@ void thread_pool_scheduler::stop() {
while (ptr != nullptr) { while (ptr != nullptr) {
if (ptr != &m_dummy) { if (ptr != &m_dummy) {
bool hidden = ptr->is_hidden(); bool hidden = ptr->is_hidden();
if (!ptr->deref()) delete ptr; ptr->deref();
std::atomic_thread_fence(std::memory_order_seq_cst); std::atomic_thread_fence(std::memory_order_seq_cst);
if (!hidden) dec_actor_count(); if (!hidden) dec_actor_count();
} }
......
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