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 update() {
     CPPA_LOG_TRACE("");
     for (auto& elem_pair : m_alterations) {
         auto& elem = elem_pair.first;
         auto old = event::none;
         auto last = end(m_meta);
         auto iter = lower_bound(begin(m_meta), last, elem.fd, m_less);
         if (iter != last) old = iter->mask;
         auto mask = next_bitmask(old, elem.mask, elem_pair.second);
         auto ptr = elem.ptr.get();
         CPPA_LOG_DEBUG("new bitmask for "
                        << elem.ptr.get() << ": " << eb2str(mask));
         if (iter == last || iter->fd != elem.fd) {
             CPPA_LOG_INFO_IF(mask == event::none,
                              "cannot erase " << ptr
                              << " (not found in m_meta)");
             if (mask != event::none) {
                 m_meta.insert(iter, elem);
                 d()->handle_event(fd_meta_event::add, elem.fd,
                              event::none, mask, ptr);
             }
         }
         else if (iter->fd == elem.fd) {
             CPPA_REQUIRE(iter->ptr == elem.ptr);
             if (mask == event::none) {
                 m_meta.erase(iter);
                 d()->handle_event(fd_meta_event::erase, elem.fd, old, mask, ptr);
             }
             else {
                 iter->mask = mask;
                 d()->handle_event(fd_meta_event::mod, elem.fd, old, mask, ptr);
             }
         }
     }
     m_alterations.clear();
 }