libevent源码分析
libevent源码深度剖析十三libevent信号处理注意点

libevent源码深度剖析十三libevent信号处理注意点系列目录(1)libevent源码深度剖析一序(2)libevent源码深度剖析二 Reactor模式(3)libevent源码深度剖析三 libevent基本使用场景和事件流程(4)libevent源码深度剖析四 libevent源代码文件组织(5)libevent源码深度剖析五 libevent的核心:事件event(6)libevent源码深度剖析六初见事件处理框架(7)libevent源码深度剖析七事件主循环(8)libevent源码深度剖析八集成信号处理(9)libevent源码深度剖析九集成定时器事件(10)libevent源码深度剖析十支持I/O多路复用技术(11)libevent源码深度剖析十一时间管理(12)libevent源码深度剖析十二让libevent支持多线程(13)libevent源码深度剖析十三 libevent信号处理注意点前面讲到了 libevent 实现多线程的方法,然而在多线程的环境中注册信号事件,还是有一些情况需要小心处理,那就是不能在多个 libevent 实例上注册信号事件。
依然冠名追加到 libevent 系列。
以 2 个线程为例,做简单的场景分析。
1 首先是创建并初始化线程 1 的 libevent 实例 base1 ,线程 1 的 libevent 实例 base2 ;2 在 base1 上注册 SIGALRM 信号;在 base2 上注册 SIGINT 信号;3 假设当前 base1 和 base2 上都没有注册其他的事件;4 线程 1 和 2 都进入 event_base_loop 事件循环:5 假设线程 1 先进入 event_base_loop ,并设置 evsignal_base = base1 ;并等待;6 接着线程 2 也进入 event_base_loop ,并设置 evsignal_base = base2 ;并等待;于是 evsignal_base 就指向了 base2 ;7 信号 ALARM 触发,调用服务例程:1static void evsignal_handler(int sig){2 ...3 evsignal_base->sig.evsigcaught[sig]++;4 evsignal_base->sig.evsignal_caught = 1;5 /* Wake up our notification mechanism */6 send(evsignal_base->sig.ev_signal_pair[0], 'a', 1, 0);7 ...8}于是 base2 得到通知 ALARM 信号发生了,而实际上 ALARM 是注册在 base1 上的, base2 上的 ALARM 注册 event 是空的,于是处理函数将不能得到调用;因此在 libevent 中,如果需要处理信号,只能将信号注册到一个 libevent 实例上。
libevent源码分析

libevent源码分析这两天没事,看了⼀下Memcached和libevent的源码,做个⼩总结。
1、⼊门1.1、概述Libevent是⼀个⽤于开发可扩展性⽹络服务器的基于事件驱动(event-driven)模型的⽹络库。
Libevent有⼏个显著的亮点:(1)事件驱动(event-driven),⾼性能;(2)轻量级,专注于⽹络,不如 ACE 那么臃肿庞⼤;(3)源代码相当精炼、易读;(4)跨平台,⽀持 Windows、Linux、*BSD和 Mac Os;(5)⽀持多种 I/O多路复⽤技术, epoll、poll、dev/poll、select 和kqueue 等;(6)⽀持 I/O,定时器和信号等事件;(7)注册事件优先级;Libevent 已经被⼴泛的应⽤,作为底层的⽹络库;⽐如 memcached、 Vomi t、 Nylon、 Netchat等等。
1.2、⼀个简单⽰例代码1int lasttime;23static void4 timeout_cb(int fd, short event, void *arg)5 {6struct timeval tv;7struct event *timeout = arg;8int newtime = time(NULL);910//printf("%s: called at %d: %d\n", __func__, newtime,11 printf("%s: called at %d: %d\n", "timeout_cb", newtime,12 newtime - lasttime);13 lasttime = newtime;1415 evutil_timerclear(&tv);16 _sec = 2;17//重新注册event18 event_add(timeout, &tv);19 }2021int22 main (int argc, char **argv)23 {24struct event timeout;25struct timeval tv;2627/* Initalize the event library */28//初始化event环境29 event_init();3031/* Initalize one event */32//设置事件33 evtimer_set(&timeout, timeout_cb, &timeout);3435 evutil_timerclear(&tv);36 _sec = 2;37//注册事件38 event_add(&timeout, &tv);3940 lasttime = time(NULL);4143 event_dispatch();4445return (0);46 }这是⼀个简单的基于libevent的定时器程序,运⾏结果:⽤libevent编程⾮常简单,只需要调⽤event_init初始化环境,然后调⽤event_add注册相应的事件,接着调⽤event_dispatch等待并处理相应的事件即可。
LibEvent代码阅读--多缓冲区和零拷贝技术

最近项目赶着发版本,连续好几天通宵赶工,瓶颈出现在了性能问题,各种方案验证和修订。
周末闲下来还是对之前学习的libevent进行总结。
在libevent的报文收发处理过程中采用了一系列提高收发性能的技术,其中多缓冲区的接收和发送以及零拷贝技术等,本篇主要分析这些技术在libevent中的运用。
首先简要的介绍一下两种技术:多缓存的收据发送和接收:点击(此处)折叠或打开1.struct iovec {2. ptr_t iov_base;/* Starting address */3. size_t iov_len;/* Length in bytes */4.};5.6.int readv(int fd,const struct iovec *vector,int count);7.int writev(int fd,const struct iovec *vector,int count);其中的iovec是指一个缓冲区,包含了数据区的地址和对应的长度,在两个函数中的count是指iovec的个数。
这种多缓冲区的发送和接收操作性能相对更好。
而iovec需要在使用前分配好相关的内存空间。
零拷贝技术:零拷贝能够减少数据之间无效的数据拷贝,而直接进行数据的发送,通常在数据发送的过程中使用,特别是在文件发送的过程中被经常使用。
通常情况下要将文件a.txt中的内容发送出去,需要进行如下的操作:读取文件内容: read(),然后发送读取的内容send()。
因此一个完整的过程会出现一个读取再发送的操作,往往文件的IO操作是相对费时的操作,因此零拷贝技术实际上就是较少了read()的处理过程,即在发送数据前不需要进行文件的读取操作,这样相对而言就会提高处理的性能。
关于零拷贝的技术有很多方式,这里主要介绍sendfile和mmap.其中的mmap是采用映射的方式将文件内容映射到内存中,在发送报文时直接读取内存中的内容,这样就能提高发送效率。
libevent 例子

libevent 例子Libevent 是一个用于处理I/O 事件驱动的库,它可以帮助开发人员编写高性能的网络应用程序。
下面是一些使用libevent 的简单示例:1.创建事件循环c复制代码#include<event2/event.h>int main() {struct event_base *base;base = event_base_new();if (!base) {// handle error}// use event_base to add, modify, and delete eventsevent_base_dispatch(base);event_base_free(base);return0;}2.添加超时事件c复制代码#include<event2/event.h>int main() {struct event_base *base;base = event_base_new();struct event *ev;ev = event_new(base, -1, EV_TIMEOUT, timeout_callback, NULL);event_add(ev, NULL);event_base_dispatch(base);event_free(ev);event_base_free(base);return0;}void timeout_callback(evutil_socket_t fd, short events, void *arg) {// handle timeout event}3.添加I/O 事件c复制代码#include<event2/event.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<fcntl.h>#include<errno.h>#include<err.h>#include<sys/types.h>#include<sys/select.h>#include<netdb.h>#include<sys/wait.h>#include<signal.h>#include<time.h>#include<stdlib.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<string.h>#include<unistd.h>#include<fcntl.h>#include<errno.h>#include<err.h>#include<sys/wait.h>#include<sys/timeb.h>#include<time.h>#include<stdlib.h>#include<stdio.h>#include<string.h>#include<unistd.h>#include<fcntl.h>#include<errno.h>#include<err.h>#include<signal.h>。
libevent源码分析event_base_dispatch,event_base_lo。。。

libevent源码分析event_base_dispatch,event_base_lo。
接⼝:event_base_dispatch/**Event dispatching loop 事件分配循环This loop will run the event base until either there are no more pending oractive, or until something calls event_base_loopbreak() orevent_base_loopexit().这个循环将会运⾏event base,知道没有等待的或者活动的事件,或者其它的调⽤了event_base_loopbreak()或event_base_loopexit().@param base the event_base structure returned by event_base_new() orevent_base_new_with_config() event_base_new() 或者 event_base_new_with_config() 返回的event_base对象@return 0 if successful, -1 if an error occurred, or 1 if we exited becauseno events were pending or active. 成功返回0,错误返回-1,或者1(当没有等待的或者活动事件时退出,会返回1)@see event_base_loop()*/EVENT2_EXPORT_SYMBOLint event_base_dispatch(struct event_base *base);intevent_base_dispatch(struct event_base *event_base){return (event_base_loop(event_base, 0));}跟踪event_base_loop接⼝/**Wait for events to become active, and run their callbacks.等待events 变成活动的,并运⾏对应的回调函数。
黑马程序员C语言教程:libevent

标题:深入浅出-服务器高并发库libevent (一)1安装libevent是一个开源的高并发服务器开发包,官方地址/ libevent目前有两个版本一个是1.4系列版本,一个是2.0系列版本。
我们可以在官方网站上看到类似有个stable表示稳定版本。
libevent-1.4.15-stable.tar.gz对于初学者学习,建议从1.4版本学起。
在安装libevent之前先判断本电脑是否已经安装了通过指令ls -al /usr/lib|grep libevent如果没有任何信息则表示没有安装,有的话如果发现libevent是1.3以下版本,则可以同过执行rpm -e libevent —nodeps 进行卸载。
如果是其他操作系统使用其他对应卸载指令即可。
对于下好的tar包,通过tar -zxvf libevent-release-1.4.15-stable.tar.gz指令解压。
然后执行./configure命令,但是有的包可能没有configure文件,却存在一个autogen.sh 脚本,运行这个脚本。
(如果运行不起来请安装autoconf包)然后./configure–prefix=/usrmakesudo make install安装完之后执行ls -al /usr/lib/|grep libevent如果发现有libevent文件库存在就代表安装完毕。
2 简单的libevent服务器我们通过连接libevent库来进行管理libevent库,所以在使用gcc或者g++编译的时候最后需要加上-levent下面是一个简单的libevent服务器。
#include <stdio.h>#include <string.h>#include <iostream>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <unistd.h>#include <event.h>using namespace std;#define SERVER_ADDR "127.0.0.1"#define SERVER_PORT 8888// 事件basestruct event_base* base;// 读事件回调函数void onRead(int iCliFd, short iEvent, void *arg) {int iLen;char buf[1500];iLen = recv(iCliFd, buf, 1500, 0);if (iLen <= 0) {cout << "Client Close" << endl;// 连接结束(=0)或连接错误(<0),将事件删除并释放内存空间 struct event *pEvRead = (struct event*)arg; event_del(pEvRead);delete pEvRead;close(iCliFd);return;}buf[iLen] = 0;cout << "Client Info:" << buf << endl;struct bufferevent* buf_ev;buf_ev = bufferevent_new(iCliFd, NULL, NULL, NULL, NULL);buf_ev->wm_read.high = 4096;char MESSAGE[]="welcome to server..";bufferevent_write(buf_ev, MESSAGE, strlen(MESSAGE));}// 连接请求事件回调函数void onAccept(int iSvrFd, short iEvent, void *arg){int iCliFd;struct sockaddr_in sCliAddr;socklen_t iSinSize = sizeof(sCliAddr);iCliFd = accept(iSvrFd, (struct sockaddr*)&sCliAddr,&iSinSize);// 连接注册为新事件 (EV_PERSIST为事件触发后不默认删除)struct event *pEvRead = new event;event_set(pEvRead, iCliFd, EV_READ|EV_PERSIST, onRead, pEvRead);event_base_set(base, pEvRead);event_add(pEvRead, NULL);struct bufferevent* buf_ev;buf_ev = bufferevent_new(iCliFd, NULL, NULL, NULL, NULL); buf_ev->wm_read.high = 4096;char MESSAGE[]="welcome to server..";bufferevent_write(buf_ev, MESSAGE, strlen(MESSAGE));cout<<"a client connect:"<<iCliFd<<endl;}int main(){int iSvrFd;struct sockaddr_in sSvrAddr;memset(&sSvrAddr, 0, sizeof(sSvrAddr));sSvrAddr.sin_family = AF_INET;sSvrAddr.sin_addr.s_addr = inet_addr(SERVER_ADDR); sSvrAddr.sin_port = htons(SERVER_PORT);// 创建tcpSocket(iSvrFd),监听本机8888端口iSvrFd = socket(AF_INET, SOCK_STREAM, 0);bind(iSvrFd, (struct sockaddr*)&sSvrAddr,sizeof(sSvrAddr));listen(iSvrFd, 10);// 初始化basebase = (struct event_base*)event_init();struct event evListen;// 设置事件event_set(&evListen, iSvrFd, EV_READ|EV_PERSIST, onAccept, NULL);// 设置为base事件event_base_set(base, &evListen);// 添加事件event_add(&evListen, NULL);// 事件循环event_base_dispatch(base);return 0;}通过编译指令g++ server.cpp -o server -Wall -g -I ./ -levent得到可执行程序./server启动。
libev事件库详解(二)

libev事件库详解(⼆)事件库之Libev(⼀)使⽤Libev#include<ev.h>#include <stdio.h>#include <signal.h>#include <sys/unistd.h>ev_io io_w;ev_timer timer_w;ev_signal signal_w;void io_action(struct ev_loop *main_loop,ev_io *io_w,int e){int rst;char buf[1024] = {'\0'};puts("in io cb\n");read(STDIN_FILENO,buf,sizeof(buf));buf[1023] = '\0';printf("Read in a string %s \n",buf);ev_io_stop(main_loop,io_w);}void timer_action(struct ev_loop *main_loop,ev_timer *timer_w,int e){puts("in tiemr cb \n");ev_timer_stop(main_loop,timer_w);}void signal_action(struct ev_loop *main_loop,ev_signal signal_w,int e){puts("in signal cb \n");ev_signal_stop(main_loop,signal_w);ev_break(main_loop,EVBREAK_ALL);}int main(int argc ,char *argv[]){struct ev_loop *main_loop = ev_default_loop(0);ev_init(&io_w,io_action);ev_io_set(&io_w,STDIN_FILENO,EV_READ);ev_init(&timer_w,timer_action);ev_timer_set(&timer_w,2,0);ev_init(&signal_w,signal_action);ev_signal_set(&signal_w,SIGINT);ev_io_start(main_loop,&io_w);ev_timer_start(main_loop,&timer_w);ev_signal_start(main_loop,&signal_w);ev_run(main_loop,0);return0;}下⾯对使⽤到的这些API进⾏说明。
libevent中文参考手册

Libevent参考手册:前言1 从一万英尺外看LibeventLibevent是用于编写高速可移植非阻塞IO应用的库,其设计目标是:❖可移植性:使用libevent编写的程序应该可以在libevent支持的所有平台上工作。
即使没有好的方式进行非阻塞IO,libevent也应该支持一般的方式,让程序可以在受限的环境中运行。
❖速度:libevent尝试使用每个平台上最高速的非阻塞IO实现,并且不引入太多的额外开销。
❖可扩展性:libevent被设计为程序即使需要上万个活动套接字的时候也可以良好工作。
❖方便:无论何时,最自然的使用libevent编写程序的方式应该是稳定的、可移植的。
libevent由下列组件构成:❖evutil:用于抽象不同平台网络实现差异的通用功能。
❖event和event_base:libevent的核心,为各种平台特定的、基于事件的非阻塞IO后端提供抽象API,让程序可以知道套接字何时已经准备好,可以读或者写,并且处理基本的超时功能,检测OS信号。
❖bufferevent:为libevent基于事件的核心提供使用更方便的封装。
除了通知程序套接字已经准备好读写之外,还让程序可以请求缓冲的读写操作,可以知道何时IO已经真正发生。
(bufferevent接口有多个后端,可以采用系统能够提供的更快的非阻塞IO方式,如Windows中的IOCP。
)❖evbuffer:在bufferevent层之下实现了缓冲功能,并且提供了方便有效的访问函数。
❖evhttp:一个简单的HTTP客户端/服务器实现。
❖evdns:一个简单的DNS客户端/服务器实现。
❖evrpc:一个简单的RPC实现。
2 库创建libevent时,默认安装下列库:❖libevent_core:所有核心的事件和缓冲功能,包含了所有的event_base、evbuffer、bufferevent和工具函数。
❖libevent_extra:定义了程序可能需要,也可能不需要的协议特定功能,包括HTTP、DNS和RPC。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
libevent源码深度剖析张亮Email: sparling.liang@回想刚开始写时,就冠以“深度剖析”的名称,也是为了给自己一些压力,以期能写好这一系列文章,对libevent源代码的各方面作详细的分析;现在看来也算是达到了最初的目的。
希望能给学习和使用libevent的朋友们有所帮助。
Email:sparkling.liang@张亮目录libevent源码深度剖析 (1)目录 (3)一序幕 (5)1 前言 (5)2 Libevent简介 (5)3 学习的好处 (5)二Reactor模式 (6)1 Reactor的事件处理机制 (6)2 Reactor模式的优点 (6)3 Reactor模式框架 (6)4 Reactor事件处理流程 (8)5 小结 (9)三基本使用场景和事件流程 (10)1 前言 (10)2 基本应用场景 (10)3 实例代码 (11)4 事件处理流程 (11)5 小结 (12)四 libevent源代码文件组织 (13)1 前言 (13)2 源代码组织结构 (13)3 小结 (14)五 libevent的核心:事件event (15)1 libevent的核心-event (15)2 libevent对event的管理 (16)3 事件设置的接口函数 (17)4 小结 (18)六初见事件处理框架 (19)1 事件处理框架-event_base (19)2 创建和初始化event_base (20)3 接口函数 (20)4 小节 (23)七事件主循环 (24)1 阶段性的胜利 (24)2 事件处理主循环 (24)3 I/O和Timer事件的统一 (27)4 I/O和Signal事件的统一 (27)5 小节 (27)八集成信号处理 (28)1 集成策略——使用socket pair (28)2 集成到事件主循环——通知event_base (29)4 evsignal_info结构体 (30)5 注册、注销signal事件 (30)5 小节 (31)九集成定时器事件 (32)1 集成到事件主循环 (32)2 Timer小根堆 (33)3 小节 (34)十支持I/O多路复用技术 (35)1 统一的关键 (35)2 设置I/O demultiplex机制 (35)3 小节 (37)十一时间管理 (38)1 初始化检测 (38)2 时间缓存 (38)3 时间校正 (40)4 小节 (41)十二让libevent支持多线程 (42)1 错误使用示例 (42)2 支持多线程的几种模式 (42)3 例子——memcached (43)4 小节 (44)一序幕1 前言Libevent是一个轻量级的开源高性能网络库,使用者众多,研究者更甚,相关文章也不少。
写这一系列文章的用意在于,一则分享心得;二则对libevent代码和设计思想做系统的、更深层次的分析,写出来,也可供后来者参考。
附带一句:Libevent是用c语言编写的(MS大牛们都偏爱c语言哪),而且几乎是无处不函数指针,学习其源代码也需要相当的c语言基础。
2 Libevent简介上来当然要先夸奖啦,Libevent 有几个显著的亮点:事件驱动(event-driven),高性能;轻量级,专注于网络,不如ACE那么臃肿庞大;源代码相当精炼、易读;跨平台,支持Windows、Linux、*BSD和Mac Os;支持多种I/O多路复用技术, epoll、poll、dev/poll、select和kqueue等;支持I/O,定时器和信号等事件;注册事件优先级;Libevent已经被广泛的应用,作为底层的网络库;比如memcached、V omit、Nylon、Netchat 等等。
Libevent当前的最新稳定版是1.4.13;这也是本文参照的版本。
3 学习的好处学习libevent有助于提升程序设计功力,除了网络程序设计方面外,Libevent的代码里有很多有用的设计技巧和基础数据结构,比如信息隐藏、函数指针、c语言的多态支持、链表和堆等等,都有助于提升自身的程序功力。
程序设计不止要了解框架,很多细节之处恰恰也是事关整个系统成败的关键。
只对libevent本身的框架大概了解,那或许仅仅是一知半解,不深入代码分析,就难以了解其设计的精巧之处,也就难以为自己所用。
事实上Libevent本身就是一个典型的Reactor模型,理解Reactor模式是理解libevent 的基石;因此下一节将介绍典型的事件驱动设计模式——Reactor模式。
参考资料:Libevent: /~provos/libevent/二Reactor模式前面讲到,整个libevent本身就是一个Reactor,因此本节将专门对Reactor模式进行必要的介绍,并列出libevnet中的几个重要组件和Reactor的对应关系,在后面的章节中可能还会提到本节介绍的基本概念。
1 Reactor的事件处理机制首先来回想一下普通函数调用的机制:程序调用某函数Æ函数执行,程序等待Æ函数将结果和控制权返回给程序Æ程序继续处理。
Reactor释义“反应堆”,是一种事件驱动机制。
和普通函数调用的不同之处在于:应用程序不是主动的调用某个API完成处理,而是恰恰相反,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,如果相应的时间发生,Reactor将主动调用应用程序注册的接口,这些接口又称为“回调函数”。
使用Libevent也是想Libevent框架注册相应的事件和回调函数;当这些时间发声时,Libevent会调用这些回调函数处理相应的事件(I/O读写、定时和信号)。
用“好莱坞原则”来形容Reactor再合适不过了:不要打电话给我们,我们会打电话通知你。
举个例子:你去应聘某xx公司,面试结束后。
“普通函数调用机制”公司HR比较懒,不会记你的联系方式,那怎么办呢,你只能面试完后自己打电话去问结果;有没有被录取啊,还是被据了;“Reactor”公司HR就记下了你的联系方式,结果出来后会主动打电话通知你:有没有被录取啊,还是被据了;你不用自己打电话去问结果,事实上也不能,你没有HR的留联系方式。
2 Reactor模式的优点Reactor模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:1)响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的;2)编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销;3)可扩展性,可以方便的通过增加Reactor实例个数来充分利用CPU资源;4)可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性;3 Reactor模式框架使用Reactor模型,必备的几个组件:事件源、Reactor框架、多路复用机制和事件处理程序,先来看看Reactor模型的整体框架,接下来再对每个组件做逐一说明。
1)事件源Linux上是文件描述符,Windows上就是Socket或者Handle了,这里统一称为“句柄集”;程序在指定的句柄上注册关心的事件,比如I/O事件。
2) event demultiplexer——事件多路分发机制由操作系统提供的I/O多路复用机制,比如select和epoll。
程序首先将其关心的句柄(事件源)及其事件注册到event demultiplexer上;当有事件到达时,event demultiplexer会发出通知“在已经注册的句柄集中,一个或多个句柄的事件已经就绪”;程序收到通知后,就可以在非阻塞的情况下对事件进行处理了。
对应到libevent中,依然是select、poll、epoll等,但是libevent使用结构体eventop进行了封装,以统一的接口来支持这些I/O多路复用机制,达到了对外隐藏底层系统机制的目的。
3) Reactor——反应器Reactor,是事件管理的接口,内部使用event demultiplexer注册、注销事件;并运行事件循环,当有事件进入“就绪”状态时,调用注册事件的回调函数处理事件。
对应到libevent中,就是event_base结构体。
一个典型的Reactor声明方式class Reactor{public:int register_handler(Event_Handler *pHandler, int event);int remove_handler(Event_Handler *pHandler, int event);void handle_events(timeval *ptv);// ...};4) Event Handler——事件处理程序事件处理程序提供了一组接口,每个接口对应了一种类型的事件,供Reactor在相应的事件发生时调用,执行相应的事件处理。
通常它会绑定一个有效的句柄。
对应到libevent中,就是event结构体。
下面是两种典型的Event Handler类声明方式,二者互有优缺点。
class Event_Handler{public:virtual void handle_read() = 0;virtual void handle_write() = 0;virtual void handle_timeout() = 0;virtual void handle_close() = 0;virtual HANDLE get_handle() = 0;// ...};class Event_Handler{public:// events maybe read/write/timeout/close .etcvirtual void handle_events(int events) = 0;virtual HANDLE get_handle() = 0;// ...};4 Reactor事件处理流程前面说过Reactor将事件流“逆置”了,那么使用Reactor模式后,事件控制流是什么样子呢?可以参见下面的序列图。
5 小结上面讲到了Reactor的基本概念、框架和处理流程,对Reactor有个基本清晰的了解后,再来对比看libevent就会更容易理解了,接下来就正式进入到libevent的代码世界了,加油!参考资料:Pattern-Oriented Software Architecture, Patterns for Concurrent and Networked Objects, V olume 2三基本使用场景和事件流程1 前言学习源代码该从哪里入手?我觉得从程序的基本使用场景和代码的整体处理流程入手是个不错的方法,至少从个人的经验上讲,用此方法分析libevent是比较有效的。