Commit 532c069d authored by Dominik Charousset's avatar Dominik Charousset

Merge branch 'Lingxi-Li-topic/refine_mem_order'

parents a481bdbf b88a6e13
...@@ -51,15 +51,25 @@ public: ...@@ -51,15 +51,25 @@ public:
size_t detach(const attachable::token& what) override; size_t detach(const attachable::token& what) override;
/// Returns the exit reason of this actor or
/// `exit_reason::not_exited` if it is still alive.
inline exit_reason get_exit_reason() const {
return exit_reason_.load(std::memory_order_relaxed);
}
/// @cond PRIVATE /// @cond PRIVATE
/// Called by the runtime system to perform cleanup actions for this actor. /// Called by the runtime system to perform cleanup actions for this actor.
/// Subtypes should always call this member function when overriding it. /// Subtypes should always call this member function when overriding it.
/// This member function is thread-safe, and if the actor has already exited
/// upon invocation, nothing is done.
virtual void cleanup(exit_reason reason, execution_unit* host); virtual void cleanup(exit_reason reason, execution_unit* host);
// Returns `exit_reason_ != exit_reason::not_exited`. // returns `exit_reason_ != exit_reason::not_exited`;
// it's possible for user code to call this method
// without acquiring `mtx_`
inline bool exited() const { inline bool exited() const {
return exit_reason_ != exit_reason::not_exited; return get_exit_reason() != exit_reason::not_exited;
} }
/// @endcond /// @endcond
...@@ -91,19 +101,25 @@ protected: ...@@ -91,19 +101,25 @@ protected:
// tries to run a custom exception handler for `eptr` // tries to run a custom exception handler for `eptr`
maybe<exit_reason> handle(const std::exception_ptr& eptr); maybe<exit_reason> handle(const std::exception_ptr& eptr);
// precondition: `mtx_` is acquired
inline void attach_impl(attachable_ptr& ptr) { inline void attach_impl(attachable_ptr& ptr) {
ptr->next.swap(attachables_head_); ptr->next.swap(attachables_head_);
attachables_head_.swap(ptr); attachables_head_.swap(ptr);
} }
// precondition: `mtx_` is acquired
static size_t detach_impl(const attachable::token& what, static size_t detach_impl(const attachable::token& what,
attachable_ptr& ptr, attachable_ptr& ptr,
bool stop_on_first_hit = false, bool stop_on_first_hit = false,
bool dry_run = false); bool dry_run = false);
// handles only `exit_msg` and `sys_atom` messages;
// returns true if the message is handled
bool handle_system_message(mailbox_element& node, execution_unit* context, bool handle_system_message(mailbox_element& node, execution_unit* context,
bool trap_exit); bool trap_exit);
// handles `exit_msg`, `sys_atom` messages, and additionally `down_msg`
// with `down_msg_handler`; returns true if the message is handled
template <class F> template <class F>
bool handle_system_message(mailbox_element& node, execution_unit* context, bool handle_system_message(mailbox_element& node, execution_unit* context,
bool trap_exit, F& down_msg_handler) { bool trap_exit, F& down_msg_handler) {
...@@ -115,7 +131,9 @@ protected: ...@@ -115,7 +131,9 @@ protected:
return handle_system_message(node, context, trap_exit); return handle_system_message(node, context, trap_exit);
} }
// initially set to exit_reason::not_exited // initially set to exit_reason::not_exited;
// can only be stored with `mtx_` acquired;
// may be read without acquiring `mtx_`
std::atomic<exit_reason> exit_reason_; std::atomic<exit_reason> exit_reason_;
// guards access to exit_reason_, attachables_, links_, // guards access to exit_reason_, attachables_, links_,
......
...@@ -50,7 +50,7 @@ adapter::adapter(actor_addr decorated, message msg) ...@@ -50,7 +50,7 @@ adapter::adapter(actor_addr decorated, message msg)
void adapter::enqueue(mailbox_element_ptr what, execution_unit* host) { void adapter::enqueue(mailbox_element_ptr what, execution_unit* host) {
if (! what) if (! what)
return; // not even an empty message return; // not even an empty message
auto reason = exit_reason_.load(); auto reason = get_exit_reason();
if (reason != exit_reason::not_exited) { if (reason != exit_reason::not_exited) {
// actor has exited // actor has exited
auto& mid = what->mid; auto& mid = what->mid;
......
...@@ -69,7 +69,7 @@ local_actor::local_actor(actor_system* sys, actor_id aid, ...@@ -69,7 +69,7 @@ local_actor::local_actor(actor_system* sys, actor_id aid,
local_actor::~local_actor() { local_actor::~local_actor() {
if (! mailbox_.closed()) { if (! mailbox_.closed()) {
detail::sync_request_bouncer f{exit_reason_}; detail::sync_request_bouncer f{get_exit_reason()};
mailbox_.close(f); mailbox_.close(f);
} }
} }
......
...@@ -39,7 +39,7 @@ void monitorable_actor::attach(attachable_ptr ptr) { ...@@ -39,7 +39,7 @@ void monitorable_actor::attach(attachable_ptr ptr) {
caf::exit_reason reason; caf::exit_reason reason;
{ // lifetime scope of guard { // lifetime scope of guard
std::unique_lock<std::mutex> guard{mtx_}; std::unique_lock<std::mutex> guard{mtx_};
reason = exit_reason_; reason = get_exit_reason();
if (reason == exit_reason::not_exited) { if (reason == exit_reason::not_exited) {
attach_impl(ptr); attach_impl(ptr);
return; return;
...@@ -58,13 +58,13 @@ size_t monitorable_actor::detach(const attachable::token& what) { ...@@ -58,13 +58,13 @@ size_t monitorable_actor::detach(const attachable::token& what) {
void monitorable_actor::cleanup(exit_reason reason, execution_unit* host) { void monitorable_actor::cleanup(exit_reason reason, execution_unit* host) {
CAF_LOG_TRACE(CAF_ARG(reason)); CAF_LOG_TRACE(CAF_ARG(reason));
CAF_ASSERT(reason != exit_reason::not_exited); CAF_ASSERT(reason != exit_reason::not_exited);
// move everyhting out of the critical section before processing it // move everything out of the critical section before processing it
attachable_ptr head; attachable_ptr head;
{ // lifetime scope of guard { // lifetime scope of guard
std::unique_lock<std::mutex> guard{mtx_}; std::unique_lock<std::mutex> guard{mtx_};
if (exit_reason_ != exit_reason::not_exited) if (get_exit_reason() != exit_reason::not_exited)
return; return;
exit_reason_ = reason; exit_reason_.store(reason, std::memory_order_relaxed);
attachables_head_.swap(head); attachables_head_.swap(head);
} }
CAF_LOG_INFO_IF(host && host->system().node() == node(), CAF_LOG_INFO_IF(host && host->system().node() == node(),
...@@ -130,10 +130,12 @@ bool monitorable_actor::establish_link_impl(const actor_addr& other) { ...@@ -130,10 +130,12 @@ bool monitorable_actor::establish_link_impl(const actor_addr& other) {
if (other && other != this) { if (other && other != this) {
std::unique_lock<std::mutex> guard{mtx_}; std::unique_lock<std::mutex> guard{mtx_};
auto ptr = actor_cast<abstract_actor_ptr>(other); auto ptr = actor_cast<abstract_actor_ptr>(other);
auto reason = get_exit_reason();
// send exit message if already exited // send exit message if already exited
if (exited()) { if (reason != exit_reason::not_exited) {
guard.unlock();
ptr->enqueue(address(), invalid_message_id, ptr->enqueue(address(), invalid_message_id,
make_message(exit_msg{address(), exit_reason_}), nullptr); make_message(exit_msg{address(), reason}), nullptr);
} else if (ptr->establish_backlink(address())) { } else if (ptr->establish_backlink(address())) {
// add link if not already linked to other // add link if not already linked to other
// (checked by establish_backlink) // (checked by establish_backlink)
...@@ -151,7 +153,7 @@ bool monitorable_actor::establish_backlink_impl(const actor_addr& other) { ...@@ -151,7 +153,7 @@ bool monitorable_actor::establish_backlink_impl(const actor_addr& other) {
default_attachable::observe_token tk{other, default_attachable::link}; default_attachable::observe_token tk{other, default_attachable::link};
if (other && other != this) { if (other && other != this) {
std::unique_lock<std::mutex> guard{mtx_}; std::unique_lock<std::mutex> guard{mtx_};
reason = exit_reason_; reason = get_exit_reason();
if (reason == exit_reason::not_exited) { if (reason == exit_reason::not_exited) {
if (detach_impl(tk, attachables_head_, true, true) == 0) { if (detach_impl(tk, attachables_head_, true, true) == 0) {
auto tmp = default_attachable::make_link(other); auto tmp = default_attachable::make_link(other);
...@@ -164,7 +166,7 @@ bool monitorable_actor::establish_backlink_impl(const actor_addr& other) { ...@@ -164,7 +166,7 @@ bool monitorable_actor::establish_backlink_impl(const actor_addr& other) {
if (reason != exit_reason::not_exited) { if (reason != exit_reason::not_exited) {
auto ptr = actor_cast<abstract_actor_ptr>(other); auto ptr = actor_cast<abstract_actor_ptr>(other);
ptr->enqueue(address(), invalid_message_id, ptr->enqueue(address(), invalid_message_id,
make_message(exit_msg{address(), exit_reason_}), nullptr); make_message(exit_msg{address(), reason}), nullptr);
} }
return false; return false;
} }
...@@ -178,6 +180,7 @@ bool monitorable_actor::remove_link_impl(const actor_addr& other) { ...@@ -178,6 +180,7 @@ bool monitorable_actor::remove_link_impl(const actor_addr& other) {
// remove_backlink returns true if this actor is linked to other // remove_backlink returns true if this actor is linked to other
auto ptr = actor_cast<abstract_actor_ptr>(other); auto ptr = actor_cast<abstract_actor_ptr>(other);
if (detach_impl(tk, attachables_head_, true) > 0) { if (detach_impl(tk, attachables_head_, true) > 0) {
guard.unlock();
// tell remote side to remove link as well // tell remote side to remove link as well
ptr->remove_backlink(address()); ptr->remove_backlink(address());
return true; return true;
...@@ -220,6 +223,7 @@ bool monitorable_actor::handle_system_message(mailbox_element& node, ...@@ -220,6 +223,7 @@ bool monitorable_actor::handle_system_message(mailbox_element& node,
bool trap_exit) { bool trap_exit) {
auto& msg = node.msg; auto& msg = node.msg;
if (! trap_exit && msg.size() == 1 && msg.match_element<exit_msg>(0)) { if (! trap_exit && msg.size() == 1 && msg.match_element<exit_msg>(0)) {
// exits for non-normal exit reasons
auto& em = msg.get_as<exit_msg>(0); auto& em = msg.get_as<exit_msg>(0);
CAF_ASSERT(em.reason != exit_reason::not_exited); CAF_ASSERT(em.reason != exit_reason::not_exited);
if (em.reason != exit_reason::normal) if (em.reason != exit_reason::normal)
......
...@@ -47,7 +47,7 @@ sequencer::sequencer(actor_addr f, actor_addr g, message_types_set msg_types) ...@@ -47,7 +47,7 @@ sequencer::sequencer(actor_addr f, actor_addr g, message_types_set msg_types)
void sequencer::enqueue(mailbox_element_ptr what, execution_unit* context) { void sequencer::enqueue(mailbox_element_ptr what, execution_unit* context) {
if (! what) if (! what)
return; // not even an empty message return; // not even an empty message
auto reason = exit_reason_.load(); auto reason = get_exit_reason();
if (reason != exit_reason::not_exited) { if (reason != exit_reason::not_exited) {
// actor has exited // actor has exited
auto& mid = what->mid; auto& mid = what->mid;
......
...@@ -83,7 +83,7 @@ splitter::splitter(std::vector<actor_addr> workers, message_types_set msg_types) ...@@ -83,7 +83,7 @@ splitter::splitter(std::vector<actor_addr> workers, message_types_set msg_types)
void splitter::enqueue(mailbox_element_ptr what, execution_unit* context) { void splitter::enqueue(mailbox_element_ptr what, execution_unit* context) {
if (! what) if (! what)
return; // not even an empty message return; // not even an empty message
auto reason = exit_reason_.load(); auto reason = get_exit_reason();
if (reason != exit_reason::not_exited) { if (reason != exit_reason::not_exited) {
// actor has exited // actor has exited
auto& mid = what->mid; auto& mid = what->mid;
......
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