| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> 《ZLToolKit源码学习笔记》(15)事件轮询模块之事件轮询器EventPoller -> 正文阅读 |
|
[Java知识库]《ZLToolKit源码学习笔记》(15)事件轮询模块之事件轮询器EventPoller |
??系列文章目录《ZLToolKit源码学习笔记》(1)VS2019源码编译 《ZLToolKit源码学习笔记》(2)工具模块之日志功能分析 《ZLToolKit源码学习笔记》(3)工具模块之终端命令解析 《ZLToolKit源码学习笔记》(4)工具模块之消息广播器 《ZLToolKit源码学习笔记》(6)线程模块之整体框架概述 《ZLToolKit源码学习笔记》(7)线程模块之线程池组件:任务队列与线程组 《ZLToolKit源码学习笔记》(8)线程模块之线程负载计算器 《ZLToolKit源码学习笔记》(9)线程模块之任务执行器 《ZLToolKit源码学习笔记》(11)线程模块之工作线程池WorkThreadPool 《ZLToolKit源码学习笔记》(12)事件轮询模块之整体框架概述 《ZLToolKit源码学习笔记》(13)事件轮询模块之管道的简单封装 《ZLToolKit源码学习笔记》(14)事件轮询模块之定时器 《ZLToolKit源码学习笔记》(15)事件轮询模块之事件轮询器EventPoller(本文) 前言一个服务器程序,一般都需要处理三类事件:IO事件、定时事件、信号。而为了方便处理,我们需要统一事件源,比如使用IO复用来管理所有事件。其次,为了实现跨平台,我们需要提供一个平台无关的统一接口,与平台相关的实现在内部完成。比如对于IO复用,linux下有epoll,windows等其它平台有select,这里我们就可以统一封装,对外提供一致的接口。一个事件管理接口,还应该是支持多线程的,本节学习下ZLToolKit中的事件管理工具:EventPoller。支持定时事件、IO事件处理,通过内置的管道事件,也可以实现多线程执行任务的负载均衡。 目录2.1.3、async_l-添加需要在事件监听线程中执行的任务 一、概述?EventPoller类按照本人的理解,接口大致分为4类:内部管道事件、定时器事件、用户事件(用户可以自己管理的事件,可以是管道、网络socket等)以及线程相关的接口。 EventPoller的事件处理模式为Reactor模式,每一个事件都有其对应的回调,在事件触发后,该回调被调用。 EventPoller的事件管理一般在单独的线程中进行,这可以通过runLoop函数确定。该接口的第一个参数可以设置是否为阻塞的,非阻塞状态下,会创建一个线程,后续的事件监听在线程中进行。linux系统下,事件监听通过epoll管理,非linux平台,通过select管理。 该类虽然是一个单例类(构造函数私有),但是由于其将EventPollerPool作为友元类,所以,使用时,我们一般不直接实例化该类对象,而是通过其友元类EventPollerPool来间接使用。在EventPollerPool中,会根据用户指定的size或者CPU核心数创建多个EventPoller的实例,后续使用时,根据特定条件选择其中一个来调用(比如选择负载最轻的)。 对于EventPollerPool的学习,可以参见《ZLToolKit源码学习笔记》(11)线程模块之工作线程池WorkThreadPool,两者类似。 二、功能分析2.1、内部管道事件?内部管道事件用于用户工作线程和事件监听线程之间的通信。事件监听线程中,监听了管道的读端,用户工作线程中,使用管道的写端。 基于该管道事件,实现了一个任务队列,可以在该线程中异步的执行任务。_list_task用于存储和管道关联的任务,async_l负责将任务加入到_list_task中,然后向管道中写入数据,触发其读事件,runLoop中监听到该事件后,调用onPipeEvent来执行并清除_list_task中的任务。 2.1.1、构造函数
可以看到,管道的读端fd被添加到事件列表中,当管道读事件被触发时,会执行onPipeEvent函数。 2.1.2、onPipeEvent-管道读事件回调
该接口在管道的读事件发生后被调用,执行_list_task中的任务。首先读取管道中的数据,然后交换_list_task,即清空其中任务。最后以此执行所有任务。 2.1.3、async_l-添加需要在事件监听线程中执行的任务
?异步执行的情况下,将任务添加到_list_task中,然后通过向管道中写数据来触发读事件,runLoop事件监听线程中调用onPipeEvent来执行任务。 2.2、定时事件该部分已经在定时器一节中学习过,可参见《ZLToolKit源码学习笔记》(14)事件轮询模块之定时器。 2.3、用户事件?用户可以通过addEvent、delEvent、modifyEvent三个接口,将自己关心的事件让EventPoller来管理。所有被管理的事件都存放在_event_map中。
2.3.1、addEvent-添加事件监听
将事件注册到epoll或者select中管理。注意看函数最后的async调用(前边的if (isCurrentThread())判断了是否是事件监听线程),说明该接口实际的操作不是在用户工作线程中执行的,而是转移到了事件监听线程中执行,避免了多线程操作epoll或者select。 每一个事件都有其对应的回调,在事件触发后,该回调被调用。 对于epoll,直接调用epoll系列api进行操作,对于select,由于每次都需要重新添加要监听的事件,所以这里仅将事件放入_event_map中,添加到select的操作在runLoop中执行。节选runLoop中相关代码如下:
?delEvent、modifyEvent和addEvent接口类似,不再赘述。 三、runLoop?内部管道事件、定时器事件 、以及用户添加的事件都在该接口中管理,当事件触发时,调用各自对应的回调函数,将事件通知上去。在回调中同步的进行IO操作等耗时较大的工作时,会导致事件不能被及时处理,应尽量避免此种操作,可以使用任务队列的方式,将就绪事件放在任务队列中,然后另外的工作线程从队列中获取任务执行。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 8:27:42- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |