libevent 写事件处理

bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
{
    struct bufferevent *bufev = arg;
    struct bufferevent_private *bufev_p = BEV_UPCAST(bufev);
    int res = 0;
    short what = BEV_EVENT_WRITING;
    int connected = 0;
    ev_ssize_t atmost = -1;

    bufferevent_incref_and_lock_(bufev);

    if (event == EV_TIMEOUT) {// 注册时同时注册定时事件和可写事件,
        /* Note that we only check for event==EV_TIMEOUT. If
         * event==EV_TIMEOUT|EV_WRITE, we can safely ignore the
         * timeout, since a read has occurred */
        what |= BEV_EVENT_TIMEOUT;
        goto error;
    }
    if (bufev_p->connecting) { // 判断连接状态是否还有效
        int c = evutil_socket_finished_connecting_(fd);
        /* we need to fake the error if the connection was refused
         * immediately - usually connection to localhost on BSD */
        if (bufev_p->connection_refused) {
            bufev_p->connection_refused = 0;
            c = -1;
        }

        if (c == 0)
            goto done;

        bufev_p->connecting = 0;
        if (c < 0) {
            event_del(&bufev->ev_write);
            event_del(&bufev->ev_read);
            bufferevent_run_eventcb_(bufev, BEV_EVENT_ERROR, 0);
            goto done;
        } else {
            connected = 1;
            bufferevent_socket_set_conn_address_fd_(bufev, fd);
            bufferevent_run_eventcb_(bufev,
                    BEV_EVENT_CONNECTED, 0);
            if (!(bufev->enabled & EV_WRITE) ||
                bufev_p->write_suspended) {
                event_del(&bufev->ev_write);
                goto done;
            }
        }
    }

    atmost = bufferevent_get_write_max_(bufev_p);

    if (bufev_p->write_suspended)// 看是否已经被挂起了
        goto done;

    if (evbuffer_get_length(bufev->output)) {  // 获取buffer大小
        evbuffer_unfreeze(bufev->output, 1);// 锁住buffer ,支持多线程
        res = evbuffer_write_atmost(bufev->output, fd, atmost);// 写数据->send
        evbuffer_freeze(bufev->output, 1);
        if (res == -1) {// 写失败了
            int err = evutil_socket_geterror(fd);
            if (EVUTIL_ERR_RW_RETRIABLE(err))// 如果不能再写了
                goto reschedule;
            what |= BEV_EVENT_ERROR;
        } else if (res == 0) {// 如果已经写完了,write len = 0;
            /* eof case
               XXXX Actually, a 0 on write doesn't indicate
               an EOF. An ECONNRESET might be more typical.
             */
            what |= BEV_EVENT_EOF;
        }
        if (res <= 0)
            goto error;

        bufferevent_decrement_write_buckets_(bufev_p, res);
    }

    if (evbuffer_get_length(bufev->output) == 0) {// 如果数据已经发送完了
        event_del(&bufev->ev_write);// 数据发完了,删除写事件
    }

    /*
     * Invoke the user callback if our buffer is drained or below the
     * low watermark.
     */
    if (res || !connected) {
        bufferevent_trigger_nolock_(bufev, EV_WRITE, 0);
    }

    goto done;

 reschedule:
    if (evbuffer_get_length(bufev->output) == 0) {// 写异常了,这里删除写事件
        event_del(&bufev->ev_write);
    }
    goto done;

 error:
    bufferevent_disable(bufev, EV_WRITE);
    bufferevent_run_eventcb_(bufev, what, 0);

 done:
    bufferevent_decref_and_unlock_(bufev);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值