bool instance::dispatch(const actor_addr& sender, const actor_addr& receiver, message_id mid, const message& msg) { CAF_LOG_TRACE(""); CAF_ASSERT(receiver.is_remote()); auto path = lookup(receiver->node()); if (! path) { notify<hook::message_sending_failed>(sender, receiver, mid, msg); return false; } auto writer = make_callback([&](serializer& sink) { msg.serialize(sink); }); header hdr{message_type::dispatch_message, 0, mid.integer_value(), sender ? sender->node() : this_node(), receiver->node(), sender ? sender->id() : invalid_actor_id, receiver->id()}; write(path->wr_buf, hdr, &writer); flush(*path); notify<hook::message_sent>(sender, path->next_hop, receiver, mid, msg); return true; }
bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender, const std::vector<strong_actor_ptr>& forwarding_stack, const strong_actor_ptr& receiver, message_id mid, const message& msg) { CAF_LOG_TRACE(CAF_ARG(sender) << CAF_ARG(receiver) << CAF_ARG(mid) << CAF_ARG(msg)); CAF_ASSERT(receiver && system().node() != receiver->node()); auto path = lookup(receiver->node()); if (! path) { notify<hook::message_sending_failed>(sender, receiver, mid, msg); return false; } auto writer = make_callback([&](serializer& sink) { sink << forwarding_stack << msg; }); header hdr{message_type::dispatch_message, 0, 0, mid.integer_value(), sender ? sender->node() : this_node(), receiver->node(), sender ? sender->id() : invalid_actor_id, receiver->id()}; write(ctx, path->wr_buf, hdr, &writer); flush(*path); notify<hook::message_sent>(sender, path->next_hop, receiver, mid, msg); return true; }
handle_message_result handle_message(Actor* self, mailbox_element* node, Fun& fun, message_id awaited_response) { bool handle_sync_failure_on_mismatch = true; if (dptr()->hm_should_skip(node)) { return hm_skip_msg; } switch (this->filter_msg(self, node)) { case msg_type::normal_exit: CAF_LOG_DEBUG("dropped normal exit signal"); return hm_drop_msg; case msg_type::expired_sync_response: CAF_LOG_DEBUG("dropped expired sync response"); return hm_drop_msg; case msg_type::expired_timeout: CAF_LOG_DEBUG("dropped expired timeout message"); return hm_drop_msg; case msg_type::inactive_timeout: CAF_LOG_DEBUG("skipped inactive timeout message"); return hm_skip_msg; case msg_type::non_normal_exit: CAF_LOG_DEBUG("handled non-normal exit signal"); // this message was handled // by calling self->quit(...) return hm_msg_handled; case msg_type::timeout: { CAF_LOG_DEBUG("handle timeout message"); auto& tm = node->msg.get_as<timeout_msg>(0); self->handle_timeout(fun, tm.timeout_id); if (awaited_response.valid()) { self->mark_arrived(awaited_response); self->remove_handler(awaited_response); } return hm_msg_handled; } case msg_type::timeout_response: handle_sync_failure_on_mismatch = false; CAF_ANNOTATE_FALLTHROUGH; case msg_type::sync_response: CAF_LOG_DEBUG("handle as synchronous response: " << CAF_TARG(node->msg, to_string) << ", " << CAF_MARG(node->mid, integer_value) << ", " << CAF_MARG(awaited_response, integer_value)); if (awaited_response.valid() && node->mid == awaited_response) { auto previous_node = dptr()->hm_begin(self, node); auto res = invoke_fun(self, node->msg, node->mid, fun); if (!res && handle_sync_failure_on_mismatch) { CAF_LOG_WARNING("sync failure occured in actor " << "with ID " << self->id()); self->handle_sync_failure(); } self->mark_arrived(awaited_response); self->remove_handler(awaited_response); dptr()->hm_cleanup(self, previous_node); return hm_msg_handled; } return hm_cache_msg; case msg_type::ordinary: if (!awaited_response.valid()) { auto previous_node = dptr()->hm_begin(self, node); auto res = invoke_fun(self, node->msg, node->mid, fun); if (res) { dptr()->hm_cleanup(self, previous_node); return hm_msg_handled; } // no match (restore self members) dptr()->hm_revert(self, previous_node); } CAF_LOG_DEBUG_IF(awaited_response.valid(), "ignored message; await response: " << awaited_response.integer_value()); return hm_cache_msg; } // should be unreachable CAF_CRITICAL("invalid message type"); }