综述:
libevent基本的操作单元就是event,每一个event代表一系列你感兴趣的状态,包括:
-
一个正在读或者写的文件描述符
-
一个变得可读或者可写的文件描述符(ET模式)
-
超时
-
系统信号的发生
-
用户触发的信号
每一个event有相似的生命周期, 当你建立了一个event,并把他绑定了一个event_base上面的时候,他就处于初始化完成状态,你可以add让它处于pending状态,当event处于pending状态,并且能够触发event的状态触发的时候(例如超时,或者文件状态改变),event就处于active状态,用户定义的callback就会被调用,如果event被设置成了persistent,他会继续等待触发,如果没有设置,他就不处于pending状态了。你也可以通过delete,使它处于非pending状态。
用法:
新建和删除的api如下:
-
#define EV_TIMEOUT 0x01 //时间到了会调用函数
-
#define EV_READ 0x02 //可以读
-
#define EV_WRITE 0x04 //可以写
-
#define EV_SIGNAL 0x08 //事件触发
-
#define EV_PERSIST 0x10 //默认事件是触发一次,当指定此标志时,他会一直触发。可以调用event_del删除
-
#define EV_ET 0x20
-
-
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
-
-
struct event *event_new(struct event_base *base, evutil_socket_t fd,
-
short what, event_callback_fn cb,
-
void *arg);
-
-
void event_free(struct event *event)
event_new函数试着新建并且绑定一个event_base,what参数可以使用上边的列出的参数,如果fd是非负的,他就我们观察的读写的文件描述符,当触发的时候,libevent会调用cb指向的函数,把fd和所有被触发的event的一个位域,还有arg,作为参数。如果失败函数会返回NULL。
生成之后,他处于初始化完成状态,如果我们想让它处于pending状态,我们需要调用event_add()函数。
不管event处于pending或者初始化完成状态,我们都可以调用event_free,释放该结构。
当你想把event自身,作为cb函数的参数的时候,因为我们还没构造出event,我们通过调用下面的函数作为event_new的arg参数:
通过把fd传如负值,我们可以把event伪装成定时器的功能:
-
#define evsignal_add(ev, tv) \
-
event_add((ev),(tv))
-
#define evsignal_del(ev) \
-
event_del(ev)
-
#define evsignal_pending(ev, what, tv_out) \
-
event_pending((ev), (what), (tv_out))
我们也可以注册系统signal:注意每个进程只能有一个event_base注册signal事件。
-
#define evsignal_new(base, signum, callback, arg) \
-
event_new(base, signum, EV_SIGNAL|EV_PERSIST, cb, arg)
-
#define evsignal_add(ev, tv) \
-
event_add((ev),(tv))
-
#define evsignal_del(ev) \
-
event_del(ev)
-
#define evsignal_pending(ev, what, tv_out) \
-
event_pending((ev), (what), (tv_out))
有时候我们把event放到一个结构体里面,在new这个结构体的时候不能调用event_new函数所以我们可以调用下面的函数,但是不建议这么做,这么变你已经固定了event的大小,在版本兼容上不太好。
-
int event_assign(struct event *event, struct event_base *base,evutil_socket_t fd, short what,
-
void (*callback)(evutil_socket_t, short, void *), void *arg)
你可以调用下面的函数,使event处于pending状态和使它处于非pending状态:
-
int event_add(struct event *ev, const struct timeval *tv);
-
int event_del(struct event *ev)
你也可以只是删除制定event的时间触发器,而不影响他的IO。
-
int event_remove_timer(struct event *ev)
你也可以设置event的优先级,当事件触发的时候,libevent会优先调用高优先级的事件,
-
int event_priority_set(struct event *event, int priority)
你可以调用下面的一系列函数来获取,event结构中的数据:
-
evutil_socket_t event_get_fd(const struct event *ev); //获取fd
-
struct event_base *event_get_base(const struct event *ev); //获取base
-
short event_get_events(const struct event *ev); //获取event flag
-
event_callback_fn event_get_callback(const struct event *ev);
-
void *event_get_callback_arg(const struct event *ev);
-
int event_get_priority(const struct event *ev);
-
-
void event_get_assignment(const struct event *event,
-
struct event_base **base_out,
-
evutil_socket_t *fd_out,
-
short *events_out,
-
event_callback_fn *callback_out,
-
void **arg_out)
如果你想定义一个只想执行一次的event,并且让libevent负责他的消亡,你可以调用下面的函数,但是他不支持EV_SIGNAL和EV_PERSIST
-
int event_base_once(struct event_base *, evutil_socket_t, short,
-
void (*)(evutil_socket_t, short, void *), void *, const struct timeval *)
最后你可以主动触发一个事件,无论他处于pending状态与否:
-
void event_active(struct event *ev, int what, short ncalls)
例子:
gcc test.cpp -levent
-
#include<event2/event.h>
-
#include<stdio.h>
-
void cb_func(evutil_socket_t fd, short what, void *arg)
-
{
-
printf("get alerted !");
-
}
-
int main()
-
{
-
struct event_base * base;
-
struct event *ev1,*ev2;
-
struct timeval five_seconds = {5,0};
-
base = event_base_new();
-
if(!base)
-
return 0;
-
ev1 = event_new(base, -1, EV_TIMEOUT,cb_func,NULL);
-
ev2 = event_new(base, -1, EV_TIMEOUT, cb_func,NULL);
-
// event_add(ev1,&five_seconds);
-
// struct timeval five_seconds1 = {15,0};
-
// event_add(ev2,&five_seconds1);
-
event_active(ev1,EV_TIMEOUT,0);
-
int tmp = event_base_dispatch(base);
-
printf("%d",tmp);
-
return 1;
-
}
阅读(5715) | 评论(0) | 转发(2) |