reactor设计模式
reactor设计模式,是一种基于事件驱动的设计模式。
这个模式的结构图如下:
图中的handle对应的是操作系统提供的句柄,例如I/O句柄,Event_Handler类持有这些句柄,(其实就是事件,可以看成是Type)
Handles:表示操作系统管理的资源,我们可以理解为fd
Synchronous Event Demultiplexer:同步事件分离器,阻塞等待Handles中的事件发生(select、poll、epoll)
Initiation Dispatcher(Reactor):初始分派器,作用为添加Event handler(事件处理器)删除Event handler以及分派事件给Event handler也就是说,SynchronousEvent Demultiplexer负责等待新事件发生,事件发生时通知InitiationDispatcher(Reactor),然后Initiation Dispatcher调用event handler处理事件
Event Handler:事件处理器的接口
Concrete Event Handler:事件处理器的实际实现,而且绑定了一个Handle因为在实际情况中,我们往往不止一种事件处理器,因此这里将事件处理器接口和实现分开,与C++Java这些高级语言中的多态类似
过程如下:
reactor类内部提供一个事件循环:handle_events(),事件循环的代码实现利用了操作系统提供的多路分离函数(Select,poll,epoll等)(这个方法调用多路复用器。)
WaitForMultipleObjects或者select等,这些多路分离的函数的特点是,可以同时等待多个句柄,在等待过程中所在线程属于挂起状态(阻塞),不消耗CPU时间,一旦某个句柄被触发,则线程被唤醒,函数将返回,线程可以执行后面的代码,
利用多路分离函数的这一特点,根据被激活的句柄对应的特定事件,调用相关的事件处理函数。可以实现事件循环。
register_handler()函数用于将Event_Handler对象注册到事件驱动列表 中,保证对于某一类型的事件,会调用Event_Handler类的响应函数handle_event()。
reactor类在做多路分离时需要操纵Event_Handler类的Handle,因此Event_Handler类需要提供get_handle()函数。
另外,当程序不需要再对特定事件响应时,需要把Event_Handler对象从事件驱动列表中删除,因此reactor类还实现了 remove_handler函数。
因为reactor相对稳定,一旦实现,不需要再定制,所以没有提供一个抽象接口类,但Event_Handler是经常需要根据不同 的需求定制的,因此需要提供一个抽象接口类,然后根据实际需求编写派生类,提供具体句柄,并实现相关虚函数。
Reactor模式实现
在Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events中,一直以Logging Server
来分析Reactor模式,这个Logging Server
的实现完全遵循这里对Reactor描述,因而放在这里以做参考。Logging Server
中的Reactor模式实现分两个部分:Client连接到Logging Server
和Client向Logging Server
写Log。因而对它的描述分成这两个步骤。
Client连接到Logging Server
Reactor_LoggingServer_connect.png
Logging Server
注册LoggingAcceptor
到InitiationDispatcher
。Logging Server
调用InitiationDispatcher的handle_events()方法启动。InitiationDispatcher
内部调用select()
方法(Synchronous Event Demultiplexer
),阻塞等待Client
连接。Client
连接到Logging Server
。InitiationDisptcher
中的select()
方法返回,并通知LoggingAcceptor
有新的连接到来。LoggingAcceptor
调用accept
方法accept
这个新连接。LoggingAcceptor
创建新的LoggingHandler
。- 新的
LoggingHandler
注册到InitiationDispatcher
中(同时也注册到Synchonous Event Demultiplexer
中),等待Client
发起写log请求。
Client向Logging Server写LogReactor_LoggingServer_log.png
Client
发送log到Logging server
。InitiationDispatcher
监测到相应的Handle
中有事件发生,返回阻塞等待,根据返回的Handle
找到LoggingHandler
,并回调LoggingHandler
中的handle_event()
方法。LoggingHandler
中的handle_event()
方法中读取Handle
中的log信息。- 将接收到的log写入到日志文件、数据库等设备中。
3.4步骤循环直到当前日志处理完成。 - 返回到
InitiationDispatcher
等待下一次日志写请求。
这模式的优点是本身不涉及多线程,从而避免了线程的上下文切换。
对于响应事件处理时间较短的情况下,可以考虑使用这个模式。
如果处理一个事件需要花费大量时间,就不能使用这个模式,那样会导致其他事件处理被阻塞。
ACE_Reactor框架是这一模式的半成品,用户只要做三件事情就可以实现并使用这一模式:
1.从Event_Handler派生一个或多个类
2.向Reactor类登记应用的事件处理对象
3.运行Reactor事件循环(它就会调用IO分离函数,开始轮讯事件,等到有事件返回,传给事件处理者)。