事件主循环

news2024/12/22 18:44:18

一、事件主循环

1、事件处理主流程

libevent的事件循环主要是通过event_base_loop函数来完成,其主要的操作如下:

1、根据timer-heap中的事件最小超时时间,计算系统I/O demultiplexer的最大等待时间。例如:当底层使用的是Linux提供的epoll机制时,这个最小超时时间就是传给epoll_wait系统调用的超时时间
2、调用系统I/O demultiplexer等待就绪I/O事件。例如:当底层使用的是Linux提供的epoll机制时,调用的是epoll_wait
3、检查signal的激活标志,如果被设置,则检查激活signal event并把event对应的事件回调插入到激活队列
4、将就绪I/O event对应的事件回调插入到激活队列
5、检查timer-heap中的timer-event,将就绪的timer-event从heap上删除,并把事件对应的回调插入到激活队列
6、根据优先级处理激活队列中的事件回调,执行回调函数处理激活事件
7、如果激活事件是超时事件,重新计算超时时间,并注册超时事件

在这里插入图片描述

2、开启事件循环的接口

下面是开启事件循环的接口,通过event_base_loop函数的第二个参数,可以修改这个函数的行为,如下:

int event_base_dispatch(struct event_base *event_base);
int event_base_loop(struct event_base *base, int flags);
/* 不设置标志就是直接调用event_base_dispatch,会一直运行事件循环,直到调用event_base_loopexit() 或 event_base_loopbreak() 或 没有要监控的事件 退出事件循环  */

/* 阻塞等待,当事件被激活并执行完回调后,退出事件循环(即:等待事件被触发一次后退出) */
#define EVLOOP_ONCE	0x01

/* 不阻塞,直接判断是否有激活事件,有激活事件直接指定对应的回调,执行完退出事件循环 */
#define EVLOOP_NONBLOCK	0x02

/* 一直运行事件循环,直到调用event_base_loopexit() 或 event_base_loopbreak() 退出事件循环*/
#define EVLOOP_NO_EXIT_ON_EMPTY 0x04

3、激活事件插入到激活队列

激活队列是一个优先级队列,当事件被激活时会根据事件的优先级把事件回调插入到激活队列。事件回调对应的类型是event_callback,它有一个evcb_pri成员记录事件回调的优先级,把激活事件回调插入到激活队列会经过下面的步骤:
1)evcallback_list *pList = &base->activequeues[evcb->evcb_pri]; // 根据事件优先级,获取对应的队列
2)事件回调(event_callback数据结构)插入到对应的优先级队列
下面是激活队列(二维列表)对应的数据结构,方框里面的数字代表优先级,如下:

在这里插入图片描述

4、处理激活队列中的事件

处理激活队列中的事件,大致按照下面的流程
1)遍历base->activequeues,依次获取对应的优先级队列(优先级值越小优先级越高,遍历时是从下标为0 的元素开始遍历的)
2)从优先级队列依次取下激活事件回调并执行对应的回调函数

4.1、事件回调对应的数据结构

struct event_callback数据结构记录与事件回调相关的信息,如下:

struct event_callback {
	TAILQ_ENTRY(event_callback) evcb_active_next;
	/* 记录事件的状态,即:激活的事件类型,例如:如果句柄可读导致事件被激活,这个字段的值就是EV_READ */
	short evcb_flags;
	/* 事件优先级 */
	ev_uint8_t evcb_pri;	/* smaller numbers are higher priority */
	/* 记录事件回调类型,这个字段的赋值点是在event_assign函数 */
	ev_uint8_t evcb_closure;
	/* 根据不同类型的事件执行不同的回调函数 */
        union {
		void (*evcb_callback)(evutil_socket_t, short, void *);
		void (*evcb_selfcb)(struct event_callback *, void *);
		void (*evcb_evfinalize)(struct event *, void *);
		void (*evcb_cbfinalize)(struct event_callback *, void *);
	} evcb_cb_union;
	/* 自定义参数 */
	void *evcb_arg;
};

4.2、执行事件回调

调用event_new接口创建对应的事件,传入的回调类型是void (*cb)(evutil_socket_t, short, void *),在执行回调时需要传入这几个参数(句柄、事件触发类型、自定义参数),下面看下这几个参数分别是如何获取到的

1)句柄:event_callback是event的成员,当前可以拿到event_callback对应的地址,通过指针偏移就可以拿到对应的event,通过event就可以获取到对应的句柄
2)事件触发类型:event的ev_res成员记录了事件触发类型
3)自定义参数:event_callback的evcb_arg成员记录了自定义参数地址

5、停止事件循环

libevent内定义了两个函数,可以用于停止事件循环:

int event_base_loopexit(struct event_base *base, const struct timeval *tv);
int event_base_loopbreak(struct event_base *base);
  • event_base_loopexit()函数告诉event_base在指定的时间tv后停止循环。如果tv参数为空的话,event_base立即停止循环,如果event_base当前正在运行active events的回调,则直到运行完之后才会停止。
  • event_base_loopbreak()函数告诉event_base立即退出循环,区别于event_base_loopexit(base, NULL),event_base_loopbreak()会在处理完当前active events之后立马退出。

注意:event_base_loopexit(base,NULL)和event_base_loopbreak(base)在没有事件循环运行时的行为不同:loopexit安排事件循环的下一个实例在下一轮回调运行后立即停止(就像它已经被调用一样与 EVLOOP_ONCE) 而loopbreak只停止当前正在运行的循环,如果事件循环没有运行,则无效。

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

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

相关文章

Android系统启动流程--system_server进程的启动流程

紧接上一篇zygote进程的启动流程,上一篇的结尾提到zygote进程中会fock出一个system_server进程,用于启动和管理Android系统中大部分的系统服务,本篇就来分析system_server进程是如何创建并运行的以及它都做了哪些重要的工作。 //文件路径&am…

Show, Attend, and Tell | a PyTorch Tutorial to Image Captioning代码调试(跑通)

Show, Attend, and Tell | a PyTorch Tutorial to Image Captioning代码调试(跑通) 文章目录 Show, Attend, and Tell | a PyTorch Tutorial to Image Captioning代码调试(跑通)前言1. 创建、安装所用的包1.1 创建环境&#xff0c…

【深度学习】OCR文本识别

OCR文字识别定义 OCR(optical character recognition)文字识别是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,然后用字符识别方法将形状翻译成计算机文字的过程;即,对文本资料进行扫描…

【数据结构】二叉树经典oj题

🚀write in front🚀 📜所属专栏:初阶数据结构 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对…

B. Make Them Equal(Codeforces Round 673 (Div. 1))

传送门 题意: 思路: 首先判断是否能够操作达到目的:即所有的数都相等。 不能达到有两种情况: 1:所有数之和对n取余不等于0 2: 每个ai都是小于i的,例如n5, a[]{0,1,2,3,4}。因为每个数都是小于 i 的&am…

idea中的 debug 中小功能按钮都代表的意思

1.step over 步过----->一行一行的往下走,如果这一行中有方法那么不会进入该方法,直接一行一行往下走,除非你在该方法中打入断点 2.step into 步入—>可以进入方法内部,但是只能进入自己写的方法内部,而不会进入方法的类库中 3.Force step into 强制步入---->可以步…

编译livox ros driver2(ROS2、livox、rviz、ubuntu22.04)

1. 编译Livox-SDK2 官方地址:https://github.com/Livox-SDK/Livox-SDK2 执行一下命令: git clone https://github.com/Livox-SDK/Livox-SDK2.git cd ./Livox-SDK2/ mkdir build cd build cmake .. && make sudo make install 如上就安装完成了…

嵌入式【CPLD】5M570ZT100C5N、5M1270ZF256C5N、5M2210ZF256C5N采用独特的非易失性架构,低成本应用设计。

英特尔MAX V CPLD 采用独特的非易失性架构,提供低功耗片上功能,适用于以边缘为中心的应用。MAX V CPLD系列能够在单位空间中提供大量 I/O 和逻辑。这些设备还使用了低成本绿色封装技术,封装大小只有 20 毫米。 MAX V系列的关键应用包括&…

PCL点云库(1) - 简介与数据类型

目录 1.1 简介 1.2 PCL安装 1.2.1 安装方法 1.2.2 测试程序 1.3 PCL数据类型 1.4 PCL中自定义point类型 1.4.1 增加自定义point的步骤 1.4.2 完整代码 1.1 简介 来源:PCL(点云库)_百度百科 PCL(Point Cloud Library&…

个推打造消息推送专项运营提升方案,数据驱动APP触达效果升级

“数智化运营”能力已成为企业的核心竞争力之一。借助数据和算法,构建完善的数智化运营体系,企业可增强用户洞察和科学决策能力,提高日常运营效率和投入产出比。近半年,个推精准把握行业客户的切实需求,将“数智化运营…

分析型数据库:MPP 数据库的概念、技术架构与未来发展方向

随着企业数据量的增多,为了配合企业的业务分析、商业智能等应用场景,从而驱动数据化的商业决策,分析型数据库诞生了。由于数据分析一般涉及的数据量大,计算复杂,分析型数据库一般都是采用大规模并行计算或者分布式计算…

css的属性选择器

文章目录 属性选择器的原理简单的语法介绍子串值(Substring value)属性选择器 CSS 属性选择器的最基本用法复杂一点的用法层叠选择多条件复合选择伪正则写法配合 **:not()** 伪类重写行内样式 组合用法:搭配伪元素提升用户体验角标功能属性选…

基于51单片机的智能晾衣架的设计与实现(源码+论文)_kaic

【摘要】随着社会和市场的变化,我国经济的快速发展和房地产行业的快速扩张,使得装修家居行业飞速发展,在行业高速发展的同时,消费者家居智能化要求也在日益发展。随着科学技术的进步和电子技术的发展,单片机作为智能控…

Stable Diffusion一键安装器,只有2.3M

最近AI画图真的是太火了,但是Midjourney收费之后大家就不知道去哪里能用AI画图了, Stable Diffusion很多人听过,但是安装特别麻烦。所以为大家介绍一款软件,一键安装SD。 Stable Diffusion一键安装器_SD一键启动器-Stable Diffus…

LeetCode:459. 重复的子字符串 —【2、KMP算法】

🍎道阻且长,行则将至。🍓 🌻算法,不如说它是一种思考方式🍀 算法专栏: 👉🏻123 一、🌱459. 重复的子字符串 题目描述:给定一个非空的字符串 s &…

Docker数据管理与Docker镜像的创建

目录 1.管理数据的方式 1.数据卷 2.数据卷容器 3.容器互联(使用centos镜像) 2.Docker镜像的创建 1.基于现有镜像创建 2.基于本地模板创建 3.基于Dockerfile创建 4.Dockerfile案例 总结 1.管理数据的方式 容器中管理数据主要有两种方式&#xff1…

c++作业

自己定义mystring类实现string功能 #include <iostream> #include<cstring> using namespace std;class myString {private:char *str; //记录c风格的字符串int size; //记录字符串的实际长度public://无参构造myString():size(10){str new …

tomcat服务搭建

系列文章目录 文章目录 系列文章目录一、Tomcat1.核心功能 二、Tomcat服务搭建1.Tomcat服务2.Tomcat 虚拟主机配置1.创建 kgc 和 benet 项目目录和文件2.修改 Tomcat 主配置文件 server.xml3.客户端浏览器访问验证 三、Tomcat多实例部署 一、Tomcat 1.核心功能 1.connector&a…

Spring Bean生命周期源码之包扫描、创建BeanDefinition、合并BeanDefinition源码

文章目录 Bean生命周期源码生成BeanDefinitionSpring容器启动时创建单例Bean合并BeanDefinition Bean生命周期源码 我们创建一个ApplicationContext对象时&#xff0c;这其中主要会做两件时间&#xff1a;包扫描得到BeanDefinition的set集合&#xff0c;创建非懒加载的单例Bea…

体验ChatGPT在具体应用场景下的能力与表现——vuedraggable的move多次触发问题

当下人工智能模型在满天飞&#xff0c;今天拿一个具体的应用场景&#xff0c;来体验下ChatGPT的能力与表现&#xff0c;看看是否能解决实际问题。 顺便填一下之前遇到的一个具体的坑&#xff1a;vuedraggable的move多次触发问题。 背景 背景是这样的&#xff0c;实现低代码开…