Libevent 事件生成

事件堆实例生成:

struct event_base *
event_base_new(void)
{
    struct event_base *base = NULL;
    struct event_config *cfg = event_config_new();
    if (cfg) {
        base = event_base_new_with_config(cfg);
        event_config_free(cfg);
    }
    return base;
}
event_config 结构如下
struct event_config {
    TAILQ_HEAD(event_configq, event_config_entry) entries;

    int n_cpus_hint;
    struct timeval max_dispatch_interval;
    int max_dispatch_callbacks;
    int limit_callbacks_after_prio;
    enum event_method_feature require_features;
    enum event_base_config_flag flags;
};

struct event_base *
event_base_new_with_config(const struct event_config *cfg)
{
    int i;
    struct event_base *base;

    if ((base = mm_calloc(1, sizeof(struct event_base))) == NULL) {
        event_warn("%s: calloc", __func__);
        return NULL;
    }

    if (cfg)
        base->flags = cfg->flags;

    should_check_environment =
        !(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV));

    {
        struct timeval tmp;
        int precise_time =
            cfg && (cfg->flags & EVENT_BASE_FLAG_PRECISE_TIMER);
        int flags;
        if (should_check_environment && !precise_time) {
            precise_time = evutil_getenv_("EVENT_PRECISE_TIMER") != NULL;
            base->flags |= EVENT_BASE_FLAG_PRECISE_TIMER;
        }
        flags = precise_time ? EV_MONOT_PRECISE : 0;
        evutil_configure_monotonic_time_(&base->monotonic_timer, flags);

        gettime(base, &tmp);
    }
  //初始化小根堆
    min_heap_ctor_(&base->timeheap);

    base->sig.ev_signal_pair[0] = -1;
    base->sig.ev_signal_pair[1] = -1;
    base->th_notify_fd[0] = -1;
    base->th_notify_fd[1] = -1;

    TAILQ_INIT(&base->active_later_queue);
    //初始化io singal哈系表
    evmap_io_initmap_(&base->io);
    evmap_signal_initmap_(&base->sigmap);
    event_changelist_init_(&base->changelist);

    base->evbase = NULL;

    if (cfg) {        //初始化base的dispatch 时间间隔 -1 影响epoll  select poll 阻塞时间参数
        memcpy(&base->max_dispatch_time,
            &cfg->max_dispatch_interval, sizeof(struct timeval));
        base->limit_callbacks_after_prio =
            cfg->limit_callbacks_after_prio;
    } else {
        base->max_dispatch_time.tv_sec = -1;
        base->limit_callbacks_after_prio = 1;
    }
    if (cfg && cfg->max_dispatch_callbacks >= 0) {
        base->max_dispatch_callbacks = cfg->max_dispatch_callbacks;
    } else {
        base->max_dispatch_callbacks = INT_MAX;
    }
    if (base->max_dispatch_callbacks == INT_MAX &&
        base->max_dispatch_time.tv_sec == -1)
        base->limit_callbacks_after_prio = INT_MAX;
   // 选用事件模型  select  poll devpoll 或者epoll   // eventops 定义选取合适模型
    for (i = 0; eventops[i] && !base->evbase; i++) {
        if (cfg != NULL) {
            /* determine if this backend should be avoided */
            if (event_config_is_avoided_method(cfg,
                eventops[i]->name))
                continue;
            if ((eventops[i]->features & cfg->require_features)
                != cfg->require_features)
                continue;
        }

        /* also obey the environment variables */
        if (should_check_environment &&
            event_is_method_disabled(eventops[i]->name))
            continue;
        //指向某个模型 如epoll
        base->evsel = eventops[i];
        //evbase 指向初始化完成的实例
        base->evbase = base->evsel->init(base);
    }

    if (base->evbase == NULL) {
        event_warnx("%s: no event mechanism available",
            __func__);
        base->evsel = NULL;
        event_base_free(base);
        return NULL;
    }

    if (evutil_getenv_("EVENT_SHOW_METHOD"))
        event_msgx("libevent using: %s", base->evsel->name);

    /* allocate a single active event queue */
    if (event_base_priority_init(base, 1) < 0) {
        event_base_free(base);
        return NULL;
    }

    /* prepare for threading */
  //有关多线程的base 初始化

    return (base);
}

大致就时base_event 的初始化, 选取一个io复用模型, Linux下优先选择epoll。

事件生成event_new:

int
event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg)
{
    if (!base)
        base = current_base;
    if (arg == &event_self_cbarg_ptr_)
        arg = ev;

    event_debug_assert_not_added_(ev);

    ev->ev_base = base;

    ev->ev_callback = callback;
    ev->ev_arg = arg;
    ev->ev_fd = fd;
    ev->ev_events = events;
    ev->ev_res = 0;
    ev->ev_flags = EVLIST_INIT;
    ev->ev_ncalls = 0;
    ev->ev_pncalls = NULL;

    if (events & EV_SIGNAL) {
        if ((events & (EV_READ|EV_WRITE|EV_CLOSED)) != 0) {
            event_warnx("%s: EV_SIGNAL is not compatible with "
                "EV_READ, EV_WRITE or EV_CLOSED", __func__);
            return -1;
        }
        ev->ev_closure = EV_CLOSURE_EVENT_SIGNAL;
    } else {
        if (events & EV_PERSIST) {
            evutil_timerclear(&ev->ev_io_timeout);
            ev->ev_closure = EV_CLOSURE_EVENT_PERSIST;
        } else {
            ev->ev_closure = EV_CLOSURE_EVENT;
        }
    }
    //初始化ev中的小根堆索引为 -1
    min_heap_elem_init_(ev);

    if (base != NULL) {
        /* by default, we put new events into the middle priority */
        ev->ev_pri = base->nactivequeues / 2;
    }

    event_debug_note_setup_(ev);

    return 0;
}
时间: 2024-11-05 09:53:51

Libevent 事件生成的相关文章

[libevent]事件主循环

libevent事件处理的中心部分--事件主循环,根据系统提供的事件多路分发机制执行事件循环,对已注册的就绪事件,调用注册事件的回调函数来处理事件. 事件处理主循环 libevent的事件主循环主要是通过event_base_loop ()函数完成的,其主要操作如下面的流程图所示,event_base_loop所作的就是持续执行下面的循环. 上图的简单描述就是: 校正系统当前时间. 将当前时间与存放时间的最小堆中的时间依次进行比较,将所有时间小于当前时间的定时器事件从堆中取出来加入到活动事件队列

for for in 给已有的li绑定click事件生成新的li也有click事件

想要给已有的li元素绑定一个click事件,点击生成新的li元素,并且新的li元素也要有click事件 //不能用for循环给每个li绑定click事件 因为这样的话 后面新生成的li就没有click事件 //即使用下面的获取dom元素方法 具有实时性 也不能给新生成的li绑定clcik事件   这两个方法是 实时的 HTMLCollection 不能直接forEach循环let ali1 = oul.getElementsByClassName('li') let ali2 = oul.get

预生成事件/生成后事件命令行对话框

可以使用以下任意宏来指定文件位置,或在存在多重选择的情况下获取输入文件的实际名称.  这些宏不区分大小写. 宏 说明 $(ConfigurationName) 当前项目配置的名称(例如,“Debug|Any CPU”). $(OutDir) 输出文件目录的路径,相对于项目目录.  这解析为“输出目录”属性的值.  它包括尾部的反斜杠“\”. $(DevEnvDir) Visual Studio 2010 的安装目录(定义为驱动器 + 路径):包括尾部的反斜杠“\”. $(PlatformName

libevent::事件::定时器2

#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg)) #include <cstdio> #include <errno.h> #include <sys/types.h> #include <event.h> #include <event2/event.h> #include <event2/event_struct.h> #include <e

原生js怎么为动态生成的标签添加各种事件

这几天用zepto.js写了不少事件,突然想到一个问题,那就是原生的js如何给动态生成的标签添加事件?因为这些标签都是后来通过ajax或者运行其他点击事件生成的,那么如果之前给他们写事件他们这个dom对象是找不到的,jq通过事件委托解决了这个问题,但是原生js这个问题该怎么解决呢?我在网上查了很多资料,好像只有一种办法,那就是在生成标签并把标签添加到html结构中后再添加对于这个新标签的各种事件,如果有更好的方法,欢迎提出来. <!DOCTYPE html> <html lang=&qu

Visual studio 生成后事件说明

在"配置属性->生成事件->生成后事件"属性页中的"命令行"编辑框中输入如下命令: copy "$(ProjectDir)$(IntDir)\$(ProjectName).tlb" "$(SolutionDir)\bin\$(ProjectName).tlb" 就可将$(ProjectDir)$(IntDir)\$(ProjectName).tlb文件拷贝到$(SolutionDir)\bin目录下.(宏的含义参见

jQuery向动态生成的内容添加事件响应

jQuery live() 方法是给所有匹配的元素附加一个事件处理函数,即使这个元素是以后通过append,prepend,after等事件生成后的内容也依然有效. 这个方法可以看做是 .bind() 方法的一个变体.使用 .bind() 时,选择器匹配的元素会附加一个事件处理函数,而以后再添加的元素则不会有.为此需要再使用一次 .bind() 才行.比如说: 1 <body> <div class="clickme">Click here</div>

使用libevent进行多线程socket编程demo

最近要对一个用libevent写的C/C++项目进行修改,要改成多线程的,故做了一些学习和研究. libevent是一个用C语言写的开源的一个库.它对socket编程里的epoll/select等功能进行了封装,并且使用了一些设计模式(比如反应堆模式),用事件机制来简化了socket编程.libevent的好处网上有很多,但是初学者往往都看不懂.我打个比方吧,1)假设有N个客户端同时往服务端通过socket写数据,用了libevent之后,你的server程序里就不用再使用epoll或是sele

Libevent库学习笔记

Libevent是一个事件触发的网络库,适用于windows.linux.bsd等多种平台,Libevent在底层select.pool.kqueue和epoll等机制基础上,封装出一致的事件接口.可以注册可读.可写.超时等事件,指定回调函数:当事件发生后,Libevent调用回调函数,可以在回调函数里实现自定义功能.编译库代码,编译脚本会判断OS支持哪种类型的事件机制(select.epoll或kqueue),然后条件编译相应代码,供上层使用的接口仍然是保持统一的. 著名分布式缓存软件memc