3 事件机制
1、什么是事件
首先,需要明确下什么叫事件。
事件,对应的英文是Event,表示有一件事情发生了。
如果一件事情,不与其他的对象相关联,发生时我们只要直接调用函数就可以了。就像上一节定时器实现一样,我们检测到定时器到期了,直接执行定时器的回调函数。
但如果涉及到两个对象,触发事件的一方,就需要一定的手段通知对方。
比如,你去朋友公司拜访他,朋友告诉你,你到公司门口,给我打电话,我下去接你。
这就是一个典型的事件场景:你到朋友公司门口,触发事件,打电话通知朋友,朋友得知你到公司门口,下楼来接你。

这个事件的通知机制,是你有朋友的电话号码,可以通过电话直接通知朋友。
那如果老板通知各部门经理,下午三点开会呢?
你应该已经想到了,直接在群里发个消息就行了,不用每个人打一个电话。
2、事件机制有什么用
上述的事件,虽然能够通知到相关角色,但通知发布的人,需要知道被通知人的联系方式,这样在程序开发中耦合太紧密了。
有时候,事件触发的对象,并不知道谁需要对事件做出响应,比如公司发出公告:下午2:00公司做核酸检测,今天没有做过核酸的同学到一楼大厅做核酸。
这个事件中,哪些人需要响应事件是需要结合自身情况处理的。而发布者是不关心具体谁要去执行,只需要将事件通知出去。
我们要实现的事件机制,就是用来解耦的。
我们可以通过一个发布订阅机制来实现事件通知。
首先有一个事件中心,各个对象实例可以到事件中心,注册自己关心的事件ID。
事件触发的模块,可以到事件中心发布事件,通知事件已经触发。
事件中心检索,是否有实例关心这个事件,如果有则通知相关实例。
这样,发布者就不需要了解谁关心这个事件,只需要将事件发布出去即可,由事件中心负责通知关心的实例。这样就将事件发布者和事件响应者解耦了。

3、事件机制实现
事件机制实现与上一节的定时器实现很相似,这里直接贴上代码分析
Event只需定义两个变量,一个是Type表示事件类型,一个是DataLen记录后缀数据长度,用于Event类型扩展。
EventMgr有两个重要变量,m_mapEvent用来记录事件注册信息,收到事件后会在这个map中查询需要调用哪些回调。
m_listEvent记录当前的Event缓存队列,虽然Event都是立即处理的,但在多线程中,仍然可能出现处理不及时而积压的情况,因此需要一个容器存放缓存队列。
EventMgr启动一个工作线程(WorkThreadFunc),查询m_listEvent是否有数据,没有数据就等待,线程挂起。这里与定时器不同,定时器需要sleep一个间隔后再次运行,用于校验是否到期。
事件触发者可以调用PostEvent,向m_listEvent插入一个Event,并通过条件变量m_cond通知工作线程,事件队列中有数据了,需要工作线程进行处理。
工作线程取出事件,交给OnEvent函数处理,在m_mapEvent中查找回调函数并回调。

4、调用方式
我们在ServiceBase中封装调用,方便派生服务使用
基类注册了监听事件(2),由基类的OnEvent函数处理。此后,在服务的任意位置触发这个事件,服务基类都可以收到事件信息,并进行处理。
为管理方便,需要有一个统一的头文件定义事件ID。
Last updated