从上一篇“按部就班实现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;
}