Libevent--事件处理

  • 以I/O事件为例
  • Libevent源码版本2.1.11

1. 注册事件

      应用程序调用event_add函数将其添加到注册事件队列中,并将对应的事件注册到事件多路分发器上。

int
evmap_io_add_(struct event_base *base, evutil_socket_t fd, struct event *ev)
{
    /*  获得event_base的后端I/O复用机制实例 */
    const struct eventop *evsel = base->evsel;   //就是操作删除、添加的函数
    /*  获得event_base中文件描述符与I/O事件队列的映射表*/
    struct event_io_map *io = &base->io;
    /* fd参数对应的I/O事件队列 */
    struct evmap_io *ctx = NULL;
    int nread, nwrite, nclose, retval = 0;
    short res = 0, old = 0;
    struct event *old_ev;

    EVUTIL_ASSERT(fd == ev->ev_fd);

    if (fd < 0)
        return 0;

#ifndef EVMAP_USE_HT
    /*I/O事件队列数组io.entries中,每个文件描述符占用一项,如果fd大于当前数组的大小,则增加数组的大小(扩大后的数组的容量要大于fd)*/
    if (fd >= io->nentries) {
        if (evmap_make_space(io, fd, sizeof(struct evmap_io *)) == -1)
            return (-1);
    }
#endif
    /*  下面这个宏根据EVMAP_USE_HT是否被定义而有不同的实现,但目的都是创建ctx,
    在映射表io中为fd和ctx添加映射关系*/
    GET_IO_SLOT_AND_CTOR(ctx, io, fd, evmap_io, evmap_io_init,
                         evsel->fdinfo_len);   //得到文件描述符为fd的ctx

    nread = ctx->nread;
    nwrite = ctx->nwrite;
    nclose = ctx->nclose;

    /*  原先fd的情况*/
    if (nread)
        old |= EV_READ;
    if (nwrite)
        old |= EV_WRITE;
    if (nclose)
        old |= EV_CLOSED;

    //得到res的情况
    if (ev->ev_events & EV_READ) {
        if (++nread == 1)
            res |= EV_READ;
    }
    if (ev->ev_events & EV_WRITE) {
        if (++nwrite == 1)
            res |= EV_WRITE;
    }
    if (ev->ev_events & EV_CLOSED) {
        if (++nclose == 1)
            res |= EV_CLOSED;
    }

    //如果读/写/关文件次数超限,返回错误
    if (EVUTIL_UNLIKELY(nread > 0xffff || nwrite > 0xffff || nclose > 0xffff)) {
        event_warnx("Too many events reading or writing on fd %d",
            (int)fd);
        return -1;
    }
    if (EVENT_DEBUG_MODE_IS_ON() &&
        (old_ev = LIST_FIRST(&ctx->events)) &&
        (old_ev->ev_events&EV_ET) != (ev->ev_events&EV_ET)) {
        event_warnx("Tried to mix edge-triggered and non-edge-triggered"
            " events on fd %d", (int)fd);
        return -1;
    }

    //如果新事件,则调用监听
    if (res) {
        // 这个extra感觉一点用处也没有
        void *extra = ((char*)ctx) + sizeof(struct evmap_io);
        /* 往事件多路分发器中注册事件,add是事件多路分发器的接口函数之一,
         * 对不同的后端I/O复用机制,这些接口函数有不同的实现
         *  */
        // 正式用epoll往io多路分发器中加入该事件,进行监听
        if (evsel->add(base, ev->ev_fd,
            old, (ev->ev_events & EV_ET) | res, extra) == -1)
            return (-1);
        retval = 1;
    }

    ctx->nread = (ev_uint16_t) nread;
    ctx->nwrite = (ev_uint16_t) nwrite;
    ctx->nclose = (ev_uint16_t) nclose;
    //将ev插到I/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值