ACE的前摄器模式笔记
ACE的代码组织
ACE
的前摄器模式中,包括前摄器接口,类命名会有如下形式代码关系
class A
{
A_Impl* implement;
}
class A_Impl
{
}
class WIN32_A : public A_Impl
{
}
调用A
的接口将直接调用指针成员A_Imp
的同名接口(A_Impl
仍然是接口),实际上调用了WIN32_A
对象中的实现。
因为前摄器功能的实现是由接口调用组成的,而实现在平台相关的具体实现中,因此ACE
类的组织形式会给理解代码带来许多麻烦,但是只要理解了上述类关系,仅仅需要从接口(A
)调用中看流程,从平台实现(WIN32_A
)中看具体实现。
后续将列举这3种类,看代码时需要把它们看成一个实现了特定功能的整体,接口类即代表了实现。
基于IOCP的前摄器实现
没有写过Windows IOCP的代码,只是粗略看了ACE源码,可能理解有误
API
函数 | 说明 |
---|---|
CreateIoCompletionPort | 创建/打开完成端口 |
GetQueuedCompletionStatus | 等待完成端口事件,多线程等待 |
PostQueuedCompletionStatus | 主动发送一个完成端口事件,自定义完成端口事件调用 |
有些关于
PostQueuedCompletionStatus
的文章会特别提到使用这个API关闭处理线程的用法,在这个API不常用的条件下,这个例子却是一种误导,同时也会局限对这个API的认识。ACE
通过这个API,实现了IOCP不直接支持的异步连接,使得连接完成事件最终可以在等待线程中处理。这个模拟过程比较复杂,而且需要额外的开销(额外的反应器实现),但是最终使得所有的网络事件(看起来)有着一致的处理流程和一致的结果处理。
ACE前摄器类
接口(A) | 实现接口(A_Imp) | Win32实现 |
---|---|---|
ACE_Proactor | ACE_Proactor_Impl | ACE_WIN32_Proactor |
ACE异步操作包装
接口(A) | 实现接口(A_Imp) | Win32实现 |
---|---|---|
ACE_Asynch_Accept | ACE_Asynch_Accept_Impl | ACE_WIN32_Asynch_Accept |
ACE_Asynch_Connect | ACE_Asynch_Connect_Impl | ACE_WIN32_Asynch_Connect |
ACE_Asynch_Read_Stream | ACE_Asynch_Read_Stream_Impl | ACE_WIN32_Asynch_Read_Stream |
ACE_Asynch_Write_Stream | ACE_Asynch_Write_Stream_Impl | ACE_WIN32_Asynch_Write_Stream |
- 对于ACE_WIN32_Asynch_Accept
,其实现的是Acceptor-Connector模式,调用Windows平台的异步AcceptEx
- 对于ACE_WIN32_Asynch_Read_Stream
和ACE_WIN32_Asynch_Write_Stream
,Windows平台也提供了异步方法
ACE OVERLAPPED包装
原始的OVERLAPPED数据结构定义模糊,需要创建者自行添加标志,在异步事件完成后,根据标志区分事件类型,然后对结构体进行适当的处理。
ACE通过继承OVERLAPPED,为操作OVERLAPPED提供了一致的接口,然后再次派生,为每种操作的OVERLAPPED对象定制complete
实现。通过面向对象的方式使用IOCP接口,使得类设计单一而简单,流程清晰。
接口(A) | 实现接口(A_Imp) | Win32实现 |
---|---|---|
ACE_Asynch_Accept::Result | ACE_Asynch_Accept_Result_Impl | ACE_WIN32_Asynch_Connect_Result |
ACE_Asynch_Connect::Result | `ACE_Asynch_Connect_Result_Impl | ACE_WIN32_Asynch_Connect_Result |
ACE_Asynch_Read_Stream::Result | `ACE_Asynch_Read_Stream_Result_Impl | ACE_WIN32_Asynch_Read_Stream_Result |
ACE_Asynch_Write_Stream::Result | `ACE_Asynch_Connect_Write_Stream_Impl | ACE_WIN32_Asynch_Write_Stream_Result |
异步连接ACE_WIN32_Asynch_Connect
实现
Windows并没有提供异步连接的方法,实际上连接一般是客户端操作,而前摄器模式和IOCP一般用在服务器端。
那么ACE
是怎么模拟客户端异步连接的呢?
- 最先ACE_WIN32_Proactor
有一个ACE_Asynch_Pseudo_Task
成员,它其实就是一个反应器实现。
- 首先ACE_WIN32_Asynch_Connect
同时也继承了ACE_Event_Handler
,这个在反应器模式中常用的基类。
- 然后将ACE_WIN32_Asynch_Connect
的socket
设置为非阻塞模式ACE_NONBLOCK
,调用connect
- 最后,将这个socket
注册到ACE_Asynch_Pseudo_Task
,设置掩码CONNECT_MASK
- 当连接完成时,ACE_WIN32_Asynch_Connect
的成员将被回调,回调函数将操作结果经由ACE_WIN32_Proactor
的post_completion
方法发送给PostQueuedCompletionStatus
,将反应器操作结果转换为前摄器结果回调。
ACE_WIN32_Asynch_Connect
是ACE_WIN32_Proactor
的唯一友元类