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 blocking_actor::dequeue(behavior& bhvr, message_id mid) {
  // try to dequeue from cache first
  if (invoke_from_cache(bhvr, mid)) {
    return;
  }
  // requesting an invalid timeout will reset our active timeout
  auto timeout_id = request_timeout(bhvr.timeout());
  // read incoming messages
  for (;;) {
    await_data();
    auto msg = next_message();
    switch (invoke_message(msg, bhvr, mid)) {
      case im_success:
        reset_timeout(timeout_id);
        return;
      case im_skipped:
        if (msg) {
          push_to_cache(std::move(msg));
        }
        break;
      default:
        // delete msg
        break;
    }
  }
}
 resumable::resume_result resume(detail::cs_thread*,
                                 execution_unit* host) override {
     auto d = static_cast<Derived*>(this);
     d->m_host = host;
     CPPA_LOG_TRACE("id = " << d->id());
     auto done_cb = [&]() -> bool {
         CPPA_LOG_TRACE("");
         d->bhvr_stack().clear();
         d->bhvr_stack().cleanup();
         d->on_exit();
         if (!d->bhvr_stack().empty()) {
             CPPA_LOG_DEBUG("on_exit did set a new behavior in on_exit");
             d->planned_exit_reason(exit_reason::not_exited);
             return false; // on_exit did set a new behavior
         }
         auto rsn = d->planned_exit_reason();
         if (rsn == exit_reason::not_exited) {
             rsn = exit_reason::normal;
             d->planned_exit_reason(rsn);
         }
         d->cleanup(rsn);
         return true;
     };
     auto actor_done = [&] {
         return    d->bhvr_stack().empty()
                || d->planned_exit_reason() != exit_reason::not_exited;
     };
     // actors without behavior or that have already defined
     // an exit reason must not be resumed
     CPPA_REQUIRE(!d->m_initialized || !actor_done());
     if (!d->m_initialized) {
         d->m_initialized = true;
         auto bhvr = d->make_behavior();
         if (bhvr) d->become(std::move(bhvr));
         // else: make_behavior() might have just called become()
         if (actor_done() && done_cb()) return resume_result::done;
         // else: enter resume loop
     }
     try {
         for (;;) {
             auto ptr = d->next_message();
             if (ptr) {
                 if (d->invoke_message(ptr)) {
                     if (actor_done() && done_cb()) {
                         CPPA_LOG_DEBUG("actor exited");
                         return resume_result::done;
                     }
                     // continue from cache if current message was
                     // handled, because the actor might have changed
                     // its behavior to match 'old' messages now
                     while (d->invoke_message_from_cache()) {
                         if (actor_done() && done_cb()) {
                             CPPA_LOG_DEBUG("actor exited");
                             return resume_result::done;
                         }
                     }
                 }
                 // add ptr to cache if invoke_message
                 // did not reset it (i.e. skipped, but not dropped)
                 if (ptr) {
                     CPPA_LOG_DEBUG("add message to cache");
                     d->push_to_cache(std::move(ptr));
                 }
             }
             else {
                 CPPA_LOG_DEBUG("no more element in mailbox; "
                                "going to block");
                 if (d->mailbox().try_block()) {
                     return resumable::resume_later;
                 }
                 // else: try again
             }
         }
     }
     catch (actor_exited& what) {
         CPPA_LOG_INFO("actor died because of exception: actor_exited, "
                       "reason = " << what.reason());
         if (d->exit_reason() == exit_reason::not_exited) {
             d->quit(what.reason());
         }
     }
     catch (std::exception& e) {
         CPPA_LOG_WARNING("actor died because of exception: "
                          << detail::demangle(typeid(e))
                          << ", what() = " << e.what());
         if (d->exit_reason() == exit_reason::not_exited) {
             d->quit(exit_reason::unhandled_exception);
         }
     }
     catch (...) {
         CPPA_LOG_WARNING("actor died because of an unknown exception");
         if (d->exit_reason() == exit_reason::not_exited) {
             d->quit(exit_reason::unhandled_exception);
         }
     }
     done_cb();
     return resumable::done;
 }
void AsyncProtocol::rx_loop()
{
    try
    {
        std::string raw_input;

        while (running_)
        {
            try
            {
                raw_input.append(io_->read());
                
                if (!running_)
                {
                    break;
                }
            }
            catch (IOReset&)
            {
                if (!running_)
                {
                    break;
                }

                Application::raise(tnt::event::ConnectionReset(this), this);

                break;
            }
            catch (...)
            {
                raw_input.clear();
            }

            if (!running_)
            {
                break;
            }

            if (raw_input.empty())
            {
                continue;
            }

            const auto& messages = parse(raw_input);

            for_all(messages, [this] (const auto& message)
            {
                assert(!message.empty());

                try
                {
                    invoke_message(message);  
                }
                catch (std::exception& ex)
                {
                    tnt::Log::error(ex.what());
                }
            });
        }
    }
    catch (std::exception& ex)
    {
        tnt::Log::error(ex.what());
        assert(false);
    }
    catch (...)
    {
        assert(false);
    }
}
 resumable::resume_result resume(execution_unit* new_host,
                                 size_t max_throughput) override {
   CAF_REQUIRE(max_throughput > 0);
   auto d = static_cast<Derived*>(this);
   CAF_LOG_TRACE("id = " << d->id());
   d->host(new_host);
   auto done_cb = [&]() -> bool {
     CAF_LOG_TRACE("");
     d->bhvr_stack().clear();
     d->bhvr_stack().cleanup();
     d->on_exit();
     if (!d->bhvr_stack().empty()) {
       CAF_LOG_DEBUG("on_exit did set a new behavior");
       d->planned_exit_reason(exit_reason::not_exited);
       return false; // on_exit did set a new behavior
     }
     auto rsn = d->planned_exit_reason();
     if (rsn == exit_reason::not_exited) {
       rsn = exit_reason::normal;
       d->planned_exit_reason(rsn);
     }
     d->cleanup(rsn);
     return true;
   };
   auto actor_done = [&]() -> bool {
     if (d->bhvr_stack().empty()
         || d->planned_exit_reason() != exit_reason::not_exited) {
       return done_cb();
     }
     return false;
   };
   // actors without behavior or that have already defined
   // an exit reason must not be resumed
   CAF_REQUIRE(!d->is_initialized()
               || (!d->bhvr_stack().empty()
                   && d->planned_exit_reason() == exit_reason::not_exited));
   std::exception_ptr eptr = nullptr;
   try {
     if (!d->is_initialized()) {
       CAF_LOG_DEBUG("initialize actor");
       d->is_initialized(true);
       auto bhvr = d->make_behavior();
       CAF_LOG_DEBUG_IF(!bhvr, "make_behavior() did not return a behavior, "
                               << "bhvr_stack().empty() = "
                               << std::boolalpha << d->bhvr_stack().empty());
       if (bhvr) {
         // make_behavior() did return a behavior instead of using become()
         CAF_LOG_DEBUG("make_behavior() did return a valid behavior");
         d->become(std::move(bhvr));
       }
       if (actor_done()) {
         CAF_LOG_DEBUG("actor_done() returned true right "
                       << "after make_behavior()");
         return resume_result::done;
       }
     }
     // max_throughput = 0 means infinite
     for (size_t i = 0; i < max_throughput; ++i) {
       auto ptr = d->next_message();
       if (ptr) {
         if (d->invoke_message(ptr)) {
           if (actor_done()) {
             CAF_LOG_DEBUG("actor exited");
             return resume_result::done;
           }
           // continue from cache if current message was
           // handled, because the actor might have changed
           // its behavior to match 'old' messages now
           while (d->invoke_message_from_cache()) {
             if (actor_done()) {
               CAF_LOG_DEBUG("actor exited");
               return resume_result::done;
             }
           }
         }
         // add ptr to cache if invoke_message
         // did not reset it (i.e. skipped, but not dropped)
         if (ptr) {
           CAF_LOG_DEBUG("add message to cache");
           d->push_to_cache(std::move(ptr));
         }
       } else {
         CAF_LOG_DEBUG("no more element in mailbox; going to block");
         if (d->mailbox().try_block()) {
           return resumable::awaiting_message;
         }
         CAF_LOG_DEBUG("try_block() interrupted by new message");
       }
     }
     if (!d->has_next_message() && d->mailbox().try_block()) {
       return resumable::awaiting_message;
     }
     // time's up
     return resumable::resume_later;
   }
   catch (actor_exited& what) {
     CAF_LOG_INFO("actor died because of exception: actor_exited, "
                  "reason = " << what.reason());
     if (d->exit_reason() == exit_reason::not_exited) {
       d->quit(what.reason());
     }
   }
   catch (std::exception& e) {
     CAF_LOG_INFO("actor died because of an exception: "
                  << detail::demangle(typeid(e))
                  << ", what() = " << e.what());
     if (d->exit_reason() == exit_reason::not_exited) {
       d->quit(exit_reason::unhandled_exception);
     }
     eptr = std::current_exception();
   }
   catch (...) {
     CAF_LOG_INFO("actor died because of an unknown exception");
     if (d->exit_reason() == exit_reason::not_exited) {
       d->quit(exit_reason::unhandled_exception);
     }
     eptr = std::current_exception();
   }
   if (eptr) {
     auto opt_reason = d->handle(eptr);
     if (opt_reason) {
       // use exit reason defined by custom handler
       d->planned_exit_reason(*opt_reason);
     }
   }
   if (!actor_done()) {
     // actor has been "revived", try running it again later
     return resumable::resume_later;
   }
   return resumable::done;
 }