Commit d2ca6275 authored by Dominik Charousset's avatar Dominik Charousset

Use a single member function for linking

Combine all four linking-related member functions into a single member function
with an enum to identify the current operation. Relates #180.
parent c6c4aa65
...@@ -119,10 +119,19 @@ class abstract_actor : public abstract_channel { ...@@ -119,10 +119,19 @@ class abstract_actor : public abstract_channel {
return detach(attachable::token{typeid(T), &what}); return detach(attachable::token{typeid(T), &what});
} }
enum linking_operation {
establish_link_op,
establish_backlink_op,
remove_link_op,
remove_backlink_op
};
/** /**
* Links this actor to `whom`. * Links this actor to `whom`.
*/ */
virtual void link_to(const actor_addr& whom); inline void link_to(const actor_addr& whom) {
link_impl(establish_link_op, whom);
}
/** /**
* Links this actor to `whom`. * Links this actor to `whom`.
...@@ -135,27 +144,33 @@ class abstract_actor : public abstract_channel { ...@@ -135,27 +144,33 @@ class abstract_actor : public abstract_channel {
/** /**
* Unlinks this actor from `whom`. * Unlinks this actor from `whom`.
*/ */
virtual void unlink_from(const actor_addr& whom); inline void unlink_from(const actor_addr& other) {
link_impl(remove_link_op, other);
}
/** /**
* Unlinks this actor from `whom`. * Unlinks this actor from `whom`.
*/ */
template <class ActorHandle> template <class ActorHandle>
void unlink_from(const ActorHandle& whom) { void unlink_from(const ActorHandle& other) {
unlink_from(whom.address()); unlink_from(other.address());
} }
/** /**
* Establishes a link relation between this actor and `other` * Establishes a link relation between this actor and `other`
* and returns whether the operation succeeded. * and returns whether the operation succeeded.
*/ */
virtual bool establish_backlink(const actor_addr& other); inline bool establish_backlink(const actor_addr& other) {
return link_impl(establish_backlink_op, other);
}
/** /**
* Removes the link relation between this actor and `other` * Removes the link relation between this actor and `other`
* and returns whether the operation succeeded. * and returns whether the operation succeeded.
*/ */
virtual bool remove_backlink(const actor_addr& other); inline bool remove_backlink(const actor_addr& other) {
return link_impl(remove_backlink_op, other);
}
/** /**
* Returns the unique ID of this actor. * Returns the unique ID of this actor.
...@@ -218,21 +233,21 @@ class abstract_actor : public abstract_channel { ...@@ -218,21 +233,21 @@ class abstract_actor : public abstract_channel {
*/ */
abstract_actor(actor_id aid, node_id nid); abstract_actor(actor_id aid, node_id nid);
virtual bool link_impl(linking_operation op, const actor_addr& other);
/** /**
* 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.
*/ */
virtual void cleanup(uint32_t reason); virtual void cleanup(uint32_t reason);
/** bool establish_link_impl(const actor_addr& other);
* The default implementation for `link_to()`.
*/
bool link_to_impl(const actor_addr& other);
/** bool remove_link_impl(const actor_addr& other);
* The default implementation for {@link unlink_from()}.
*/ bool establish_backlink_impl(const actor_addr& other);
bool unlink_from_impl(const actor_addr& other);
bool remove_backlink_impl(const actor_addr& other);
/** /**
* Returns `exit_reason() != exit_reason::not_exited`. * Returns `exit_reason() != exit_reason::not_exited`.
......
...@@ -65,25 +65,6 @@ abstract_actor::abstract_actor() ...@@ -65,25 +65,6 @@ abstract_actor::abstract_actor()
// nop // nop
} }
bool abstract_actor::link_to_impl(const actor_addr& other) {
if (other && other != this) {
guard_type guard{m_mtx};
auto ptr = actor_cast<abstract_actor_ptr>(other);
// send exit message if already exited
if (exited()) {
ptr->enqueue(address(), message_id::invalid,
make_message(exit_msg{address(), exit_reason()}), m_host);
}
// add link if not already linked to other
// (checked by establish_backlink)
else if (ptr->establish_backlink(address())) {
m_attachables.push_back(default_attachable::make_link(other));
return true;
}
}
return false;
}
void abstract_actor::attach(attachable_ptr ptr) { void abstract_actor::attach(attachable_ptr ptr) {
CAF_LOG_TRACE(""); CAF_LOG_TRACE("");
if (ptr == nullptr) { if (ptr == nullptr) {
...@@ -118,28 +99,40 @@ void abstract_actor::detach(const attachable::token& what) { ...@@ -118,28 +99,40 @@ void abstract_actor::detach(const attachable::token& what) {
// ptr will be destroyed here, without locked mutex // ptr will be destroyed here, without locked mutex
} }
void abstract_actor::link_to(const actor_addr& other) { bool abstract_actor::link_impl(linking_operation op, const actor_addr& other) {
static_cast<void>(link_to_impl(other)); switch (op) {
} case establish_link_op:
return establish_link_impl(other);
void abstract_actor::unlink_from(const actor_addr& other) { case establish_backlink_op:
static_cast<void>(unlink_from_impl(other)); return establish_backlink_impl(other);
case remove_link_op:
return remove_link_impl(other);
case remove_backlink_op:
return remove_backlink_impl(other);
}
return false;
} }
bool abstract_actor::remove_backlink(const actor_addr& other) { bool abstract_actor::establish_link_impl(const actor_addr& other) {
default_attachable::predicate pred(other, default_attachable::link);
if (other && other != this) { if (other && other != this) {
guard_type guard{m_mtx}; guard_type guard{m_mtx};
auto i = std::find_if(m_attachables.begin(), m_attachables.end(), pred); auto ptr = actor_cast<abstract_actor_ptr>(other);
if (i != m_attachables.end()) { // send exit message if already exited
m_attachables.erase(i); if (exited()) {
ptr->enqueue(address(), message_id::invalid,
make_message(exit_msg{address(), exit_reason()}), m_host);
}
// add link if not already linked to other
// (checked by establish_backlink)
else if (ptr->establish_backlink(address())) {
m_attachables.push_back(default_attachable::make_link(other));
return true; return true;
} }
} }
return false; return false;
} }
bool abstract_actor::establish_backlink(const actor_addr& other) { bool abstract_actor::establish_backlink_impl(const actor_addr& other) {
uint32_t reason = exit_reason::not_exited; uint32_t reason = exit_reason::not_exited;
default_attachable::predicate pred(other, default_attachable::link); default_attachable::predicate pred(other, default_attachable::link);
if (other && other != this) { if (other && other != this) {
...@@ -162,7 +155,7 @@ bool abstract_actor::establish_backlink(const actor_addr& other) { ...@@ -162,7 +155,7 @@ bool abstract_actor::establish_backlink(const actor_addr& other) {
return false; return false;
} }
bool abstract_actor::unlink_from_impl(const actor_addr& other) { bool abstract_actor::remove_link_impl(const actor_addr& other) {
if (!other) { if (!other) {
return false; return false;
} }
...@@ -179,6 +172,19 @@ bool abstract_actor::unlink_from_impl(const actor_addr& other) { ...@@ -179,6 +172,19 @@ bool abstract_actor::unlink_from_impl(const actor_addr& other) {
return false; return false;
} }
bool abstract_actor::remove_backlink_impl(const actor_addr& other) {
default_attachable::predicate pred(other, default_attachable::link);
if (other && other != this) {
guard_type guard{m_mtx};
auto i = std::find_if(m_attachables.begin(), m_attachables.end(), pred);
if (i != m_attachables.end()) {
m_attachables.erase(i);
return true;
}
}
return false;
}
actor_addr abstract_actor::address() const { actor_addr abstract_actor::address() const {
return actor_addr{const_cast<abstract_actor*>(this)}; return actor_addr{const_cast<abstract_actor*>(this)};
} }
......
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