【传智播客】Libevent学习笔记(三):事件循环

目录

  • 00. 目录
  • 01. event_base_loop函数
  • 02. event_base_dispatch函数
  • 03. event_base_loopexit函数
  • 04. event_base_loopbreak函数
  • 05. event_base_got_exit函数
  • 06. event_base_got_break函数
  • 07. event_base_dump_events函数
  • 08. event_base_dump_events函数
  • 09. 废弃的事件循环函数
  • 10.参考

00. 目录

声明: 该博客来源于传智播客C++学院相关培训参考手册

01. event_base_loop函数

一旦有了一个已经注册了某些事件的event_base(关于如何创建和注册事件请看笔记四),就需要让libevent等待事件并且通知事件的发生。

event_base_loop函数

/**Wait for events to become active, and run their callbacks.This is a more flexible version of event_base_dispatch().By default, this loop will run the event base until either there are no morepending or active events, or until something calls event_base_loopbreak() orevent_base_loopexit().  You can override this behavior with the 'flags'argument.@param eb the event_base structure returned by event_base_new() orevent_base_new_with_config()@param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK@return 0 if successful, -1 if an error occurred, or 1 if we exited becauseno events were pending or active.@see event_base_loopexit(), event_base_dispatch(), EVLOOP_ONCE,EVLOOP_NONBLOCK*/
int event_base_loop(struct event_base *base, int flag);  //while(1) { .... }
功能:等待事件被触发, 然后执行对应的回调函数
参数:base: event_base_new的返回值flag: 标志
返回值:成功: 0成功  1表示没有事件触发失败: -1

循环相关标志:

/** @name Loop flagsThese flags control the behavior of event_base_loop().*/
/**@{*/
/** Block until we have an active event, then exit once all active events* have had their callbacks run. */
#define EVLOOP_ONCE 0x01
/** Do not block: see which events are ready now, run the callbacks* of the highest-priority ones, then exit. */
#define EVLOOP_NONBLOCK 0x02
/**@}*/

默认情况下,event_base_loop()函数运行event_base直到其中没有已经注册的事件为止。执行循环的时候,函数重复地检查是否有任何已经注册的事件被触发(比如说,读事件的文件描述符已经就绪,可以读取了;或者超时事件的超时时间即将到达)。如果有事件被触发,函数标记被触发的事件为“激活的”,并且执行这些事件。

在flags参数中设置一个或者多个标志就可以改变event_base_loop()的行为。如果设置了EVLOOP_ONCE,循环将等待某些事件成为激活的,执行激活的事件直到没有更多的事件可以执行,然会返回。如果设置了EVLOOP_NONBLOCK,循环不会等待事件被触发:循环将仅仅检测是否有事件已经就绪,可以立即触发,如果有,则执行事件的回调。

完成工作后,如果正常退出,event_base_loop()返回0;如果因为后端中的某些未处理错误而退出,则返回-1。

为帮助大家理解,这里给出event_base_loop()的算法概要:

while (any events are registered with the loop) {if (EVLOOP_NONBLOCK was set, or any events are already active)If any registered events have triggered, mark them active.elseWait until at least one event has triggered, and mark it active.for (p = 0; p < n_priorities; ++p {if (any event with priority of p is active) {Run all active events with priority of p.break; /* Do not run any events of a less important priority */}}if (EVLOOP_ONCE was set or EVLOOP_NONBLOCK was set)break;
}

02. event_base_dispatch函数

event_base_dispatch()等同于没有设置标志的event_base_loop()。所以,event_base_dispatch()将一直运行,直到没有已经注册的事件了,或者调用了event_base_loopbreak()或者event_base_loopexit()为止。

/**Event dispatching loopThis loop will run the event base until either there are no more pending oractive, or until something calls event_base_loopbreak() orevent_base_loopexit().@param base the event_base structure returned by event_base_new() orevent_base_new_with_config()@return 0 if successful, -1 if an error occurred, or 1 if we exited becauseno events were pending or active.@see event_base_loop()*/
int event_base_dispatch(struct event_base *base);
等价于没有设置标志的 event_base_loop函数

event_base_dispatch()将一直运行,直到没有已经注册的事件了,或者调用了event_base_loopbreak()或者event_base_loopexit()为止。

这些函数定义在<event2/event.h>中,从libevent 1.0版就存在了。

03. event_base_loopexit函数

/**Exit the event loop after the specified timeThe next event_base_loop() iteration after the given timer expires willcomplete normally (handling all queued events) then exit withoutblocking for events again.Subsequent invocations of event_base_loop() will proceed normally.@param eb the event_base structure returned by event_init()@param tv the amount of time after which the loop should terminate,or NULL to exit after running all currently active events.@return 0 if successful, or -1 if an error occurred@see event_base_loopbreak()*/
int event_base_loopexit(struct event_base *base, const struct timeval *tv);
功能:让event_base在给定时间之后停止循环。
参数:base event_base_new的返回值tv 表示延时的时间,如果为NULL 立即停止循环,没有延时返回值:成功: 0成功  失败: -1

注意:

如果event_base当前正在执行任何激活事件的回调,则回调会继续运行,直到运行完所有激活事件的回调之才退出。

04. event_base_loopbreak函数

/**Abort the active event_base_loop() immediately.event_base_loop() will abort the loop after the next event is completed;event_base_loopbreak() is typically invoked from this event's callback.This behavior is analogous to the "break;" statement.Subsequent invocations of event_loop() will proceed normally.@param eb the event_base structure returned by event_init()@return 0 if successful, or -1 if an error occurred@see event_base_loopexit()*/
int event_base_loopbreak(struct event_base *base);
功能:让event_base立即停止循环。
参数:base event_base_new的返回值     
返回值:成功: 0成功  失败: -1

这些函数声明在<event2/event.h>中。event_break_loopexit()函数首次在libevent 1.0c版本中实现;event_break_loopbreak()首次在libevent 1.4.3版本中实现。

注意:

event_base_loopbreak()让event_base立即退出循环。它与event_base_loopexitbase,NULL)的不同在于,如果event_base当前正在执行激活事件的回调,它将在执行完当前正在处理的事件后立即退出。

event_base_loopexit(base,NULL)和event_base_loopbreak(base)在事件循环没有运行时的行为不同:前者安排下一次事件循环在下一轮回调完成后立即停止(就好像带EVLOOP_ONCE标志调用一样);后者却仅仅停止当前正在运行的循环,如果事件循环没有运行,则没有任何效果。

官方参考示例一: 立即退出循环

#include <event2/event.h>/* Here's a callback function that calls loopbreak */
void cb(int sock, short what, void *arg)
{struct event_base *base = arg;event_base_loopbreak(base);
}void main_loop(struct event_base *base, evutil_socket_t watchdog_fd)
{struct event *watchdog_event;/* Construct a new event to trigger whenever there are any bytes toread from a watchdog socket.  When that happens, we'll call thecb function, which will make the loop exit immediately withoutrunning any other active events at all.*/watchdog_event = event_new(base, watchdog_fd, EV_READ, cb, base);event_add(watchdog_event, NULL);event_base_dispatch(base);
}

官方参考示例二: 执行事件循环10秒,然后退出

#include <event2/event.h>void run_base_with_ticks(struct event_base *base)
{struct timeval ten_sec;ten_sec.tv_sec = 10;ten_sec.tv_usec = 0;/* Now we run the event_base for a series of 10-second intervals, printing"Tick" after each.  For a much better way to implement a 10-secondtimer, see the section below about persistent timer events. */while (1) {/* This schedules an exit ten seconds from now. */event_base_loopexit(base, &ten_sec);event_base_dispatch(base);puts("Tick");}
}

测试代码: 每隔3秒钟输出一个字符串

#include <stdio.h>
#include <event.h>int main(void)
{struct event_base *base = NULL;struct timeval tmo = {3, 0}; base = event_base_new();if (NULL == base){   printf("event_base_new failded...\n");return 1;}while(1){   //设置三秒钟退出事件循环event_base_loopexit(base, &tmo); //进入事件循环event_base_dispatch(base);printf("hello itcast\n");}event_base_free(base);return 0;
}

05. event_base_got_exit函数

有时候需要知道对event_base_dispatch()或者event_base_loop()的调用是正常退出的,还是因为调用event_base_loopexit()或者event_base_break()而退出的。可以调用下述函数来确定是否调用了loopexit或者break函数。

/**Checks if the event loop was told to exit by event_loopexit().This function will return true for an event_base at every point afterevent_loopexit() is called, until the event loop is next entered.@param eb the event_base structure returned by event_init()@return true if event_base_loopexit() was called on this event base,or 0 otherwise@see event_base_loopexit()@see event_base_got_break()*/
int event_base_got_exit(struct event_base *base);
功能:判断循环是否因为调用event_base_loopexit()或者event_base_break()而退出的时候返回true,否则返回false。下次启动事件循环的时候,这些值会被重设。
参数:base event_base_new的返回值     
返回值:true 循环是因为调用对应的函数而退出0 其它情况

参考示例:

#include <stdio.h>
#include <event.h>int main(void)
{struct event_base *base = NULL;struct timeval tmo = {3, 0}; base = event_base_new();if (NULL == base){   printf("event_base_new failded...\n");return 1;}   while(1){   event_base_loopexit(base, &tmo);event_base_dispatch(base);printf("hello itcast\n");//如果事件循环因为event_base_loopexit而退出 返回trueif (event_base_got_exit(base)){printf("event_base_got_exit return true\n");}}   event_base_free(base);return 0;
}

06. event_base_got_break函数

有时候需要知道对event_base_dispatch()或者event_base_loop()的调用是正常退出的,还是因为调用event_base_loopexit()或者event_base_break()而退出的。可以调用下述函数来确定是否调用了loopexit或者break函数。

/**Checks if the event loop was told to abort immediately by event_loopbreak().This function will return true for an event_base at every point afterevent_loopbreak() is called, until the event loop is next entered.@param eb the event_base structure returned by event_init()@return true if event_base_loopbreak() was called on this event base,or 0 otherwise@see event_base_loopbreak()@see event_base_got_exit()*/
int event_base_got_break(struct event_base *base);
功能:判断循环是否因为调用event_base_loopexit()或者event_base_break()而退出的时候返回true,否则返回false。下次启动事件循环的时候,这些值会被重设。
参数:base event_base_new的返回值     
返回值:true 循环是因为调用对应的函数而退出0 其它情况

07. event_base_dump_events函数

有时候需要在事件回调中获取当前时间的近似视图,但不想调用gettimeofday()(可能是因为OSgettimeofday()作为系统调用实现,而你试图避免系统调用的开销)。

在回调中,可以请求libevent开始本轮回调时的当前时间视图。

void event_base_dump_events(struct event_base *, FILE *);/** Sets 'tv' to the current time (as returned by gettimeofday()),looking at the cached value in 'base' if possible, and callinggettimeofday() or clock_gettime() as appropriate if there is nocached time.Generally, this value will only be cached while actuallyprocessing event callbacks, and may be very inaccuate if yourcallbacks take a long time to execute.Returns 0 on success, negative on failure.*/
int event_base_gettimeofday_cached(struct event_base *base,struct timeval *tv);
如果event_base当前正在执行回调,event_base_gettimeofday_cached()函数设置tv_out参数的值为缓存的时间。否则,函数调用evutil_gettimeofday()获取真正的当前时间。成功时函数返回0,失败时返回负数。返回值:成功 0失败 负数

注意:

注意,因为libevent在开始执行回调的时候时间值会被缓存,所以这个值至少是有一点不精确。如果回调执行很长时间,这个值将非常不精确。

这个函数是libevent 2.0.4-alpha新引入的。

08. event_base_dump_events函数

为帮助调试程序(或者调试libevent),有时候可能需要已经加入到event_base的所有事件及其状态的完整列表。调用event_base_dump_events()可以将这个列表输出到指定的文件中。

这个列表是人可读的,未来版本的libevent将会改变其格式。

void event_base_dump_events(struct event_base *base, FILE *file);
功能:转储event_base的状态到文件中。
参数:base event_base_new的返回值file FILE类型指针返回值:无

这个函数在libevent 2.0.1-alpha版本中引入。

09. 废弃的事件循环函数

前面已经讨论过,老版本的libevent 具有“当前”event_base的概念。

本文讨论的某些事件循环函数具有操作当前event_base的变体。除了没有base参数外,这些函数跟当前新版本函数的行为相同。

1697806-20190604193652953-246076132.png

2.0版本之前的event_base是不支持锁的,所以这些函数并不是完全线程安全的:不允许在执行事件循环的线程之外的其他线程中调用*_loopbreak()或者_loopexit()*函数。

10.参考

相关书籍: http://www.wangafu.net/~nickm/libevent-book/Ref2_eventbase.html

官方参考网站: https://www.monkey.org/~provos/libevent/doxygen-2.0.1/index.html

转载于:https://www.cnblogs.com/szitcast/p/10975682.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/462417.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android的MVC框架

http://www.cnblogs.com/wanghafan/archive/2012/07/20/2600786.html MVC是当前比较流行的框架&#xff0c;随便Google下&#xff0c;就可以发现几乎所有的应用程序开发中都采用了MVC框架&#xff0c;例如&#xff1a;.NET&#xff0c;Java Spring&#xff0c;Java Struts&…

DVWA-SQL注入

SQL注入解题思路 寻找注入点&#xff0c;可以通过web扫描工具实现通过注入点&#xff0c;尝试得到连接数据库的用户名&#xff0c;数据库名称&#xff0c;权限等信息。猜解关键数据库表极其重要字段与内容。通过获得的用户信息寻找后台进行登录。利用后台上传webshell或一句话木…

easyui验证:validatebox

2019独角兽企业重金招聘Python工程师标准>>> $.extend($.fn.validatebox.defaults.rules, { eqTrim : {/* 填写名字前面不能有空格&#xff01; */ validator : function(value,param) { var reg new RegExp(param); var falg!reg.test(value); return falg; }, me…

秒懂机器学习---当机器学习遇上决策树....

秒懂机器学习---当机器学习遇上决策树.... 一、总结 一句话总结&#xff1a; 多多看图&#xff0c;图的直观效果很好&#xff0c;很多时候文字实在表达不清 1、决策树&#xff08;Decision Tree&#xff09;中的各个节点表示什么意思&#xff1f; 每一个树节点表示一个属性上的…

Linux系统目录结构及主要内容

为什么80%的码农都做不了架构师&#xff1f;>>> 文件结构 &#xff1a; /&#xff1a;根目录&#xff0c;所有的目录、文件、设备都在/之下&#xff0c;/就是Linux文件系统的组织者&#xff0c;也是最上级的领导者。 /bin&#xff1a; bin 就是二进制&#xff08;b…

学习《深度学习入门:基于Python的理论与实现》高清中文版PDF+源代码

入门神经网络深度学习&#xff0c;推荐学习《深度学习入门&#xff1a;基于Python的理论与实现》&#xff0c;这本书不来虚的&#xff0c;一上来就是手把手教你一步步搭建出一个神经网络&#xff0c;还能把每一步的出处讲明白。理解神经网络&#xff0c;很容易就能入门。 深度学…

学习《PythonWeb开发实战(董伟明)》中文PDF+源代码

python可以用了进行数据分析&#xff0c;也可以进行Web开发&#xff0c;一般会使用django或者flask等进行开发。 国内介绍python web的书有写的不错的&#xff0c;推荐看看《PythonWeb开发实战》 他的定位是进阶读者&#xff0c;介绍了Python web的生态&#xff0c;有些包介绍得…

周鸿祎:在360新员工入职培训上的讲话

这个是周鸿祎给入司360新员工的一段话&#xff0c;不但适合360&#xff0c;也适合所有的公司员工。特此分享。我想给新入职的同事讲一讲我的期望&#xff0c;再提几个建议。我这个人喜欢说真话&#xff0c;不喜欢说漂亮话&#xff0c;因为漂亮话没用。但说真话&#xff0c;大家…

使用面向对象技术创建高级 Web 应用程序

作者&#xff1a; 出处&#xff1a; 使用面向对象技术创建高级 Web 应用程序 来源:开源中国社区 作者:oschina最近&#xff0c;我面试了一位具有5年Web应用开发经验的软件开发人员。她有4年半的JavaScript编程经验&#xff0c;自认为自己具有非常优秀的JavaScript技能&#xff…

DevExpress控件使用经验总结

DevExpress控件使用经验总结 DevExpress是一个比较有名的界面控件套件&#xff0c;提供了一系列的界面控件套件的DotNet界面控件。本文主要介绍我在使用DevExpress控件过程中&#xff0c;遇到或者发现的一些问题解决方案&#xff0c;或者也可以所示一些小的经验总结。总体来讲&…

第二阶段团队绩效评分

第二阶段评分结果&#xff1a; 转载于:https://www.cnblogs.com/xczd/p/11068692.html

随堂小测冲刺.第19天

我们小组的logo出来的&#xff0c;太酷了&#xff0c;不符合我的审美&#xff0c;本人表示无法接受。。。 还要谢谢李泽宇的女盆友&#xff0c;O(∩_∩)O哈哈~ 转载于:https://www.cnblogs.com/daisy99lijing/p/11024465.html

MSBuild编译扩展

新增一个C#工程&#xff0c;用记事本打开工程文件&#xff08;.csproj结尾&#xff09;&#xff0c;滚动条拉到最后&#xff0c;大家可以看到一段如下的代码&#xff0c;其中<Target Name"BeforeBuild">和<Target Name"AfterBuild">大家根据名…

修改2440里面的FriendlyARM

修改2440里面的FriendlyARM 在/etc/init.d文件夹里面有一个rcS文件&#xff0c;修改/bin/hostname FriendlyARM中的FriendlyARM即可 比如修改为/bin/hostname Solar posted on 2011-12-07 17:22 Neddy11 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/Neddy…

vs2008 下编译jrtplib-3.9.0成功

网址:http://blog.csdn.net/jid_223/article/details/6858663 jrtplib-3.9.0的编译&#xff0c;终于搞通了。网上搜集了很多资料&#xff0c;自己也调试了很久。 首先&#xff0c;jrtplib-3.9.0是什么不用多说吧&#xff0c;它是一个很牛的老外用C写的一个开源的RTP协议库&…

Eclipse安装VJET报错解决办法

2019独角兽企业重金招聘Python工程师标准>>> Eclipse在安装JS编辑器插件VJET时可能会出现以下错误 Cannot complete the install because one or more required items could not be found. Software being installed: VJET Java Based Dom Kit (Incubation) 0.10.0…

罐头瓶里面的电能表

生活中我们经常见到数字电能表&#xff0c;只不过下面这个是装在罐头里面的电能表&#xff0c; 此想法来自EnterJar&#xff0c;&#xff0c; 怎么样&#xff1f;直接把用电器接上就可以测出电子产品的电能状况&#xff0c;很方便把&#xff01; &#xff0c;原理很简单&#x…

面向对象编程从骨子里就有问题——看看名人大家是如何吐槽面向对象的

2019独角兽企业重金招聘Python工程师标准>>> 本文由“外刊IT评论”网(www.aqee.net)荣誉出品 “面向对象编程是一个极其糟糕的主意&#xff0c;只有硅谷里的人能干出这种事情。” — Edsger Dijkstra(图灵奖获得者) “面向对象设计是用罗马数字做计算。” — Ro…

花了两个星期,我终于把 WSGI 整明白了

在 三百六十行&#xff0c;行行转 IT 的现状下&#xff0c;很多来自各行各业的同学&#xff0c;都选择 Python 这门胶水语言做为踏入互联网大门的第一块敲门砖&#xff0c;在这些人里&#xff0c;又有相当大比例的同学选择了 Web 开发这个方向&#xff08;包括我&#xff09;。…

如何:通过现有代码创建 C++ 项目

http://msdn.microsoft.com/zh-cn/library/b9cy3d6x(vvs.90).aspx 如何&#xff1a;通过现有代码创建 C 项目 Visual Studio 2008其他版本2&#xff08;共 2&#xff09;对本文的评价是有帮助 - 评价此主题更新&#xff1a;2007 年 11 月 可以使用 “从现有代码文件创建新项目”…