前言
为什么说ACE C++网络通信框架的设计非常优良,无论阅读它的类设计、方法设计、源代码文件结构都是具有非常典型的模式
模式的重复出现,会减轻学习新组件的惊讶程度 :)
鸟瞰
对照此图验证对于ACE的了解,和寻找合适的搭建组件
API阅读
阅读API Doc总比直接阅读代码轻松,所以,建议经常阅读ACE Class API文档
Class类设计
- 默认构造函数
辅以
open
接口在对象默认构造后,进行创建;此实践符合C++的编程建议规则,避免构造半成品对象
- 有参构造函数
- *Base提供某一类的骨架实现
- template<> class A<>:public *base { … }通过模板参数,提供鸭子辨型偏序化能力,比继承的弹性更强,约束降低
ACE_Get_Opt
提供类unix 命令参数选项的解析风格,针对于main入口传递的argc、argv进行选项解析
ACE_Task
可以成为主动对象,自带线程池和消费输入消息的队列;在程序建构的时间,可以作为基础组件,进行任务分解、队列数据交换进行多线程协作,用来构建程序的骨架是非常方便的
ACE_Event_Handler
此为基础类,具有一个非常特殊的设计,handle_*方法如果返回-1
,会作为一个特殊指示,进而导致handle_close接口的调用。
如果实现符合ACE的设计,接口配合起来也是非常方便的;但如果您忘记了,有时也会造成一些麻烦,例如,handle_input遇到读入数据为零的异常,如果依然return 0
,则会在短时间内,在Reactor
中无限循环重复处理这个异常句柄,造成CPU冲高!
int ACE_Event_Handler::handle_close ( ACE_HANDLE handle,ACE_Reactor_Mask close_mask )
Called when a handle_*() method returns -1 or when the remove_handler() method is called on an ACE_Reactor. The close_mask indicates which event has triggered the handle_close() method callback on a particular handle.
Reactor
反应器,可以作为定时器、信号、IO事件的集中调度和派发
ACE_Message_Block
在数据结构中我们通常用连续存储,或链表存储两种结构来应对不同数据结构的存储需求。ACE_Message_Block类号称全ACE框架都可以使用的类,它的API接口能力很强大的!
- 基于wr_ptr、rd_ptr的数组操作能力
- 基于cont的的chain分片能力
- 基于pre、next的list双链能力
- 设置更大size后,内存动态增长的能力
- 定制化内存管理器的能力
- 支持引用技术
> Stores messages for throughout ACE (particularly in an ACE_Message_Queue)
基于ACE框架的程序普通结构
普通结构的设计假定:
- IO处理不会占用太多CPU时间,所以,用一个Reactor足以;相对于CPU, 网卡为低速、慢设备
- 后端的业务处理通常比较消耗CPU,所以,可以使用具有线程池的ACE_Task组件进行应对;甚至使用异步IO进行处理
method方法设计
- 结对 FieldType mbrField() 、mbrField(FieldType[&|*])
- 大量默认参数的使用,提供方法扩展能力的同时,又可以无干扰地不显现这些参数信息,避免阅读代码压力
源码文件结构
- *.h
-
- *_T.h
-
- *.cpp
-
- *_T.cpp
-
- *.inl
-
- *_T.inl
-
- 在*.h & *.cpp中提供类实现或*Base类的实现
- 在*.inl中提供需要内联代码的实现,默认高性能实现,内联函数提供了C++编译器保证的函数参数检查;需要将此类文件识别为CPP文件
- 在*_T.h & *_T.cpp & *_T.inl中提供模板类的实现
在ACE开发规范中说明了
.inl
和_T.*
的不同要求,可以参见后面链接
使用ACE框架的例子目录
在$ACE_ROOT/netsvcs目录中提供了官方使用ACE网络框架,实现鸟瞰图中命名服务、时间服务、日志服务等例子程序,可以进行研读 :)
无处不在的设计模式
- Acceptor、Connector模式
- Adapter
- Factory [implementation] | Factory Method
- Bridge
- Proxy
- Singleton
- Strategy