ACE的主動對象模式的實現
對分散式系統設計來說,ACE提供的主動對象模式是讓我們在系統框架構建的時候,回歸到傳統的單線程編程思維。你可能要問,既然有主動對象,那必然有被動對象,沒有錯,確實有被動對象,那到底什麼是主動對象?什麼又是被動對象呢?
被動對象:
假如我們要給一個客戶端提供一個方法,計算兩個數之和。我們一般定義一個對象,然後實現具體的加法運算操作,客戶端在調用的時候,首先實例化我們這個對象,然後再執行這個方法。此時,這個對象的加法運算操作的執行和客戶端的調用線程在一個線程中完成。這是標準的單線程執行順序。我們把這種對象叫做被動對象,被動對象所提供的方法叫做被動對象的方法。
主動對象:
同理,假如我們要給一個客戶端提供一個方法,計算兩個數之和。同樣我們如果實現了一個主動對象,同時給這個主動對象增加一個計算兩個數之和的主動對象方法,那麼當客戶端調用這個主動對象所提供的方法的時候,這個對象的加法運算操作的執行和客戶端的調用線程就不在一個線程中完成。而是在另外的一個線程中執行。我們把這種對象叫做主動對象,主動對象所提供的方法叫做主動對象的方法。
// 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) { 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); this->scheduler_.enqueue(new CAdd_MethordRequest(add, result)); return result; } private: CScheduler scheduler_; }; int main(int argc, char* argv[]) { ACE_Future<int> results[10]; //定義主動對象 Agent agent; for (int i = 0 ; i < 10; i++) { //調用主動對象的方法 results[i] = agent.calculate_add(i, i); } //模擬客戶端去做其他事情了 ACE_OS::sleep (5); //這個事檢測調用了主動對象方法的返回值,在時間情況中在其他線程中。 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; }