ACE_Task介绍(生产者/消费者)

概述

ACE_Task是ACE中的任务或主动对象“处理结构”的基类。ACE使用此类来实现主动对象模式。所有希望成为“主动对象”的对象都必须由此类派生。同时可将它看作是更高级的、更为面向对象的线程。
ACE_Task处理的是对象,因此更有利于构造OO 程序,产生更好的OO软件,而且,它还包括了一种用于 与其他任务通信的易于使用的机制。
ACE_Task可用作:
<1>更高级的线程(常称其为任务)
<2>主动对象模式中的主动对象
ACE任务:
每个任务都含有一或多个线程,以及一个底层消息队列。各个任务通过消息队列进行通信。至于消息队列实现的内在细节程序员不必关注。发送任务用putq() 将消息插入到另一任务的消息队列中,接收任务通过使用getq()将消息提取出来。这样的体系结构大大简化了多线程程序的编程模型。

创建和使用任务的步骤

要搭架一个基于ACE_Task的消息系统,通常要做如下的步骤:
(1)编写一个派生自ACE_Task的类,
指定它的同步策略
同步模式分两种: ACE_MT_SYNCH(多线程)和ACE_NULL_SYNCH(单线程)。多线程模式下线程的消息队列会使用多线程同步策略,会造成线程的阻塞;单线程模式下不存在同步的额外开销;多线程下保证一个线程对象在同一时刻只有一个方法在执行。
指定线程的创建标志:在activate方法执行的时候可以指定线程的内部类型,THR_DETACHED(分离的,可以直接被ACE_Thread_Manager::wait()方法来回收),默认情况下线程的内部类型是THR_JOINABLE(可结合的,此线程退出的状态会被其他线程捕获并作出相应的处理);THR_NEW_LWP (挂钩到内核级线程,会创建一个内核线程);你的线程如果在独立运行一般你会使用:activate(THR_NEW_LWP
| THR_BOUND | THR_DETACHED,1);来创建你的线程

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);
    {
		// putq(msg);
    }
}

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, // 线程的数目,即有多少处理线程 ...)

生产者消费者实例

#include "ace/Log_Msg.h"
#include "ace/Task.h"
#include "ace/OS.h"
#include "ace/Message_Block.h"
#include <stdio.h>
#include <string.h>
#include <iostream>

using namespace std;


typedef struct Data
{
	int len;
	char buffer[20];
	int count;
} DataStruct;

//The Consumer Task.
class Consumer:
	public ACE_Task<ACE_MT_SYNCH>
{
public:
	int open(void*)
	{
		ACE_DEBUG((LM_DEBUG, "(%t) Consumer task opened"));
		cout<<endl;
		//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 * msg =0;
		int count = 0;
		do
		{
			msg=0;
			//Get message from underlying queue
			getq(msg);
			DataStruct *user = (DataStruct*)msg->rd_ptr();
			count = user->count;
			ACE_DEBUG((LM_DEBUG,
				"(%t)Got message: %s,%d,%d from remote task",user->buffer,user->len,user->count));
			cout<<endl;
			delete user;	
			msg->release();
		}while(count < 10);
		return 0;
	}
	int close(u_long)
	{
		ACE_DEBUG((LM_DEBUG,"Consumer closes down"));
		cout<<endl;
		return 0;
	}
};
class Producer : public ACE_Task<ACE_MT_SYNCH>
{
public:
	Producer(Consumer * consumer):consumer_(consumer), count(0)
	{
		//msg_=new ACE_Message_Block((char*)&data_,sizeof(data_));
	}
	int open(void*)
	{
		ACE_DEBUG((LM_DEBUG, "(%t) Producer task opened"));
		cout<<endl;
		//Activate the Task
		activate(THR_NEW_LWP,1);
		return 0;
	}
	//The Service Processing routine
	int svc(void)
	{
		while(count<11)
		{
			//Send message to consumer
			ACE_DEBUG((LM_DEBUG,
				"(%t)Sending message: %d to remote task",count));
			cout<<endl;
			DataStruct *user = new DataStruct();
			sprintf(user->buffer,"hello %d",count);
			user->len = strlen(user->buffer);
			user->count = count;
			msg_=new ACE_Message_Block((char*)user,sizeof(DataStruct));
			consumer_->putq(msg_);
			//Go to sleep for a sec.
			ACE_OS::sleep(1);
			count++;
		}
		return 0;
	}
	int close(u_long)
	{
		ACE_DEBUG((LM_DEBUG,"Producer closes down"));
		cout<<endl;
		return 0;
	}
private:
	int count;
	Consumer * consumer_;
	ACE_Message_Block * msg_;
};
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::system("pause");
	delete producer;
	delete consumer;
	return 0;
}

分析:
以上为经典的生产者-消费者例子,演示了两个任务如何使用底层的消息队列进行通信。我们可以将生产者和消费者看作是不同的ACE_Task类型的对象。方案十分简单,但却是面向对象的,在编写面向对象的多线程程序或主动对象的实例时,我们可采用此方案,它提供了比低级线程API更好的方法。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值