Exemplo n.º 1
0
void Dispatcher::AddWrite(net::Connection& _c, const Callback& write_cb) {
    assert(dynamic_cast<Connection*>(&_c));
    Connection& c = static_cast<Connection&>(_c);

    std::unique_lock<std::mutex> d_lock(d_->mutex_);
    Watch& w = GetWatch(&c);
    w.write_cb.emplace_back(write_cb);
    if (!w.active) {
        std::unique_lock<std::mutex> c_lock(c.d_->mutex_);
        c.d_->watcher_.insert(this);
        w.active = true;
    }
    // our virtual sockets are always writable: issue notification.
    Notify(&c);
}
Exemplo n.º 2
0
//! Register a buffered read callback and a default exception callback.
void Dispatcher::AddRead(net::Connection& _c, const Callback& read_cb) {
    assert(dynamic_cast<Connection*>(&_c));
    Connection& c = static_cast<Connection&>(_c);

    std::unique_lock<std::mutex> d_lock(d_->mutex_);
    Watch& w = GetWatch(&c);
    w.read_cb.emplace_back(read_cb);
    if (!w.active) {
        std::unique_lock<std::mutex> c_lock(c.d_->mutex_);
        c.d_->watcher_.insert(this);
        w.active = true;
        // if already have a packet, issue notification.
        if (c.d_->inbound_.size())
            Notify(&c);
    }
}
Exemplo n.º 3
0
void Dispatcher::DispatchOne(const std::chrono::milliseconds& timeout) {

    Connection* c = nullptr;
    if (!notify_.pop_for(c, timeout)) {
        sLOG << "DispatchOne timeout";
        return;
    }

    if (c == nullptr) {
        sLOG << "DispatchOne interrupt";
        return;
    }

    sLOG << "DispatchOne run";

    std::unique_lock<std::mutex> d_lock(mutex_);

    Map::iterator it = map_.find(c);
    if (it == map_.end()) {
        sLOG << "DispatchOne expired connection?";
        return;
    }

    Watch& w = it->second;
    assert(w.active);

    std::unique_lock<std::mutex> c_lock(c->mutex_);

    // check for readability
    if (w.read_cb.size() && c->inbound_.size()) {

        while (c->inbound_.size() && w.read_cb.size()) {
            c_lock.unlock();
            d_lock.unlock();

            bool ret = true;
            try {
                ret = w.read_cb.front()();
            }
            catch (std::exception& e) {
                LOG1 << "Dispatcher: exception " << typeid(e).name()
                     << "in read callback.";
                LOG1 << "  what(): " << e.what();
                throw;
            }

            d_lock.lock();
            c_lock.lock();

            if (ret) break;
            w.read_cb.pop_front();
        }

        if (w.read_cb.size() == 0 && w.write_cb.size() == 0) {
            // if all callbacks are done, listen no longer.
            c->watcher_.erase(this);
            map_.erase(it);
            return;
        }
    }

    // "check" for writable. virtual sockets are always writable.
    if (w.write_cb.size()) {

        while (w.write_cb.size()) {
            c_lock.unlock();
            d_lock.unlock();

            bool ret = true;
            try {
                ret = w.write_cb.front()();
            }
            catch (std::exception& e) {
                LOG1 << "Dispatcher: exception " << typeid(e).name()
                     << "in write callback.";
                LOG1 << "  what(): " << e.what();
                throw;
            }

            d_lock.lock();
            c_lock.lock();

            if (ret) break;
            w.write_cb.pop_front();
        }

        if (w.read_cb.size() == 0 && w.write_cb.size() == 0) {
            // if all callbacks are done, listen no longer.
            c->watcher_.erase(this);
            map_.erase(it);
            return;
        }
    }
}