time-test例子
第一个例子位于libevent源码libevent-2.1.12-stable/sample/time-test.c
下面,是一个超时事件回调。
int
main(int argc, char **argv)
{
struct event timeout;
struct timeval tv;
struct event_base *base;
int flags;
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
(void)WSAStartup(wVersionRequested, &wsaData);
#endif
if (argc == 2 && !strcmp(argv[1], "-p")) {
event_is_persistent = 1;
flags = EV_PERSIST;
} else {
event_is_persistent = 0;
flags = 0;
}
/* Initialize the event library */
base = event_base_new();
/* Initialize one event */
event_assign(&timeout, base, -1, flags, timeout_cb, (void*) &timeout);
evutil_timerclear(&tv);
tv.tv_sec = 2;
event_add(&timeout, &tv);
evutil_gettimeofday(&lasttime, NULL);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
event_base_dispatch(base);
return (0);
}
从main函数看起
- 创建了三个变量:代表超时事件的timeout、存储时间的tv和用于管理事件的
event_base
结构体指针变量(使用指针是因为event_base
结构体是一个库内部实现的结构体,对外只提供操作接口,不暴露实现细节)。 - 根据参数设置事件的flag(是否持久)。
event_base_new()
:通过接口分配一个event_base
结构体,同时也代表着事件库的初始化。event_assign
:初始化timeout事件,指定管理事件的event_base
、事件flag、事件触发的回调以及回调参数。event_add
:添加事件并设置事件的超时事件。event_base_dispatch
:开始事件循环,等待回调。
static void
timeout_cb(evutil_socket_t fd, short event, void *arg)
{
struct timeval newtime, difference;
struct event *timeout = arg;
double elapsed;
evutil_gettimeofday(&newtime, NULL);
evutil_timersub(&newtime, &lasttime, &difference);
elapsed = difference.tv_sec +
(difference.tv_usec / 1.0e6);
printf("timeout_cb called at %d: %.3f seconds elapsed.\n",
(int)newtime.tv_sec, elapsed);
lasttime = newtime;
if (! event_is_persistent) {
struct timeval tv;
evutil_timerclear(&tv);
tv.tv_sec = 2;
event_add(timeout, &tv);
}
}
接着看回调,回调函数的类型都是固定的typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
- 通过传给回调的参数arg获取到之前的event,因为在之前初始化timeout事件的时候将事件本身设置为了回调的参数。
- 计算事件触发时的时间并更新lasttime。
- 判断是否事件持久,如果事件持久,重新把事件添加到事件循环中。
signal-test例子
这个例子位于libevent-2.1.12-stable/sample/signal-test.c
,是一个信号事件回调
int
main(int argc, char **argv)
{
struct event *signal_int = NULL;
struct event_base* base;
int ret = 0;
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
(void) WSAStartup(wVersionRequested, &wsaData);
#endif
/* Initialize the event library */
base = event_base_new();
if (!base) {
ret = 1;
goto out;
}
/* Initialize one event */
signal_int = evsignal_new(base, SIGINT, signal_cb, event_self_cbarg());
if (!signal_int) {
ret = 2;
goto out;
}
event_add(signal_int, NULL);
event_base_dispatch(base);
out:
if (signal_int)
event_free(signal_int);
if (base)
event_base_free(base);
return ret;
}
先看main函数
- 创建事件event和管理事件的event_base
event_base_new
:初始化事件库evsignal_new
:初始化超时事件,虽然叫evsignal_new
但本质是event_new
创建事件event_add
:添加信号事件event_base_dispatch
:开启事件循环,等待信号事件回调- 释放事件和事件管理器
static void
signal_cb(evutil_socket_t fd, short event, void *arg)
{
struct event *signal = arg;
printf("signal_cb: got signal %d\n", event_get_signal(signal));
if (called >= 2)
event_del(signal);
called++;
}
接着看信号事件回调,很简单,就是打印信号并在第三次回调时删除事件