您的位置:首页 > 其它

LibEvent中文帮助文档-第6章【创建Event_base】

2016-12-02 11:15 711 查看
[align=center]LiEvent中文帮助文档--第6章【创建Event_base】[/align]

   返回主目录

Libevent

快速可移植非阻塞式网络编程
 
 

修订历史
版本
日期
作者
备注
V1.0
2016-11-15
周勇
Libevent编程中文帮助文档
 

文档是2009-2012年由Nick-Mathewson基于Attribution-Noncommercial-Share
Alike许可协议3.0创建,未来版本将会使用约束性更低的许可来创建.
此外,本文档的源代码示例也是基于BSD的"3条款"或"修改"条款.详情请参考BSD文件全部条款.本文档最新下载地址:
英文:http://libevent.org/
中文:http://blog.csdn.net/zhouyongku/article/details/53431750
请下载并运行"gitclonegit://github.com/nmathewson/libevent-
book.git"获取本文档描述的最新版本源码.

<<上一章>>

6.创建Event_base

在你能使用任何感兴趣的LibEvent函数之前,你需要分配一个或多个event_base结构体.每个event_base结构体拥有一些列的event并且可以通过轮询判断哪个event是激活的.
 
如果一个event_base设置为使用锁定,在多个线程中访问它是安全的,然而只能在一个线程中去处理其事件循环.如果你想在多线程中轮询IO,那么你需要为每个线程分配一个event_base.
 


注意:未来版本将会支持event_base多线程运行
 
每个event_base都有一个方法或后台用来决定哪个event已经准备好了.已经验证的可行方法是:

select

poll

epoll

kqueue

devpoll

evport

win32

用户可以通过一些环境变量来禁用某些后台,如果想要kqueue后端,设置变量EVENT_NOKQUEUE,诸如此类.如果你想要从程序内部关闭后台,请查看下面的event_config_avoid_method()方法.
 

6.1创建默认的Event_base

event_base()函数分配和返回了一个默认参数的event_base,它检验环境变量然后分配了一个指向新的event_base的指针,如果错误则返回NULL.
 
择各种方法时,函数会选择其中操作系统支持的最快方法.
 
接口
struct event_base *event_base_new(void);

就大多数程序而言,这个函数就已经足够了.
event_base_new()函数声明在<event2/event.h>中,首次出现在libevent
1.4.3版.
 

6.2创建复杂的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_new_with_config()函数来获取一个新的event_base,当这些完成后就可以使用event_config_free()函数来释放event_config.
 
接口
int event_config_avoid_method(struct event_config *cfg, const char *method);
enum event_method_feature
{
EV_FEATURE_ET = 0x01,
EV_FEATURE_O1 = 0x02,
EV_FEATURE_FDS = 0x04,
};
int event_config_require_features(struct event_config *cfg,
enum event_method_feature feature);
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
};
int event_config_set_flag(struct event_config *cfg,enum event_base_config_flag flag);

调用event_config_avoid_method()可以通过名字让libevent避免使用特定的可用后端.调event_config_require_feature()让 libevent不使用不能提供所有指定特征的后端.调用event_config_set_flag()让libevent在创建event_base时设置一个或者多个将在下面介绍的运行时标志.
 
vent_config_require_features()可识别的特征值有:

EV_FEATURE_ET:要求支持边沿触发的后端

EV_FEATURE_O1: 要求添加、删除单个事件,或者确定哪个事件激活的操作是O(1)复杂度的后端

EV_FEATURE_FDS:要求支持任意文件描述符,而不仅仅是套接字的后端

event_config_set_flag()可识别的选项值有:

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

EVENT_BASE_FLAG_NO_CACHE_TIME: 不是在事件循环每次准备执行超时回调时检测当前时间,而是在每次超时回调后进行检测.注意:这会消耗更多的CPU时间.

上述操作event_config的函数都在成功时返回0,失败时返回-1.

____________________________________________________________________________________________________
注意
设置event_config,请求OS不能提供的后端是很容易的.比如说,对于libevent2.0.1-alpha,在Windows中是没有O(1)后端的;在Linux中也没有同时提供 EV_FEATURE_FDS和EV_FEATURE_O1特征的后端.如果创建了 libevent不能满足的配置,event_base_new_with_config()会返回NULL.
____________________________________________________________________________________________________

接口
int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus)

虽然这个函数将来可能会在别的平台上起作用,但就目前来讲它只限于使用Windows的完成端口(IOCP)时使用.调用这个函数来通知event_config创建的event_base要在多线程下充分利用好传入的cpu数量.这只是一个暗示,event_base也可能调高cpu数量或降低cpu数量.

接口
int event_config_set_max_dispatch_interval(struct event_config *cfg,const struct timeval *max_interval, int max_callbacks,int min_priority);

该函数能够限制优先级反转,通过在检查更高权限之前限制优先级的事件回调函数调用.如果变量max_interval不为空,则事件循环会去检验函数返回后的时间,如果max_interval时间过去了,那么就会搜寻那些更高优先级的事件.如果max_callbacks参数非负,事件循环也会在max_callbacks个回调函数返回后检查更多事件.这种规则适用于任何事件的优先级高低算法.
 
示例:设置边缘触发
struct event_config *cfg;
struct event_base *base;
int i;
/* My program wants to use edge-triggered events if at all possible. So I’ll try to get a base twice: Once insisting on edge-triggered IO, and once not.*/
for (i=0; i<2; ++i)
{
cfg = event_config_new();
/* I don’t like select.*/
event_config_avoid_method(cfg, "select");
if (i == 0)
event_config_require_features(cfg, EV_FEATURE_ET);
base = event_base_new_with_config(cfg);
event_config_free(cfg);
if (base)
break;
/* If we get here, event_base_new_with_config() returned NULL. If this is the first time around the loop, we’ll try again without setting EV_FEATURE_ET. If this is the second time around the loop, we’ll give up.*/
}

示例:避免优先级反转
struct event_config *cfg;
struct event_base *base;
cfg = event_config_new();
if (!cfg)
/* Handle error */;

/* I’m going to have events running at two priorities. I expect that some of my priority-1 events are going to have pretty slow callbacks,so I don’t want more than 100 msec to elapse (or 5 callbacks) before checking for priority-0 events.*/

struct timeval msec_100 = { 0, 100*1000 };
event_config_set_max_dispatch_interval(cfg, &msec_100, 5, 1);
base = event_base_new_with_config(cfg);
if (!base)
/* Handle error */;
event_base_priority_init(base, 2);

这些函数和类型定义在<event2/event.h>中.
 
EVENT_BASE_FLAG_IGNORE_ENV标志首次出现是在LibEvent2.0.2-alpha版本中,EVENT_BASE_FLAG_PRECISE_TIMER标志首次出现是在LibEvent2.1.2-alpha版本中.event_config_set_num_cpus_hint()函数最新版本在LibEvent2.0.7-rc,event_config_set_max_dispatch_interval()最新在LibEvent2.1.1-alpha版本,其余是在LibEvent2.0.1-alpha中首次出现.
 

<<下一章>>



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息