void local_actor::join(const group& what) { BOOST_ACTOR_LOG_TRACE(BOOST_ACTOR_TSARG(what)); if (what && m_subscriptions.count(what) == 0) { BOOST_ACTOR_LOG_DEBUG("join group: " << to_string(what)); m_subscriptions.insert(std::make_pair(what, what->subscribe(this))); } }
continue_writing_result continue_writing() override { BOOST_ACTOR_LOG_TRACE(""); BOOST_ACTOR_LOG_DEBUG_IF(!m_has_unwritten_data, "nothing to write (done)"); while (m_has_unwritten_data) { size_t written; try { written = m_out->write_some(m_buf.data(), m_buf.size()); } catch (std::exception& e) { BOOST_ACTOR_LOG_ERROR(to_verbose_string(e)); static_cast<void>(e); // keep compiler happy return continue_writing_result::failure; } if (written != m_buf.size()) { BOOST_ACTOR_LOG_DEBUG("tried to write " << m_buf.size() << "bytes, " << "only " << written << " bytes written"); m_buf.erase_leading(written); return continue_writing_result::continue_later; } else { m_buf.clear(); m_has_unwritten_data = false; BOOST_ACTOR_LOG_DEBUG("write done, " << written << " bytes written"); } } return continue_writing_result::done; }
void middleman_event_handler::update() { BOOST_ACTOR_LOG_TRACE(""); auto mless = [](const fd_meta_info& lhs, native_socket_type rhs) { return lhs.fd < rhs; }; for (auto& elem_pair : m_alterations) { auto& elem = elem_pair.first; auto old = event::none; auto last = m_meta.end(); auto iter = std::lower_bound(m_meta.begin(), last, elem.fd, mless); if (iter != last) old = iter->mask; auto mask = next_bitmask(old, elem.mask, elem_pair.second); auto ptr = elem.ptr; BOOST_ACTOR_LOG_DEBUG("new bitmask for " << elem.ptr << ": " << eb2str(mask)); if (iter == last || iter->fd != elem.fd) { if (mask != event::none) { // element has been removed from m_meta by an // previous alteration but is not put back in m_meta.insert(iter, elem); handle_event(fd_meta_event::add, elem.fd, event::none, mask, ptr); } } else if (iter->fd == elem.fd) { BOOST_ACTOR_REQUIRE(iter->ptr == elem.ptr); if (mask == event::none) { // note: we cannot decide whether it's safe to dispose `ptr`, // because we didn't parse all alterations yet m_dispose_list.emplace_back(ptr); m_meta.erase(iter); handle_event(fd_meta_event::erase, elem.fd, old, mask, ptr); } else { iter->mask = mask; handle_event(fd_meta_event::mod, elem.fd, old, mask, ptr); } } } m_alterations.clear(); // m_meta won't be touched inside loop auto first = m_meta.begin(); auto last = m_meta.end(); // checks whether an element can be safely deleted, // i.e., was not put back into m_meta by some alteration auto is_alive = [&](native_socket_type fd) -> bool { auto iter = std::lower_bound(first, last, fd, mless); return iter != last && iter->fd == fd; }; // dispose everything that wasn't put back into m_meta again for (auto elem : m_dispose_list) { auto rd = elem->read_handle(); auto wr = elem->write_handle(); if ( (rd == wr && !is_alive(rd)) || (rd != wr && !is_alive(rd) && !is_alive(wr))) { elem->dispose(); } } m_dispose_list.clear(); }
void forwarding_actor_proxy::forward_msg(const actor_addr& sender, message_id mid, message msg) { BOOST_ACTOR_LOG_TRACE(BOOST_ACTOR_ARG(id()) << ", " << BOOST_ACTOR_TSARG(sender) << ", " << BOOST_ACTOR_MARG(mid, integer_value) << ", " << BOOST_ACTOR_TSARG(msg)); shared_lock<detail::shared_spinlock> guard_(manager_mtx_); if (manager_) manager_->enqueue(invalid_actor_addr, invalid_message_id, make_message(forward_atom::value, sender, address(), mid, std::move(msg)), nullptr); }
void manager::detach(bool invoke_disconnect_message) { BOOST_ACTOR_LOG_TRACE(""); if (! detached()) { BOOST_ACTOR_LOG_DEBUG("disconnect servant from broker"); detach_from_parent(); if (invoke_disconnect_message) { auto msg = detach_message(); parent_->invoke_message(parent_->address(),invalid_message_id, msg); } parent_ = nullptr; } }
void local_actor::quit(std::uint32_t reason) { BOOST_ACTOR_LOG_TRACE("reason = " << reason << ", class " << detail::demangle(typeid(*this))); if (reason == exit_reason::unallowed_function_call) { // this is the only reason that causes an exception cleanup(reason); BOOST_ACTOR_LOG_WARNING("actor tried to use a blocking function"); // when using receive(), the non-blocking nature of event-based // actors breaks any assumption the user has about his code, // in particular, receive_loop() is a deadlock when not throwing // an exception here aout(this) << "*** warning: event-based actor killed because it tried " "to use receive()\n"; throw actor_exited(reason); } planned_exit_reason(reason); }
void local_actor::cleanup(std::uint32_t reason) { BOOST_ACTOR_LOG_TRACE(BOOST_ACTOR_ARG(reason)); m_subscriptions.clear(); super::cleanup(reason); }
void functor_based_blocking_actor::act() { BOOST_ACTOR_LOG_TRACE(""); m_act(this); }
void middleman_event_handler::erase_later(continuable* ptr, event_bitmask e) { BOOST_ACTOR_LOG_TRACE(BOOST_ACTOR_ARG(ptr) << ", e = " << eb2str(e)); alteration(ptr, e, fd_meta_event::erase); }
void middleman_event_handler::add_later(continuable* ptr, event_bitmask e) { BOOST_ACTOR_LOG_TRACE(BOOST_ACTOR_ARG(ptr) << ", " << BOOST_ACTOR_TARG(e, eb2str) << ", socket = " << ptr->read_handle()); alteration(ptr, e, fd_meta_event::add); }