Commit 1b744245 authored by Dominik Charousset's avatar Dominik Charousset

Create actors with ref count 1, close #176

parent b76ec4b9
...@@ -227,12 +227,12 @@ class abstract_actor : public abstract_channel { ...@@ -227,12 +227,12 @@ class abstract_actor : public abstract_channel {
/** /**
* Creates a non-proxy instance. * Creates a non-proxy instance.
*/ */
abstract_actor(); abstract_actor(size_t initial_ref_count = 0);
/** /**
* Creates a proxy instance for a proxy running on `nid`. * Creates a proxy instance for a proxy running on `nid`.
*/ */
abstract_actor(actor_id aid, node_id nid); abstract_actor(actor_id aid, node_id nid, size_t initial_ref_count = 0);
virtual bool link_impl(linking_operation op, const actor_addr& other); virtual bool link_impl(linking_operation op, const actor_addr& other);
......
...@@ -56,9 +56,9 @@ class abstract_channel : public ref_counted { ...@@ -56,9 +56,9 @@ class abstract_channel : public ref_counted {
protected: protected:
abstract_channel(); abstract_channel(size_t initial_ref_count = 0);
abstract_channel(node_id nid); abstract_channel(node_id nid, size_t initial_ref_count = 0);
private: private:
......
...@@ -46,13 +46,21 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>>, ...@@ -46,13 +46,21 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>>,
using reference = T& ; using reference = T& ;
using const_reference = const T&; using const_reference = const T&;
constexpr intrusive_ptr() : m_ptr(nullptr) { } constexpr intrusive_ptr() : m_ptr(nullptr) {
// nop
}
intrusive_ptr(pointer raw_ptr) { set_ptr(raw_ptr); } intrusive_ptr(pointer raw_ptr, bool add_ref = true) {
set_ptr(raw_ptr, add_ref);
}
intrusive_ptr(intrusive_ptr&& other) : m_ptr(other.release()) { } intrusive_ptr(intrusive_ptr&& other) : m_ptr(other.release()) {
// nop
}
intrusive_ptr(const intrusive_ptr& other) { set_ptr(other.get()); } intrusive_ptr(const intrusive_ptr& other) {
set_ptr(other.get(), true);
}
template <class Y> template <class Y>
intrusive_ptr(intrusive_ptr<Y> other) : m_ptr(other.release()) { intrusive_ptr(intrusive_ptr<Y> other) : m_ptr(other.release()) {
...@@ -60,7 +68,9 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>>, ...@@ -60,7 +68,9 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>>,
"Y* is not assignable to T*"); "Y* is not assignable to T*");
} }
~intrusive_ptr() { if (m_ptr) m_ptr->deref(); } ~intrusive_ptr() {
if (m_ptr) m_ptr->deref();
}
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);
...@@ -76,17 +86,11 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>>, ...@@ -76,17 +86,11 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>>,
return result; return result;
} }
/** void reset(pointer new_value = nullptr, bool add_ref = true) {
* Sets this pointer to `ptr` without modifying reference count. if (m_ptr) {
*/ m_ptr->deref();
void adopt(pointer ptr) { }
reset(); set_ptr(new_value, add_ref);
m_ptr = ptr;
}
void reset(pointer new_value = nullptr) {
if (m_ptr) m_ptr->deref();
set_ptr(new_value);
} }
template <class... Ts> template <class... Ts>
...@@ -150,11 +154,12 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>>, ...@@ -150,11 +154,12 @@ class intrusive_ptr : detail::comparable<intrusive_ptr<T>>,
pointer m_ptr; pointer m_ptr;
inline void set_ptr(pointer raw_ptr) { inline void set_ptr(pointer raw_ptr, bool add_ref) {
m_ptr = raw_ptr; m_ptr = raw_ptr;
if (raw_ptr) raw_ptr->ref(); if (raw_ptr && add_ref) {
raw_ptr->ref();
}
} }
}; };
/** /**
......
...@@ -57,7 +57,8 @@ namespace caf { ...@@ -57,7 +57,8 @@ namespace caf {
class sync_handle_helper; class sync_handle_helper;
/** /**
* Base class for local running Actors. * Base class for local running actors.
* @warning Instances of `local_actor` start with a reference count of 1
* @extends abstract_actor * @extends abstract_actor
*/ */
class local_actor : public extend<abstract_actor>::with<mixin::memory_cached> { class local_actor : public extend<abstract_actor>::with<mixin::memory_cached> {
......
...@@ -34,33 +34,38 @@ namespace caf { ...@@ -34,33 +34,38 @@ namespace caf {
*/ */
class ref_counted : public memory_managed { class ref_counted : public memory_managed {
public: public:
ref_counted(); ~ref_counted();
ref_counted(const ref_counted&); ref_counted(const ref_counted&);
ref_counted& operator=(const ref_counted&); ref_counted& operator=(const ref_counted&);
explicit ref_counted(size_t initial_count = 0);
~ref_counted();
/** /**
* Increases reference count by one. * Increases reference count by one.
*/ */
inline void ref() { ++m_rc; } inline void ref() {
++m_rc;
}
/** /**
* Decreases reference count by one and calls `request_deletion` * Decreases reference count by one and calls `request_deletion`
* when it drops to zero. * when it drops to zero.
*/ */
inline void deref() { inline void deref() {
if (--m_rc == 0) request_deletion(); if (--m_rc == 0) {
request_deletion();
}
} }
/** /**
* Queries whether there is exactly one reference. * Queries whether there is exactly one reference.
*/ */
inline bool unique() const { return m_rc == 1; } inline bool unique() const {
return m_rc == 1;
}
inline size_t get_reference_count() const { return m_rc; } inline size_t get_reference_count() const {
return m_rc;
}
private: private:
std::atomic<size_t> m_rc; std::atomic<size_t> m_rc;
......
...@@ -109,6 +109,9 @@ intrusive_ptr<C> spawn_impl(execution_unit* host, ...@@ -109,6 +109,9 @@ intrusive_ptr<C> spawn_impl(execution_unit* host,
detail::proper_actor<C, policy_token> detail::proper_actor<C, policy_token>
>::type; >::type;
auto ptr = detail::make_counted<actor_impl>(std::forward<Ts>(args)...); auto ptr = detail::make_counted<actor_impl>(std::forward<Ts>(args)...);
// actors start with a reference count of 1, hence we need to deref ptr once
CAF_REQUIRE(!ptr->unique());
ptr->deref();
CAF_LOGF_DEBUG("spawned actor with ID " << ptr->id()); CAF_LOGF_DEBUG("spawned actor with ID " << ptr->id());
CAF_PUSH_AID(ptr->id()); CAF_PUSH_AID(ptr->id());
before_launch_fun(ptr.get()); before_launch_fun(ptr.get());
......
...@@ -47,8 +47,8 @@ using guard_type = std::unique_lock<std::mutex>; ...@@ -47,8 +47,8 @@ using guard_type = std::unique_lock<std::mutex>;
// m_exit_reason is guaranteed to be set to 0, i.e., exit_reason::not_exited, // m_exit_reason is guaranteed to be set to 0, i.e., exit_reason::not_exited,
// by std::atomic<> constructor // by std::atomic<> constructor
abstract_actor::abstract_actor(actor_id aid, node_id nid) abstract_actor::abstract_actor(actor_id aid, node_id nid, size_t initial_count)
: super(std::move(nid)), : super(std::move(nid), initial_count),
m_id(aid), m_id(aid),
m_exit_reason(exit_reason::not_exited), m_exit_reason(exit_reason::not_exited),
m_host(nullptr), m_host(nullptr),
...@@ -56,8 +56,8 @@ abstract_actor::abstract_actor(actor_id aid, node_id nid) ...@@ -56,8 +56,8 @@ abstract_actor::abstract_actor(actor_id aid, node_id nid)
// nop // nop
} }
abstract_actor::abstract_actor() abstract_actor::abstract_actor(size_t initial_count)
: super(detail::singletons::get_node_id()), : super(detail::singletons::get_node_id(), initial_count),
m_id(detail::singletons::get_actor_registry()->next_id()), m_id(detail::singletons::get_actor_registry()->next_id()),
m_exit_reason(exit_reason::not_exited), m_exit_reason(exit_reason::not_exited),
m_host(nullptr), m_host(nullptr),
......
...@@ -24,11 +24,15 @@ namespace caf { ...@@ -24,11 +24,15 @@ namespace caf {
using detail::singletons; using detail::singletons;
abstract_channel::abstract_channel() : m_node(singletons::get_node_id()) { abstract_channel::abstract_channel(size_t initial_ref_count)
: ref_counted(initial_ref_count),
m_node(singletons::get_node_id()) {
// nop // nop
} }
abstract_channel::abstract_channel(node_id nid) : m_node(std::move(nid)) { abstract_channel::abstract_channel(node_id nid, size_t initial_ref_count)
: ref_counted(initial_ref_count),
m_node(std::move(nid)) {
// nop // nop
} }
......
...@@ -29,8 +29,12 @@ ...@@ -29,8 +29,12 @@
namespace caf { namespace caf {
// local actors are created with a reference count of one that is adjusted
// later on in spawn(); this prevents subtle bugs that lead to segfaults,
// e.g., when calling address() in the ctor of a derived class
local_actor::local_actor() local_actor::local_actor()
: m_dummy_node(), : super(1),
m_dummy_node(),
m_current_node(&m_dummy_node), m_current_node(&m_dummy_node),
m_planned_exit_reason(exit_reason::not_exited) { m_planned_exit_reason(exit_reason::not_exited) {
// nop // nop
......
...@@ -21,10 +21,6 @@ ...@@ -21,10 +21,6 @@
namespace caf { namespace caf {
ref_counted::ref_counted() : m_rc(0) {
// nop
}
ref_counted::~ref_counted() { ref_counted::~ref_counted() {
// nop // nop
} }
...@@ -38,4 +34,8 @@ ref_counted& ref_counted::operator=(const ref_counted&) { ...@@ -38,4 +34,8 @@ ref_counted& ref_counted::operator=(const ref_counted&) {
return *this; return *this;
} }
ref_counted::ref_counted(size_t initial_count) : m_rc(initial_count) {
// nop
}
} // namespace caf } // namespace caf
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