void blocking_actor::dequeue(behavior& bhvr, message_id mid) {
  CAF_LOG_TRACE(CAF_MARG(mid, integer_value));
  // try to dequeue from cache first
  if (invoke_from_cache(bhvr, mid)) {
    return;
  }
  // requesting an invalid timeout will reset our active timeout
  uint32_t timeout_id = 0;
  if (mid == invalid_message_id) {
    timeout_id = request_timeout(bhvr.timeout());
  } else {
    request_sync_timeout_msg(bhvr.timeout(), mid);
  }
  // read incoming messages
  for (;;) {
    await_data();
    auto msg = next_message();
    switch (invoke_message(msg, bhvr, mid)) {
      case im_success:
        if (mid == invalid_message_id) {
          reset_timeout(timeout_id);
        }
        return;
      case im_skipped:
        if (msg) {
          push_to_cache(std::move(msg));
        }
        break;
      default:
        // delete msg
        break;
    }
  }
}
void remote_actor_proxy::forward_msg(const actor_addr& sender, message_id mid,
                                     message msg) {
  CAF_LOG_TRACE(CAF_ARG(id()) << ", " << CAF_TSARG(sender) << ", "
                              << CAF_MARG(mid, integer_value) << ", "
                              << CAF_TSARG(msg));
  m_parent->enqueue(
    invalid_actor_addr, invalid_message_id,
    make_message(atom("_Dispatch"), sender, address(), mid, std::move(msg)),
    nullptr);
}
void forwarding_actor_proxy::forward_msg(const actor_addr& sender,
                                         message_id mid, message msg) {
  CAF_LOG_TRACE(CAF_ARG(id()) << ", " << CAF_TSARG(sender) << ", "
                              << CAF_MARG(mid, integer_value) << ", "
                              << CAF_TSARG(msg));
  shared_lock<detail::shared_spinlock> m_guard(m_manager_mtx);
  m_manager->enqueue(invalid_actor_addr, invalid_message_id,
                     make_message(atom("_Dispatch"), sender,
                                  address(), mid, std::move(msg)),
                     nullptr);
}
 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");
 }
  optional<message> invoke_fun(Actor* self, message& msg, message_id& mid,
                               Fun& fun,
                               MaybeResponseHdl hdl = MaybeResponseHdl{}) {
#   ifdef CAF_LOG_LEVEL
      auto msg_str = to_string(msg);
#   endif
    CAF_LOG_TRACE(CAF_MARG(mid, integer_value) << ", msg = " << msg_str);
    auto res = fun(msg); // might change mid
    CAF_LOG_DEBUG_IF(res, "actor did consume message: " << msg_str);
    CAF_LOG_DEBUG_IF(!res, "actor did ignore message: " << msg_str);
    if (!res) {
      return none;
    }
    if (res->empty()) {
      // make sure synchronous requests
      // always receive a response
      if (mid.is_request() && !mid.is_answered()) {
        CAF_LOG_WARNING("actor with ID " << self->id()
                        << " did not reply to a synchronous request message");
        auto fhdl = fetch_response_promise(self, hdl);
        if (fhdl) {
          fhdl.deliver(make_message(unit));
        }
      }
    } else {
      CAF_LOGF_DEBUG("res = " << to_string(*res));
      if (res->template has_types<atom_value, uint64_t>()
          && res->template get_as<atom_value>(0) == atom("MESSAGE_ID")) {
        CAF_LOG_DEBUG("message handler returned a message id wrapper");
        auto id = res->template get_as<uint64_t>(1);
        auto msg_id = message_id::from_integer_value(id);
        auto ref_opt = self->sync_handler(msg_id);
        // calls self->response_promise() if hdl is a dummy
        // argument, forwards hdl otherwise to reply to the
        // original request message
        auto fhdl = fetch_response_promise(self, hdl);
        if (ref_opt) {
          behavior cpy = *ref_opt;
          *ref_opt =
            cpy.add_continuation([=](message & intermediate)
                         ->optional<message> {
              if (!intermediate.empty()) {
                // do no use lamba expresion type to
                // avoid recursive template instantiaton
                behavior::continuation_fun f2 = [=](
                  message & m)->optional<message> {
                  return std::move(m);

                };
                auto mutable_mid = mid;
                // recursively call invoke_fun on the
                // result to correctly handle stuff like
                // sync_send(...).then(...).then(...)...
                return this->invoke_fun(self, intermediate,
                             mutable_mid, f2, fhdl);
              }
              return none;
            });
        }
        // reset res to prevent "outer" invoke_fun
        // from handling the result again
        res->reset();
      } else {
        // respond by using the result of 'fun'
        CAF_LOG_DEBUG("respond via response_promise");
        auto fhdl = fetch_response_promise(self, hdl);
        if (fhdl) {
          fhdl.deliver(std::move(*res));
          // inform caller about success
          return message{};
        }
      }
    }
    return res;
  }