libevent定时器是怎么实现的
发布日期:2021-05-08 05:59:08 浏览次数:21 分类:精选文章

本文共 3218 字,大约阅读时间需要 10 分钟。

1. 定时器是怎么实现的

在之前的文章里我们讲过,libevent最后处理都是在event_base_loop调用了相应的dispatch函数,定时器也是在dispatch函数中处理的。

还是以epoll为例,在epoll_dispatch函数有以下一段代码:

if (tv != NULL) {     timeout = evutil_tv_to_msec_(tv);  if (timeout < 0 || timeout > MAX_EPOLL_TIMEOUT_MSEC) {      /* Linux kernels can wait forever if the timeout is    * too big; see comment on MAX_EPOLL_TIMEOUT_MSEC. */   timeout = MAX_EPOLL_TIMEOUT_MSEC;  } } epoll_apply_changes(base); event_changelist_remove_all_(&base->changelist, base); EVBASE_RELEASE_LOCK(base, th_base_lock); //epoll_wait的最后一个参数即为超时时间 res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout); EVBASE_ACQUIRE_LOCK(base, th_base_lock); if (res == -1) {     if (errno != EINTR) {      event_warn("epoll_wait");   return (-1);  }  return (0); }

从上面代码可以看出,是通过epoll_wait的超时机制来实现定时器的,这样我们就可以知道,其实定时器就是利用了select和epoll_wait等这些系统函数的超时机制,才实现的定时器。

总的来讲,定时器就是在事件主循环中,等待网络调用超时,当超时以后,将任务写入队列,然后处理队列,调用回调函数,这样就实现了定时器。

2. 定时器代码实现

看libevent源代码中例子:

#include 
#include
#include
#include
#ifdef EVENT__HAVE_SYS_TIME_H#include
#endif#include
#include
#include
#include
#include
#include
#include
#include
struct timeval lasttime;int event_is_persistent;static voidtimeout_cb(evutil_socket_t fd, short event, void *arg){ struct timeval newtime, difference; struct event *timeout = (struct event*)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); }}intmain(int argc, char **argv){ struct event timeout; struct timeval tv; struct event_base *base; int flags; if (argc == 2 && !strcmp(argv[1], "-p")) { event_is_persistent = 1; flags = EV_PERSIST; } else { event_is_persistent = 0; flags = 0; } /* Initalize the event library */ base = event_base_new(); /* Initalize one event */ event_assign(&timeout, base, -1, flags, timeout_cb, (void*) &timeout); evutil_timerclear(&tv); tv.tv_sec = 3; event_add(&timeout, &tv); evutil_gettimeofday(&lasttime, NULL); event_base_dispatch(base); return (0);}

实现三秒调用一次回调函数,执行结果如下:

timeout_cb called at 1535528104: 3.001 seconds elapsed.timeout_cb called at 1535528107: 3.000 seconds elapsed.timeout_cb called at 1535528110: 3.001 seconds elapsed.timeout_cb called at 1535528113: 2.999 seconds elapsed.timeout_cb called at 1535528116: 3.000 seconds elapsed.timeout_cb called at 1535528119: 3.002 seconds elapsed.timeout_cb called at 1535528122: 2.999 seconds elapsed.timeout_cb called at 1535528125: 3.001 seconds elapsed.timeout_cb called at 1535528128: 3.000 seconds elapsed.timeout_cb called at 1535528131: 3.000 seconds elapsed.timeout_cb called at 1535528134: 2.999 seconds elapsed.timeout_cb called at 1535528137: 3.000 seconds elapsed.timeout_cb called at 1535528140: 3.000 seconds elapsed.timeout_cb called at 1535528143: 3.000 seconds elapsed.timeout_cb called at 1535528146: 3.000 seconds elapsed.timeout_cb called at 1535528149: 3.002 seconds elapsed.
上一篇:libevent简单服务端和客户端实现
下一篇:libevent绑定、监听和读写数据

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2025年04月03日 16时41分16秒