标题：ACE_Task
ACE_Task

一、概述ACE_Task是ACE中的任务或主动对象“处理结构”的基类。ACE使用此类来实现主动对象模式。所有希望成为“主动对象”的对象都必须由此类派生。同时可将它看作是更高级的、更为面向对象的线程。
ACE_Task处理的是对象，因此更有利于构造OO程序，产生更好的OO软件，而且，它还包括了一种用于
与其他任务通信的易于使用的机制。
ACE_Task可用作：
<1>更高级的线程(常称其为任务)
<2>主动对象模式中的主动对象
PS.ACE任务：
每个任务都含有一或多个线程，以及一个底层消息队列。各个任务通过消息队列进行通信。至于消息队列实现的内在细节程序员不必关注。发送任务用putq() 将消息插入到另一任务的消息队列中，接收任务通过使用getq()将消息提取出来。这样的体系结构大大简化了多线程程序的编程模型。
二、创建和使用任务的步骤从ACE_Task类派生的子类应实现以下业务逻辑：
<1>实现服务初始化和终止方法。
open()方法应该包含所有专属于任务的初始化代码。其中可能包括诸如连接控制块、锁和内存这样的资源。close()方法用于终止。
<2>调用启用(Activation)方法。
在主动对象实例化后，必须通过调用activate()启用它。要在主动对象中创建的线程数目及其它参数，被传递给activate()方法。它将使svc()方法成为所有它生成的线程的启动点。
<3>实现服务专有的处理方法。
在主动对象被启用后，各个新线程在svc() 方法中启动。程序员必须在子类中定义此方法。
三、一个任务间通信的实例//消费者类定义
#i nclude "ace/OS.h"
#i nclude "ace/Task.h"
#i nclude "ace/Message_Block.h"
//The Consumer Task.
class Consumer : 
public ACE_Task<ACE_MT_SYNCH>
{
public:
int open(void*)
{
ACE_DEBUG((LM_DEBUG, "(%t) Producer task opened \n"));
//Activate the Task
activate(THR_NEW_LWP,1);
return 0;
}
//The Service Processing routine
int svc(void)
{
//Get ready to receive message from Producer
ACE_Message_Block * mb = 0;
do
{
mb = 0;
//Get message of underlying queue
getq(mb);
ACE_DEBUG((LM_DEBUG,
"(%t) Got message: %d from remote task\n", *mb->rd_ptr()));
}while(*mb->rd_ptr()<10);
return 0;
}
int close(u_long)
{
ACE_DEBUG((LM_DEBUG, "Consumer closes down \n"));
return 0;
}
};
//生产者类定义
class Producer : 
public ACE_Task<ACE_MT_SYNCH>
{
public:
Producer(Consumer * consumer) : 
consumer_(consumer), data_(0)
{
mb = new ACE_Message_Block((char *)&data_, sizeof(data_));
}
int open(void *)
{
ACE_DEBUG((LM_DEBUG, "(%t) Producer task opened \n"));
//Activate the Task
activate(THR_NEW_LWP, 1);
return 0;
}
//The Service Processing routine
int svc(void)
{
while(data_ < 11)
{
//Send message to consumer
ACE_DEBUG((LM_DEBUG,
"(%t) Sending message: %d to remote task\n", data_));
consumer_->putq(mb_);
//Go to sleep for a sec.
ACE_OS::sleep(1);
data_++;
}
return 0;
}
int close(void)
{
ACE_DEBUG((LM_DEBUG, "Producer closes down \n"));
return 0;
}
private:
char data_;
Consumer * consumer_;
ACE_Message_Block * mb_;
};
//main()函数
int main(int argc, char *argv[])
{
Consumer * consumer = new Consumer;
Producer * producer = new Producer(consumer);
producer->open(0);
consumer->open(0);
//Wait for all the tasks to exit. ACE_Thread_Manager::instance()->wait();
ACE_OS::exit(0);
}
分析：
以上为经典的生产者-消费者例子，演示了两个任务如何使用底层的消息队列进行通信。我们可以将生产者和消费者看作是不同的ACE_Task类型的对象。方案十分简单，但却是面向对象的，在编写面向对象的多线程程序或主动对象的实例时，我们可采用此方案，它提供了比低级线程API更好的方法。
ACE_Task框架
在我看来，ACE的ACE_Task框架提供了一种基于消息的编程模式，可以Windows编程的消息循环进行类比。
ACE_Task
Windows 消息循环
说明
消息类型
ACE_Message_Block*
MSG
Windows 消息用MSG结构表示，ACE_Task中因为不能预计各种应用中消息的类型，所以ACE_Message_Block基本上可以理解为是对一个指针的封装，这个指针指向实际的一块内存或是一个对象等等。在创建ACE_Message_Block时，可以指定是由ACE_Message_Block来管理内存（构造函数中指定一个size_t类型的大小），还是由我们自己管理内存（构造函数中指定一个指针）。而一个ACE_Message_Block类型的指针，就是一个消息，我们通过传递它来进行逻辑的业务处理。
发送消息
ACE_Task::putq
SendMessage
事实上，到底用SendMessage还是PostMessage与ACE_Task::putq来进行类比，我很为难，PostMessage发送一个消息后立刻返回，这与通常的ACE_Task::putq行为非常类似，因为ACE_Task是运行在另外一个线程上，ACE_Task::putq只是完成将消息插入到消息队列的工作，理论上它应该立刻返回，但实际上，ACE_Task的消息队列有容量大小限制，这个限制由我们自己限定，当当前消息队列满时，ACE_Task::putq将阻塞一直到可以插入，这时候就比较类似与SendMessage，
取出消息
ACE_Task::getq
GetMessage
GetMessage和ACE_Task::getq在当前消息队列没有消息时都会阻塞到有消息可用为止，所以对于它们的使用比较类似，通常会写一个消息循环函数
BOOL bRet;
MSG msg;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{ 
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg); 
DispatchMessage(&msg); 
}
}
ACE_Message_Block * msg;
while(getq(msg) != -1) // int putq (ACE_Message_Block *, ACE_Time_Value *timeout = 0);
{
// process msg here
}
消息处理函数
默认没有提供
WNDPROC
通过TranslateMessage和DispatchMessage，Windows将消息投递到相映窗口的WNDPROC上，ACE_Task没有提供类似与WNDPROC的回调函数，如果愿意，我们可以在ACE_Task上写出类似的结构，而通常，我们直接在消息循环中编写处理消息的代码
尽管看起来ACE_Task提供的消息系统与WIndows的消息系统很象，但实际上，它们还是有比较大的区别，要搭架一个基于ACE_Task的消息系统，通常要做如下的步骤： 
编写一个派生自ACE_Task的类，指定它的同步模式
ACE_Task的消息队列可以由多个处理线程共享使用，所以需要提供同步模式，例如ACE_MT_SYNCH和ACE_NULL_SYNCH分别表示基于多线程的同步和不使用同步，这个参数是ACE_Task的一个模板参数。 class My_Task : public ACE_Task<ACE_MT_SYNCH>
{
public:
virtual int svc();
}
重载ACE_Task的svc 方法，编写消息循环相关的代码 int My_Task::svc()
{
ACE_Message_Block * msg;
while(getq(msg) != -1) // int putq (ACE_Message_Block *, ACE_Time_Value *timeout = 0);
{
// process msg here
}
}
svc 方法相当与处理线程的入口方法。 
假设My_Task是一个基于ACE_Task的类，创建一个唯一的My_Task实例，这个可以通过
typedef ACE_Singleton<MyTask, SYNCH_METHOD> MYTASK;
然后总是使用MYTASK::instance方法来获取一个My_Task的指针来完成。 在适当位置（一般是程序开始的时候），让My_Task开始工作
MYTASK::intance()->activate(
THR_NEW_LWP | THR_JOINABLE |THR_INHERIT_SCHED , // 线程创建的属性
n_threads = 1, // 线程的数目，即有多少处理线程
...)在有消息发生的时候发送消息 ACE_Message_Block * msg;
// fill the msg
...
MYTASK::intance()->putq(msg);
最后考虑一个使用ACE_Task的实例，在一个编写WEB服务器的项目中，类Request_Handler负责处理HTTP请求，Request_Hanlder派生自ACE_Task，当有请求时，其他的代码将Http请求构造成一个ACE_Message_Block，并调用Request_Handler的putq方法将请求插入消息队列，Request_Handler 配置为根据CPU的数目创建处理线程，Request_Handler的svc方法从队列中获取请求进行处理，然后将处理的结果构造成为一个ACE_Message_Block,插入到Response_Handler的消息队列，Response_Handler也派生自ACE_Task，但它只有一个处理线程，它仅仅将相应的数据写回给客户端。