说起C++ 的系统和网络编程开源库,恐怕没有人敢否认ACE的王者地位。其实ACE不光是一个实用的程序库和框架集,它更是一个设计模式的典范应用。ACE在线索引文档:http://www.dre.vanderbilt.edu/Doxygen/Stable/ace/index.html
ACE具有极其明显的分层体系结构,一般划分为三个层次:
1. 操作系统适配层
2. C++包装层
3. 构架和模式层
前面的两层都是对各个平台的底层OS API进行包装,最后化身成通用的C++类或者函数。举个简单的例子,比如ACE_OS::sleep(1)在任何平台下都是休眠一秒,这样就很方便写出跨平台的代码了。更好玩的是第三层,ACE把设计模式玩到了极致,设计出了许多实用的组件。比如任务和主动对象(Active Object),反应堆(Reactor),接受器(Acceptor)和连接器(Connector)。下面简单讲一下这三类模式的应用。
1. 任务和主动对象(Active Object)
那么到底什么是主动对象呢?传统上,所有的对象都是被动的代码段,对象中的代码是在对它发出方法调用的线程中执行的。也就是,调用线程(calling threads)被“借出”,以执行被动对象的方法。
而主动对象却不一样。这些对象持有它们自己的线程(甚或多个线程),并将这个线程用于执行对它们的任何方法的调用。因而,如果你想象一个传统对象,在里面封装了一个线程(或多个线程),你就得到了一个主动对象。
ACE中的主动对象的实现核心是ACE_Task。要实现一个主动对象,只需继承自ACE_TASK。ACE_Task有几个虚函数比较重要。open(), close()分别是对应服务初始化和关闭。可以在open()调用activate()来创建线程执行任务。而ACE_TASK中的所有主动线程的执行入口是虚函数svc()。只需在svc()中加入你的主动对象需要执行的任务代码即可。
2. 反应堆(ACE_Reactor)
在设计模式教科书中这么描述反应堆模式:反应堆本质上提供一组更高级的编程抽象,简化了事件驱动的分布式应用的设计和实现。除此而外,反应堆还将若干不同种类的事件的多路分离集成到易于使用的API中。特别地,反应堆对基于定时器的事件、信号事件、基于I/O端口监控的事件和用户定义的通知进行统一地处理。
描述地比较抽象,简单来讲就是:
a.创建事件处理器,以处理感兴趣的事件。比如handle_input()函数处理可能收到的输入。
int CMyACETask::handle_input (ACE_HANDLE fd);
b.把事件处理器指针和感兴趣的事件登记到反应堆,具体来说就是
m_reactor->register_handler(this, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK );
c.在用户已登记的某个事件发生时,反应堆发出对处理器中相应方法的回调。
3. 接受器(Acceptor)和连接器(Connector)
ACE_Acceptor工厂允许应用开发者改变“助手”对象,以用于:
被动连接建立
连接建立后的处理
同样地,ACE_Connector工厂允许应用开发者改变“助手”对象,以用于:
主动连接建立
连接建立后的处理
接受器和连接器的具体代码比较简单,请见索引文档。