现在的位置: 首页 > 综合 > 正文

获取 ACE 主动对象方法返回值的另外一种方法

2019年01月10日 ⁄ 综合 ⁄ 共 2940字 ⁄ 字号 评论关闭

从上一篇“按部就班实现ACE的主动对象”中我们可以看到,我们必须为所有要从客户异步调用的方法编写方法对象。每个方法对象都派生自ACE_Method_Object,并会实现它的call()方法。每个方法对象还维护上下文信息(比如执行方法所需的参数,以及用于获取返回值的ACE_Future对象。这些值作为私有属性维护)。你可以把方法对象看作是方法调用的罩子closure)。客户发出方法调用,使得相应的方法对象被实例化,并被放入启用队列(activation
queue
)中。方法对象是命令(Command)模式的一种形式(参见有关设计模式的参考文献)。

ACE_Activation_Queue是一个队列,方法对象在等待执行时被放入其中。因而启用队列中含有所有等待调用的方法(以方法对象的形式)。封装在ACE_Task中的线程保持阻塞,等待任何方法对象被放入启用队列。一旦有方法对象被放入,任务就将该方法对象取出,并调用它的call()方法。call()方法应该随即调用该方法在ACE_Task中的相应实现。在方法实现返回后,call()方法在ACE_Future对象中设置(set())所获得的结果。

上一篇我们展示了获取异步调用的返回结果的一种方法,下边再展示一种获取异步调用结果的另外一种方法。

// ActiveObject.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "ace/OS_NS_unistd.h"
#include "ace/Activation_Queue.h"
#include "ace/Method_Request.h"
#include "ace/Task.h"
#include "ace/Future.h"
#include "ace/Auto_Ptr.h"

class CAdd;
class CAdd_MethordRequest;
class CScheduler;
class CAgent;

//第一步: 实现一个被动对象
class CAdd
{
public:
	CAdd(int a1, int a2)
	{
		m_a1 = a1;
		m_a2 = a2;
	}
	~CAdd(void)
	{
	}
public:
	int calculate_add()
	{
		return m_a1 + m_a2;
	}

	int geta1()
	{
		return m_a1;
	}

	int geta2()
	{
		return m_a2;
	}
private:
	int m_a1;
	int m_a2;
};

//第二步:从 ACE_Method_Request 继承一个对象,实现他的虚函数 void call()
class CAdd_MethordRequest : public ACE_Method_Request
{
public:
	CAdd_MethordRequest(CAdd add, ACE_Future<int>& retvalue)
	{
		m_padd = new CAdd(add.geta1(), add.geta2());
		returnVal_ = retvalue;
	}
	~CAdd_MethordRequest(void)
	{
		delete m_padd;
	}
public:
	virtual int call(void)
	{
		this->returnVal_.set(this->m_padd->calculate_add());
		return 0;
	}
private:
	CAdd *m_padd;
	ACE_Future<int> returnVal_;
};

//第三步,实现一个task, 其中定义一个ACE_Activation_Queue对象
class CScheduler : public ACE_Task_Base
{
public:
	CScheduler(void)
	{  
		this->activate();
	}

	~CScheduler(void)
	{
	}

public:
	virtual int svc (void)
	{
		while (1)
		{
			//smart pointer, 他的删除我们就不管了。
			auto_ptr<ACE_Method_Request> request(this->activation_queue_.dequeue());
			if (request->call() == -1) break;
		}
		return 0;
	}
	int enqueue (ACE_Method_Request *request)
	{
		return this->activation_queue_.enqueue (request);
	}
private:
	ACE_Activation_Queue activation_queue_;
};

//第四步,实现一个主动对象
class Agent
{
public:
	Agent()
	{
	}
	~Agent(void)
	{
	}
public:
	//这个才是真正的主动对象的方法,这个方法才是客户端调用的真正的方法
	ACE_Future<int> calculate_add(int a1, int a2)
	{
		ACE_Future<int> result;
		CAdd add(a1, a2);
		//想想,什么地方删除new 的对象呢??
		this->scheduler_.enqueue(new CAdd_MethordRequest(add, result));
		return result;
	}
private:
	CScheduler scheduler_;
};

//第五步,获取异步调用结果的一种方法。
class CompletionCallBack : public ACE_Future_Observer<int>
{
public:
	CompletionCallBack (Agent& proxy): proxy_(proxy)
	{
	}
	virtual void update(const ACE_Future<int>& future)
	{
		int result = 0;
		((ACE_Future<int>)future).get(result);
		ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("calculate result: %d\n"), result));
	}
private:
	Agent& proxy_;
};



int main(int argc, char* argv[])
{	
	//定义主动对象
	Agent agent;
	ACE_Future<int> results[10];
	CompletionCallBack cb(agent);

	for (int i = 0 ; i < 10; i++)
	{		
		//调用主动对象的方法
		results[i] = agent.calculate_add(i, i);
	    results[i].attach(&cb);
	}

	//模拟客户端去做其他事情了
	//ACE_OS::sleep (1);  
	//这个事检测调用了主动对象方法的返回值,在时间情况中在其他线程中。
	/*for (int j = 0; j < 10; j++)
	{
		int result = 0;
		results[j].get(result);
		ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("calculate result: %d\n"), result));
	}*/

	ACE_Thread_Manager::instance ()->wait ();

	return 0;
}


 

抱歉!评论已关闭.