ACE笔记(二):ACE_Task框架

作者:李嘉
日期:2006-8-19
未经本人的书面许可,请勿进行任何商业目的的转载。

    在我看来,ACE的ACE_Task框架提供了一种基于消息的编程模式,可以Windows编程的消息循环进行类比。

    ACE_TaskWindows 消息循环说明
消息类型ACE_Message_Block*MSGWindows消息用MSG结构表示,ACE_Task中因为不能预计各种应用中消息的类型,所以ACE_Message_Block基本上可以理解为是对一个指针的封装,这个指针指向实际的一块内存或是一个对象等等。在创建ACE_Message_Block时,可以指定是由ACE_Message_Block来管理内存(构造函数中指定一个 size_t类型的大小),还是由我们自己管理内存(构造函数中指定一个指针)。而一个ACE_Message_Block类型的指针,就是一个消息,我们通过传递它来进行逻辑的业务处理。
发送消息ACE_Task::putqSendMessage事实上,到底用SendMessage还是PostMessage与ACE_Task::putq来进行类比,我很为难,PostMessage发送一个消息后立刻返回,这与通常的ACE_Task::putq行为非常类似,因为ACE_Task是运行在另外一个线程上,ACE_Task::putq只是完成将消息插入到消息队列的工作,理论上它应该立刻返回,但实际上,ACE_Task的消息队列有容量大小限制,这个限制由我们自己限定,当当前消息队列满时,ACE_Task::putq将阻塞一直到可以插入,这时候就比较类似与SendMessage,
取出消息ACE_Task::getqGetMessageGetMessage和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的消息系统,通常要做如下的步骤:

  1. 编写一个派生自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();
    }
    	
  2. 重载 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 方法相当与处理线程的入口方法。
  3. 假设 My_Task是一个基于ACE_Task的类,创建一个唯一的My_Task实例,这个可以通过
    typedef ACE_Singleton<MyTask, SYNCH_METHOD> MYTASK;
    然后总是使用MYTASK::instance方法来获取一个My_Task的指针来完成。
  4. 在适当位置(一般是程序开始的时候),让My_Task开始工作
    MYTASK::intance()->activate(
    THR_NEW_LWP | THR_JOINABLE |THR_INHERIT_SCHED , // 线程创建的属性
    n_threads = 1, // 线程的数目,即有多少处理线程
    ...)
  5. 在有消息发生的时候发送消息
    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,但它只有一个处理线程,它仅仅将相应的数据写回给客户端。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值