libevent源码浅析(四)

最近刚刚一个项目自己用libevent,因此这几天又把libevent的代码拿出来翻了下,当初看的时候有些似是而非的东西,这次是基本没有了。这篇也算是前面几篇libevent的blog的补充了。

struct event_base {
 const struct eventop *evsel;
 void *evbase;
 int event_count; /* counts number of total events */
 int event_count_active; /* counts number of active events */

 int event_gotterm; /* Set to terminate loop */
 int event_break; /* Set to terminate loop immediately */

 /* active event management */
 struct event_list **activequeues;
 int nactivequeues;

 /* signal handling info */
 struct evsignal_info sig;

 struct event_list eventqueue;
 struct timeval event_tv;

 struct min_heap timeheap;

 struct timeval tv_cache;
};

我们这里用select来讲,其他的事件驱动器都相似。

我们来看,其中activequeues我们知道是表示激活的事件队列.这里libevent的处理是,select被唤醒后,调用 event_active方法,将此事件插入到activequeues队列中,这里这个队列的实现是用tail queue。然后libevent会执行event_process_active方法,从而从激活队列中,依次执行所激活的事件。这里这个队列之所以是一个指针的指针,是因为,libevent中事件还分为优先级,这样每个优先级都有一个activequeues队列。

记下来我们再来看定时器的实现,libevent会在每次执行循环时,从优先级队列中取出来最小的那个时间,然后将它加入到select中,从而实现定时器。而在每次select超时退出后,libevent会从小到大取出超时时间(直到大于当前时间),每次和当前时间比较,如果已超时,则会从优先级队列中删除此节点,然后将此超时事件加入到激活队列中。

接下来我们来看相关代码。

int
event_base_loop(struct event_base *base, int flags)
{
..................................................

 timeout_correct(base, &tv);

 tv_p = &tv;
///判断是否有激活事件,如果没有的话我们则会从优先级队列中取出最小的那个时间。也就是离现在最近的那个超时时间。
 if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {
///下面会介绍这个函数
  timeout_next(base, &tv_p);
 } else {
  /*
  * if we have active events, we just poll new events
  * without waiting.
  */
  evutil_timerclear(&tv);
 }

.........................................................
 /* clear time cache */
 base->tv_cache.tv_sec = 0;
///调用相关事件驱动引擎的dispatch方法,这个方法中会将已激活的事件加入到激活队列,这里看到tv_p也就是上面取到的超时时间被传入到dispatch。
 res = evsel->dispatch(base, evbase, tv_p);

 if (res == -1)
  return (-1);
 gettime(base, &base->tv_cache);
///处理超时事件,将所有已超时的事件加入到激活队列。下面我们会介绍这个函数
 timeout_process(base);

 if (base->event_count_active) {
 ///执行激活事件队列
  event_process_active(base);
  if (!base->event_count_active && (flags & EVLOOP_ONCE))
///判断是否退出。
  done = 1;
 } else if (flags & EVLOOP_NONBLOCK)
  done = 1;
 }

 /* clear time cache */
 base->tv_cache.tv_sec = 0;
 event_debug(("%s: asked to terminate loop.", __func__));
 return (0);
}

时间: 2024-08-03 01:33:38

libevent源码浅析(四)的相关文章

libevent源码浅析(二):libevent的定时器的实现

在libevent中定时器的实现是通过基于最小堆的优先级队列来实现的. 对于这两个数据结构比较陌生的可以去翻算法导论的6.5节. 主要的源码都在min_heap.c中. 我们先来看主要的数据结构: typedef struct min_heap { struct event** p; unsigned n, a; } min_heap_t; 在这个数据结构中 p也就是整个优先级队列,而这个优先级队列的每个节点都是一个struct *event.n表示这个队列的元素个数.a表示这个队列的大小. 接

libevent源码浅析(三):libevent的信号的处理

在libevent中通过使用socketpair建立一对流管道,也就是全双工管道,来将信号事件与句柄事件统一起来. 先来看数据结构: struct evsignal_info { struct event ev_signal; ///<所属的event int ev_signal_pair[2]; ///<创建的流管道 int ev_signal_added; ///<信号是否已被加入到event中的标记. volatile sig_atomic_t evsignal_caught; /

libevent源码浅析(一)

这里分析的是libevent-1.4.9. PS:前面还看了libev的源代码,妈的,那代码写的太猥亵了,相比较libevent代码写的好多了.. 首先来看一下最主要的几个数据结构: eventop结构体是所有事件驱动模型的基类.所有的io复用类型都会实现此结构体里各种方法. struct eventop { const char *name; ///<事件驱动名称 void *(*init)(struct event_base *); //<初始化 int (*add)(void *, st

Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令

Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Android Debug Bridge,就是起到调试桥的作用.通过adb我们可以在IDE中调试Android程序,说白了就是debug工具.adb的工作方式比较特殊,采用监听Socket TCP 5554等端口的方式让IDE和Qemu通讯,默认情况下adb会daemon相关的网络端口,所以当我们运行And

PgSQL · 最佳实践 · pg_rman源码浅析与使用

背景 对于商业数据库来说,备份的功能一般都非常的全面. 比如Oracle,它的备份工具rman是非常强大的,很多年前就已经支持全量.增量.归档的备份模式,支持压缩等. 还支持元数据存储到数据库中,管理也非常的方便,例如保留多少归档,备份集的管理也很方便,例如要恢复到什么时间点,将此前的备份清除等等. 对于开源数据库来说,支持向商业版本这么丰富功能的比较少,PostgreSQL算是非常完善的一个. PostgreSQL作为最高级的开源数据库,备份方面已经向商业数据库看齐. 目前PostgreSQL

我对java String的理解 及 源码浅析

一.char说起到String 这也是自己第二次回过头来啃java基础书,小生自认为愚昧无知.如果大神有好的教育,可以评论私信.以下都是我的看法: 为什么说char 呢,我这里先卖个关子.在java中,char是用unicode编码的,占16位(2字节).从ansi编码(1字节)到unicode编码(2字 节).Java中使用Unicode的原因是,Java的Applet(网页)运行,Unicode里面包含最多最广比如:中 文,English,Spanish,German, French等.因此

苹果推出最受欢迎的iOS 到 民用与商用数据库备份的差异与源码浅析

背景 苹果推出了有史以来最受欢迎的一版iOS,为什么这么受欢迎? 最主要的还是使用了最新的APFS文件系统,这个文件系统几乎集成了ZFS,Btrfs的所有优良特性,比如最为好用的快照(块级增量).压缩.使得苹果的操作系统一下子瘦了,而且备份占用空间也非常小. 对于数据库来说,备份也不是小事,如何实现高效的备份.节省空间的备份以及具备可以定义SLA的恢复(不会随着数据库的大小.REDO的多少而变化). 对于商业数据库来说,备份的功能一般都非常的全面. 比如Oracle,它的备份工具rman是非常强

Android源码浅析(二)——Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境

Android源码浅析(二)--Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境 接着上篇,上片主要是介绍了一些安装工具的小知识点Android源码浅析(一)--VMware Workstation Pro和Ubuntu Kylin 16.04 LTS安装配置,其实Ubuntu Kylin 16.04 LTS也只是为了体验,我们为了追求稳定,还是使用了Ubuntu14.04 这里提供一个国内镜像的下载链接,可以用迅雷,下载下来之后后缀

Android源码浅析(一)——VMware Workstation Pro和Ubuntu Kylin 16.04 LTS安装配置

Android源码浅析(一)--VMware Workstation Pro和Ubuntu Kylin 16.04 LTS安装配置 最近地方工作,就是接触源码的东西了,所以好东西还是要分享,系列开了这么多,完结 的也没几个,主要还是自己覆盖的太广了,却又不精通,嘿嘿,工作需要,所以写下了本篇博客 一.VMware 12 我选择的虚拟机试VMware,挺好用的感觉,下载VMware就不说了,善用搜索键嘛,这里我提供一个我现在在用的 下载地址:链接:http://pan.baidu.com/s/1k