Esempio n. 1
0
 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;
 }
Esempio n. 2
0
 void register_for_writing() {
     if (!m_has_unwritten_data) {
         BOOST_ACTOR_LOG_DEBUG("register for writing");
         m_has_unwritten_data = true;
         m_parent->continue_writer(this);
     }
 }
Esempio n. 3
0
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)));
    }
}
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 middleman_event_handler::alteration(continuable* ptr,
                                         event_bitmask e,
                                         fd_meta_event etype) {
    native_socket_type fd;
    switch (e) {
        case event::read:
            fd = ptr->read_handle();
            break;
        case event::write: {
            fd = ptr->write_handle();
            break;
        }
        case event::both: {
            fd = ptr->read_handle();
            auto wrfd = ptr->write_handle();
            if (fd != wrfd) {
                BOOST_ACTOR_LOG_DEBUG("read_handle != write_handle, split "
                               "into two function calls");
                // split into two function calls
                e = event::read;
                alteration(ptr, event::write, etype);
            }
            break;
        }
        default:
            BOOST_ACTOR_CRITICAL("invalid bitmask");
            return;
    }
    m_alterations.emplace_back(fd_meta_info(fd, ptr, e), etype);
}
Esempio n. 6
0
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;
  }
}