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