void default_actor_addressing::write(serializer* sink, const actor_ptr& ptr) { CPPA_REQUIRE(sink != nullptr); if (ptr == nullptr) { CPPA_LOGMF(CPPA_DEBUG, self, "serialized nullptr"); sink->begin_object("@0"); sink->end_object(); } else { // local actor? if (!ptr->is_proxy()) { get_actor_registry()->put(ptr->id(), ptr); } auto pinf = m_pinf; if (ptr->is_proxy()) { auto dptr = ptr.downcast<default_actor_proxy>(); if (dptr) pinf = dptr->process_info(); else CPPA_LOGMF(CPPA_ERROR, self, "downcast failed"); } sink->begin_object("@actor"); sink->write_value(ptr->id()); sink->write_value(pinf->process_id()); sink->write_raw(process_information::node_id_size, pinf->node_id().data()); sink->end_object(); } }
void local_actor::forward_message(const actor_ptr& new_receiver) { if (new_receiver == nullptr) { return; } auto& from = last_sender(); auto id = m_current_node->mid; if (id.valid() == false || id.is_response()) { new_receiver->enqueue(from.get(), m_current_node->msg); } else { new_receiver->sync_enqueue(from.get(), id, m_current_node->msg); // treat this message as asynchronous message from now on m_current_node->mid = message_id_t(); } }
void actor_registry::put(actor_id key, const actor_ptr& value) { bool add_attachable = false; if (value != nullptr) { shared_guard guard(m_instances_mtx); auto i = m_entries.find(key); if (i == m_entries.end()) { auto entry = std::make_pair(key, value_type(value, exit_reason::not_exited)); upgrade_guard uguard(guard); add_attachable = m_entries.insert(entry).second; } } if (add_attachable) { CPPA_LOG_INFO("added " << key); struct eraser : attachable { actor_id m_id; actor_registry* m_registry; eraser(actor_id id, actor_registry* s) : m_id(id), m_registry(s) { } void actor_exited(std::uint32_t reason) { m_registry->erase(m_id, reason); } bool matches(const token&) { return false; } }; value->attach(new eraser(key, this)); } }
void local_actor::forward_message(const actor_ptr& dest, message_priority p) { if (dest == nullptr) return; auto& id = m_current_node->mid; dest->enqueue({last_sender(), dest, id, p}, m_current_node->msg); // treat this message as asynchronous message from now on id = message_id{}; }
inline void operator()(const actor_ptr& sender, const message_id& mid) const { CPPA_REQUIRE(rsn != exit_reason::not_exited); if (mid.is_request() && sender != nullptr) { sender->enqueue({nullptr, sender, mid.response_id()}, make_any_tuple(atom("EXITED"), rsn)); } }
bool actor::unlink_from_impl(const actor_ptr& other) { guard_type guard{m_mtx}; // remove_backlink returns true if this actor is linked to other if (other && !exited() && other->remove_backlink(this)) { auto i = std::find(m_links.begin(), m_links.end(), other); CPPA_REQUIRE(i != m_links.end()); m_links.erase(i); return true; } return false; }
void default_actor_addressing::write(serializer* sink, const actor_ptr& ptr) { CPPA_REQUIRE(sink != nullptr); if (ptr == nullptr) { CPPA_LOG_DEBUG("serialize nullptr"); sink->write_value(static_cast<actor_id>(0)); process_information::serialize_invalid(sink); } else { // local actor? if (!ptr->is_proxy()) { get_actor_registry()->put(ptr->id(), ptr); } auto pinf = m_pinf; if (ptr->is_proxy()) { auto dptr = ptr.downcast<default_actor_proxy>(); if (dptr) pinf = dptr->process_info(); else CPPA_LOG_ERROR("downcast failed"); } sink->write_value(ptr->id()); sink->write_value(pinf->process_id()); sink->write_raw(process_information::node_id_size, pinf->node_id().data()); } }
bool actor::link_to_impl(const actor_ptr& other) { if (other && other != this) { guard_type guard{m_mtx}; // send exit message if already exited if (exited()) { send_as(this, other, atom("EXIT"), exit_reason()); } // add link if not already linked to other // (checked by establish_backlink) else if (other->establish_backlink(this)) { m_links.push_back(other); return true; } } return false; }
/** * @brief Sends @p what as a synchronous message to @p whom. * @param whom Receiver of the message. * @param what Message content as tuple. * @returns A handle identifying a future to the response of @p whom. * @warning The returned handle is actor specific and the response to the sent * message cannot be received by another actor. * @throws std::invalid_argument if <tt>whom == nullptr</tt> */ inline message_future sync_send_tuple(const actor_ptr& whom, any_tuple what) { if (whom) return self->send_sync_message(whom.get(), std::move(what)); else throw std::invalid_argument("whom == nullptr"); }
inline typename std::enable_if<std::is_base_of<channel, C>::value>::type send_tuple_as(const actor_ptr& from, const intrusive_ptr<C>& whom, any_tuple what) { if (whom) whom->enqueue(from.get(), std::move(what)); }
void local_actor::demonitor(const actor_ptr& whom) { attachable::token mtoken{typeid(down_observer), this}; if (whom) whom->detach(mtoken); }
void local_actor::monitor(const actor_ptr& whom) { if (whom) whom->attach(attachable_ptr{new down_observer(this, whom)}); }
void local_actor::monitor(actor_ptr whom) { if (whom) whom->attach(new down_observer(this, whom)); }