libevent的event_base源码详解

event_base

libevent 中,event_base(事件基) 是一个核心组件,它负责管理所有的事件及其相关的回调函数。event_base 实际上是一个事件循环(Event Loop)的基础,用于监控和调度事件。每个 event_base 实例都是一个独立的事件管理系统,可以用来管理一组事件,并且可以独立于其他 event_base 实例运行。

创建事件基

在开始使用 libevent 之前,需要创建一个 event_base 实例。这通常是在程序启动时完成的,因为 event_base 是整个事件处理系统的中心。

event_base 可以通过以下两种方式创建:

  • 使用 event_base_new 函数

    1
    struct event_base *event_base_new(void);

    这个函数创建一个新的 event_base 实例,并返回指向该实例的指针。如果创建失败,则返回 NULL

  • 使用 event_base_new_with_config 函数

    1
    struct event_base *event_base_new_with_config(const struct event_config *config);

    这个函数允许你指定一些配置选项来创建 event_base。例如,你可以指定底层事件机制(如 pollepoll 等)。

初始化和配置

在创建 event_base 实例之后,你可能还需要对其进行一些初始化和配置操作,以适应特定的需求。例如:

  • 启用调试模式

    1
    void event_enable_debug_mode(void);

    调用此函数可以启用调试模式,这会在 libevent 内部增加额外的日志记录。

  • 设置内存管理函数

    1
    void event_set_mem_functions(void *(*malloc_fn)(size_t), void (*free_fn)(void *));

    你可以覆盖 libevent 使用的内存分配和释放函数,这对于需要特定内存管理策略的应用程序很有用。

  • 初始化线程支持
    如果你的应用程序是多线程的,需要使用 evthread 函数来初始化线程支持。例如:

    1
    2
    #include <event2/thread.h>
    int evthread_use_pthreads(void);

    这个函数初始化线程支持,使得 libevent 可以在多线程环境中安全地使用。

添加事件

创建好 event_base 后,你需要添加事件到其中。事件可以是基于文件描述符的(如监听套接字的读写事件),也可以是基于定时器或信号的。

添加文件描述符事件

创建一个文件描述符事件并将其添加到 event_base 中:

1
struct event *event_new(struct event_base *base, int fd, short flags, void (*callback)(evutil_socket_t, short, void *), void *arg);

这个函数创建一个事件,并返回指向该事件的指针。你需要将事件添加到 event_base 中:

1
int event_add(struct event *ev, const struct timeval *tv);

event_add 函数将事件添加到 event_base 中,并设置事件的超时时间(如果有的话)。

添加定时器事件

创建一个定时器事件:

1
struct event *evtimer_new(struct event_base *base, void (*callback)(evutil_socket_t, short, void *), void *arg);

然后添加定时器事件:

1
int event_add(struct event *ev, const struct timeval *tv);

定时器事件可以设置超时时间,当超时时间到达时,对应的回调函数会被调用。

运行事件循环

创建并配置好 event_base 之后,你需要运行事件循环来处理事件。libevent 提供了多种方式来运行事件循环:

  • 使用 event_base_dispatch 函数

    1
    int event_base_dispatch(struct event_base *base);

    这个函数进入事件循环,并一直运行直到没有更多的事件需要处理或手动退出。

  • 使用 event_base_loop 函数

    1
    int event_base_loop(struct event_base *base, int flags);

    这个函数允许你更细粒度地控制事件循环的行为,例如你可以指定只运行一次事件循环(EVENT_BASE_ONCE)。

  • 退出事件循环

    1
    void event_base_loopexit(struct event_base *base, void *sig);

    这个函数允许你在事件循环内部安全地退出事件循环。

管理事件基

除了创建和运行事件基之外,还有一些函数用于管理和维护 event_base

  • 销毁事件基

    1
    void event_base_free(struct event_base *base);

    这个函数销毁 event_base 及其所有关联的事件。

  • 检查事件基状态

    1
    int event_base_is_running(const struct event_base *base);

    这个函数检查 event_base 是否正在运行。

示例代码

//[todo]