Libevent应用 (一) 建立event_base

1 建立event_base

​ event_base算是Libevent最基础、最重要的对象,因为修改配置、添加事件等,基本都需要将它作为参数传递进去。 

1.1创建默认的event_base

​ 这个对象通过event_base_new创建:

#include <event2/event.h>
struct event_base *event_base_new(void);

​ event_base_new()函数分配并且返回一个新的具有默认设置的event_base。函数会检测环境变量,返回一个到event_base的指针。如果发生错误,则返回NULL。选择各种方法时,函数会选择OS支持的最快方法。

​ 使用完event_base之后,使用event_base_free()进行释放。

void event_base_free(struct event_base *base);

注意:这个函数不会释放当前与event_base关联的任何事件,或者关闭他们的套接字,或者释放任何指针。

编译的时候需要加上-levent

1.2 检查后端的方法

​ 有时候需要检查event_base支持哪些特征,或者当前使用哪种方法。

const char **event_get_supported_methods(void);
const char *event_get_version();

​ event_get_supported_methods()函数返回一个指针,指向libevent支持的方法名字数组。这个数组的最后一个元素是NULL。

#include <event2/event.h>
#include <stdio.h>
int main(void)
{
    int i = 0;
    const char **methods = event_get_supported_methods();
    printf("Starting Libevent %s.  Available methods are:\n", event_get_version());
    while(methods[i] != NULL) 
    {
        printf("%s\n", methods[i++]);
    }
}

1.3 创建复杂的event_base

​ 要对取得什么类型的event_base有更多的控制,就需要使用event_config。event_config是一个容纳event_base配置信息的不透明结构体。需要event_base时,将event_config传递给event_base_new_with_config()。

struct event_config *event_config_new(void);
struct event_base *event_base_new_with_config(const struct event_config *cfg);
void event_config_free(struct event_config *cfg);

​ 要使用这些函数分配event_base,先调用event_config_new()分配一个event_config。然后,对event_config调用其它函数,设置所需要的event_base特征。最后,调用event_base_new_with_config()获取新的event_base。完成工作后,使用event_config_free()释放event_config。

1.3.1 禁用特定后端

​ 调用event_config_avoid_method()可以通过名字让libevent避免使用特定的可用后端。成功时返回0,失败时返回-1。

int event_config_avoid_method(struct event_config *cfg, const char *method);
const char* method;//指定特定的后端,例如"select" "poll" "epoll"

1.3.2 设置特征

​ 调用event_config_require_feature()让libevent不使用不能提供所有指定特征的后端。成功时返回0,失败时返回-1。

int event_config_require_features(struct event_config *cfg,
                                  enum event_method_feature feature);
enum event_method_feature {
    EV_FEATURE_ET = 0x01, //要求支持边沿触发的后端
    EV_FEATURE_O1 = 0x02, //要求添加、删除单个事件,或者确定哪个事件激活的操作是O(1)复杂度的后端
    EV_FEATURE_FDS = 0x04, //要求支持任意文件描述符,而不仅仅是套接字的后端
};

注意:

​ 设置event_config,请求OS不能提供的后端是很容易的。

​ 比如说,对于libevent 2.0.1-alpha,在Windows中是没有O(1)后端的;

​ 在Linux中也没有同时提供EV_FEATURE_FDS和EV_FEATURE_O1特征的后端。

​ 如果创建了libevent不能满足的配置,event_base_new_with_config()会返回NULL。

1.3.3 设置标志

​ 调用event_config_set_flag()让libevent在创建event_base时设置一个或者多个将在下面介绍的运行时标志。成功时返回0,失败时返回-1。

int event_config_set_flag(struct event_config *cfg,
    enum event_base_config_flag flag);

enum event_base_config_flag {
    EVENT_BASE_FLAG_NOLOCK = 0x01, 
    EVENT_BASE_FLAG_IGNORE_ENV = 0x02,  
    EVENT_BASE_FLAG_STARTUP_IOCP = 0x04, 
    EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08, 
    EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10,
    EVENT_BASE_FLAG_PRECISE_TIMER = 0x20
};
EVENT_BASE_FLAG_NOLOCK://不要为event_base分配锁。设置这个选项可以为event_base节省一点用于锁定和解锁的时间,但是让在多个线程中访问event_base成为不安全的。

EVENT_BASE_FLAG_IGNORE_ENV://选择使用的后端时,不要检测EVENT_*环境变量。使用这个标志需要三思:这会让用户更难调试你的程序与libevent的交互。

EVENT_BASE_FLAG_STARTUP_IOCP://仅用于Windows,让libevent在启动时就启用任何必需的IOCP分发逻辑,而不是按需启用。

EVENT_BASE_FLAG_NO_CACHE_TIME://不缓存时间,在每个超时事件之后重新读取系统时间. 
  
EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST://告诉libevent,如果决定使用epoll后端,可以安全地使用更快的基于changelist的后端。epoll-changelist后端可以在后端的分发函数调用之间,同样的fd多次修改其状态的情况下,避免不必要的系统调用。但是如果传递任何使用dup()或者其变体克隆的fd给libevent,epoll-changelist后端会触发一个内核bug,导致不正确的结果。在不使用epoll后端的情况下,这个标志是没有效果的。也可以通过设置EVENT_EPOLL_USE_CHANGELIST环境变量来打开epoll-changelist选项。

1.3.4 event_base优先级

​ libevent支持为事件设置多个优先级。然而,event_base默认只支持单个优先级。可以调用event_base_priority_init()设置event_base的优先级数目。

int event_base_priority_init(struct event_base *base, int n_priorities);

​ 成功时这个函数返回0,失败时返回-1。base是要修改的event_base,n_priorities是要支持的优先级数目,这个数目至少是1。每个新的事件可用的优先级将从0(最高)到n_priorities-1(最低)。

​ 常量EVENT_MAX_PRIORITIES表示n_priorities的上限。调用这个函数时为n_priorities给出更大的值是错误的。

注意:

​ 必须在任何事件激活之前调用这个函数,最好在创建event_base后立刻调用。

1.3.5 定制event_base代码
struct event_config *cfg;
struct event_base *base;

cfg = event_config_new();
event_config_avoid_method(cfg, "select");   //避免使用低效率select
event_config_require_features(cfg, EV_FEATURE_ET);  //使用具有边沿触发类型的后端
event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
base = event_base_new_with_config(cfg);
event_config_free(cfg);

event_base_priority_init(base, 3); //设置优先级
event_base_free(base);

1.3.6 检查后端和特征

​ event_base_get_method()返回event_base正在使用的方法。event_base_get_features()返回event_base支持的特征的比特掩码。

const char *event_base_get_method(const struct event_base *base);
enum event_method_feature event_base_get_features(const struct event_base *base);

示例代码如下:

#include <stdio.h>
#include <event2/event.h>
int main(void)
{
    struct event_base *base;
    enum event_method_feature f;
    base = event_base_new();
    if (!base) 
    {
        puts("Couldn't get an event_base!");
    } 
    else 
    {
        printf("Using Libevent with backend method %s.\n", event_base_get_method(base));
        f = event_base_get_features(base);
        if ((f & EV_FEATURE_ET))
            printf("  Edge-triggered events are supported.\n");
        if ((f & EV_FEATURE_O1))
            printf("  O(1) event notification is supported.\n");
        if ((f & EV_FEATURE_FDS))
            printf("  All FD types are supported.\n");
        puts("");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值