void actor_ostream::redirect_all(actor_system& sys, std::string fn, int flags) { auto pr = sys.scheduler().printer(); pr->enqueue(make_mailbox_element(nullptr, message_id::make(), {}, redirect_atom::value, std::move(fn), flags), nullptr); }
void manager::detach(execution_unit*, bool invoke_disconnect_message) { CAF_LOG_TRACE(CAF_ARG(invoke_disconnect_message)); // This function gets called from the multiplexer when an error occurs or // from the broker when closing this manager. In both cases, we need to make // sure this manager does not receive further socket events. remove_from_loop(); // Disconnect from the broker if not already detached. if (!detached()) { CAF_LOG_DEBUG("disconnect servant from broker"); auto raw_ptr = parent(); // Keep a strong reference to our parent until we go out of scope. strong_actor_ptr ptr; ptr.swap(parent_); detach_from(raw_ptr); if (invoke_disconnect_message) { auto mptr = make_mailbox_element(nullptr, invalid_message_id, {}, detach_message()); switch (raw_ptr->consume(*mptr)) { case im_success: raw_ptr->finalize(); break; case im_skipped: raw_ptr->push_to_cache(std::move(mptr)); break; case im_dropped: CAF_LOG_INFO("broker dropped disconnect message"); break; } } } }
actor_ostream& actor_ostream::write(std::string arg) { printer_->enqueue(make_mailbox_element(nullptr, message_id::make(), {}, add_atom::value, self_, std::move(arg)), nullptr); return *this; }
bool monitorable_actor::cleanup(error&& reason, execution_unit* host) { CAF_LOG_TRACE(CAF_ARG(reason)); attachable_ptr head; bool set_fail_state = exclusive_critical_section([&]() -> bool { if (!getf(is_cleaned_up_flag)) { // local actors pass fail_state_ as first argument if (&fail_state_ != &reason) fail_state_ = std::move(reason); attachables_head_.swap(head); flags(flags() | is_terminated_flag | is_cleaned_up_flag); on_cleanup(); return true; } return false; }); if (!set_fail_state) return false; CAF_LOG_DEBUG("cleanup" << CAF_ARG(id()) << CAF_ARG(node()) << CAF_ARG(reason)); // send exit messages for (attachable* i = head.get(); i != nullptr; i = i->next.get()) i->actor_exited(reason, host); // tell printer to purge its state for us if we ever used aout() if (getf(abstract_actor::has_used_aout_flag)) { auto pr = home_system().scheduler().printer(); pr->enqueue(make_mailbox_element(nullptr, make_message_id(), {}, delete_atom::value, id()), nullptr); } return true; }
void actor_ostream::redirect(abstract_actor* self, std::string fn, int flags) { if (!self) return; auto pr = self->home_system().scheduler().printer(); pr->enqueue(make_mailbox_element(nullptr, message_id::make(), {}, redirect_atom::value, self->id(), std::move(fn), flags), nullptr); }
void scribe::data_transferred(execution_unit* ctx, size_t written, size_t remaining) { CAF_LOG_TRACE(CAF_ARG(written) << CAF_ARG(remaining)); if (detached()) return; data_transferred_msg tmp{hdl(), written, remaining}; auto ptr = make_mailbox_element(nullptr, invalid_message_id, {}, tmp); parent()->context(ctx); parent()->consume(std::move(ptr)); }
bool monitorable_actor::handle_system_message(mailbox_element& x, execution_unit* ctx, bool trap_exit) { auto& msg = x.content(); if (!trap_exit && msg.size() == 1 && msg.match_element<exit_msg>(0)) { // exits for non-normal exit reasons auto& em = msg.get_mutable_as<exit_msg>(0); if (em.reason) cleanup(std::move(em.reason), ctx); return true; } if (msg.size() > 1 && msg.match_element<sys_atom>(0)) { if (!x.sender) return true; error err; mailbox_element_ptr res; msg.apply( [&](sys_atom, get_atom, std::string& what) { CAF_LOG_TRACE(CAF_ARG(what)); if (what != "info") { err = sec::unsupported_sys_key; return; } res = make_mailbox_element(ctrl(), x.mid.response_id(), {}, ok_atom::value, std::move(what), strong_actor_ptr{ctrl()}, name()); } ); if (!res && !err) err = sec::unsupported_sys_message; if (err && x.mid.is_request()) res = make_mailbox_element(ctrl(), x.mid.response_id(), {}, std::move(err)); if (res) { auto s = actor_cast<strong_actor_ptr>(x.sender); if (s) s->enqueue(std::move(res), ctx); } return true; } return false; }
void response_promise::deliver_impl(message msg) { CAF_LOG_TRACE(CAF_ARG(msg)); if (!stages_.empty()) { auto next = std::move(stages_.back()); stages_.pop_back(); next->enqueue(make_mailbox_element(std::move(source_), id_, std::move(stages_), std::move(msg)), context()); return; } if (source_) { source_->enqueue(std::move(self_), id_.response_id(), std::move(msg), context()); source_.reset(); return; } CAF_LOG_INFO_IF(self_ != nullptr, "response promise already satisfied"); CAF_LOG_INFO_IF(self_ == nullptr, "invalid response promise"); }
typename response_type< typename Handle::signatures, detail::implicit_conversions_t<typename std::decay<Ts>::type>... >::delegated_type delegate(const Handle& dest, Ts&&... xs) { static_assert(sizeof...(Ts) > 0, "nothing to delegate"); using token = detail::type_list< typename detail::implicit_conversions< typename std::decay<Ts>::type >::type...>; static_assert(response_type_unbox<signatures_of_t<Handle>, token>::valid, "receiver does not accept given message"); auto mid = current_element_->mid; current_element_->mid = P == message_priority::high ? mid.with_high_priority() : mid.with_normal_priority(); dest->enqueue(make_mailbox_element(std::move(current_element_->sender), mid, std::move(current_element_->stages), std::forward<Ts>(xs)...), context()); return {}; }
actor_ostream& actor_ostream::flush() { printer_->enqueue(make_mailbox_element(nullptr, message_id::make(), {}, flush_atom::value, self_), nullptr); return *this; }
void actor_companion::enqueue(strong_actor_ptr src, message_id mid, message content, execution_unit* eu) { auto ptr = make_mailbox_element(std::move(src), mid, {}, std::move(content)); enqueue(std::move(ptr), eu); }
void eq_impl(message_id mid, strong_actor_ptr sender, execution_unit* ctx, Ts&&... xs) { enqueue(make_mailbox_element(std::move(sender), mid, {}, std::forward<Ts>(xs)...), ctx); }
void abstract_broker::enqueue(strong_actor_ptr src, message_id mid, message msg, execution_unit*) { enqueue(make_mailbox_element(std::move(src), mid, {}, std::move(msg)), &backend()); }
void basp_broker_state::deliver(const node_id& src_nid, actor_id src_aid, strong_actor_ptr dest, message_id mid, std::vector<strong_actor_ptr>& stages, message& msg) { CAF_LOG_TRACE(CAF_ARG(src_nid) << CAF_ARG(src_aid) << CAF_ARG(dest) << CAF_ARG(msg) << CAF_ARG(mid)); auto src = src_nid == this_node() ? system().registry().get(src_aid) : proxies().get_or_put(src_nid, src_aid); // Intercept link messages. Forwarding actor proxies signalize linking // by sending link_atom/unlink_atom message with src = dest. if (msg.type_token() == make_type_token<atom_value, strong_actor_ptr>()) { switch (static_cast<uint64_t>(msg.get_as<atom_value>(0))) { default: break; case link_atom::value.uint_value(): { if (src_nid != this_node()) { CAF_LOG_WARNING("received link message for an other node"); return; } auto ptr = msg.get_as<strong_actor_ptr>(1); if (!ptr) { CAF_LOG_WARNING("received link message with invalid target"); return; } if (!src) { CAF_LOG_DEBUG("received link for invalid actor, report error"); anon_send(actor_cast<actor>(ptr), make_error(sec::remote_linking_failed)); return; } static_cast<actor_proxy*>(ptr->get())->local_link_to(src->get()); return; } case unlink_atom::value.uint_value(): { if (src_nid != this_node()) { CAF_LOG_WARNING("received unlink message for an other node"); return; } auto ptr = msg.get_as<strong_actor_ptr>(1); if (!ptr) { CAF_LOG_DEBUG("received unlink message with invalid target"); return; } if (!src) { CAF_LOG_DEBUG("received unlink for invalid actor, report error"); return; } static_cast<actor_proxy*>(ptr->get())->local_unlink_from(src->get()); return; } } } if (!dest) { auto rsn = exit_reason::remote_link_unreachable; CAF_LOG_INFO("cannot deliver message, destination not found"); self->parent().notify<hook::invalid_message_received>(src_nid, src, invalid_actor_id, mid, msg); if (mid.valid() && src) { detail::sync_request_bouncer srb{rsn}; srb(src, mid); } return; } self->parent().notify<hook::message_received>(src_nid, src, dest, mid, msg); dest->enqueue(make_mailbox_element(std::move(src), mid, std::move(stages), std::move(msg)), nullptr); }