使用ACE提供的封装类,可以方便的实现主动对象模式。实现主动模式需要的ACE封装类:
- ACE_Task:主动对象类的父类,用于派生线程,异步执行用户的异步调用请求。
- ACE_Activation_Queue:用户的异步调用请求被封装为对象,排入此执行队列。此队列使用ACE_Message_Queue<ACE_SYNCH>实现,因此在使用此队列时无需再加额外的锁。
- ACE_Method_Request:用户的异步调用请求封装为此类的对象,放到ACE_Activation_Queue队列,等待异步执行。
- ACE_Future<T>:用于返回异步执行的结果。
主动对象模式具体实现方法:
客户的主动对象类继承ACE_Task,并包含一个ACE_Activation_Queue私有成员变量。代码如下:
1 #include "ace/Task.h"
2 #include "ace/Activation_Queue.h"
3 #include "ace/Future.h"
4 #include "ace/Method_Request.h"
5
6
7 //Active object
8 class My_Active_Object: public ACE_Task<ACE_MT_SYNCH>
9 {
10 public:
11 //Initialization and termination methods
12 My_Active_Object();
13 ~My_Active_Object();
14 virtual int open (void *);
15 virtual int close (u_long flags = 0);
16
17 //The entry point for all threads created in the My_Active_Object
18 virtual int svc (void);
19
20
21 //Asynchronous function provided by the My_Active_Object
22 //Assume the return value is u_long. This function will
23 //put the user's request into the activation_queue_, which
24 //whill be dequeued in the threads. In the thread, the reques
25 //will call the actual implemetation.
26 ACE_Future<u_long> Asynch_fun();
27
28 //Actual implementation method of Asynch_fun()
29 u_long Asynch_fun_i();
30 private:
31
32 ACE_Activation_Queue activation_queue_;
33 };
其中 Asynch_fun()是提供给用户的异步调用方法,当用户调用此方法时,将用户的请求封装进一个ACE_Method_Request对象,放置到activation_queue_队列,队列上的请求,将在主动对象的私有线程中执行。为了将用户请求封装进ACE_Method_Request对象,我们需要定义自己用户请求类,此类继承自ACE_Method_Request类 :
35 //method request
36 class Asynch_fun_Request: public ACE_Method_Request
37 {
38 public:
39 Asynch_fun_Request(My_Active_Object *active_object,
40 ACE_Future<u_long> &future_result);
41 ~Asynch_fun_Request();
42
43 //The call() method will be called by the Active Object
44 //class, once this method object is dequeued from the activation
45 //queue. This is implemented so that it does two things. First it
46 //must execute the actual implementation method (which is specified
47 //in the My_Active_Object class. Second, it must set the result it obtains from
48 //that call in the future object that it has returned to the client.
49 //Note that the method object always keeps a reference to the same
50 //future object that it returned to the client so that it can set the
51 //result value in it.
52 virtual int call (void);
53 private:
54 My_Active_Object *active_object_;
55 ACE_Future<u_long> future_result_;
56 };
在主动对象的私有线程中,将取下此类的对象,并调用此对象的call()方法,而cal()l方法则调用主动对象实际的实现方法 Asynch_fun_i()。相关代码如下:
70 int Asynch_fun_Request::call(void)
71 {
72 ACE_DEBUG ((LM_DEBUG, "(%t) Asynch_fun_Request::call() is called.\n"));
73 future_result_.set(active_object_->Asynch_fun_i());
74 }
下面我们来看一下主动对象类的几个方法的实现:
svc()方法取下Asynch_fun_Request类的对象,执行其call()方法。
98 int My_Active_Object::svc()
99 {
100 ACE_DEBUG ((LM_DEBUG, "(%t) My_Active_Object::svc() is called.\n"));
101 while(1)
102 {
103 // Dequeue the next method object (we use an auto pointer in
104 // case an exception is thrown in the <call>).
105 auto_ptr<ACE_Method_Request> mo
106 (this->activation_queue_.dequeue ());
107 ACE_DEBUG ((LM_DEBUG, "(%t) calling method object\n"));
108
109 // Call it.
110 if (mo->call () == -1)
111 break;
112
113 // Destructor automatically deletes it.
114 }
115 return 0;
116 }
Asynch_fun()方法为提供给用户的异步调用方法,此方法被调用时,将动态分配一个Asynch_fun_Request对象,并放置到执行队列上,然后立即返回一个ACE_Future对象。这个ACE_Future对象中的返回值,将在实际实现函数中设置。
122 ACE_Future<u_long> My_Active_Object::Asynch_fun()
123 {
124 ACE_DEBUG ((LM_DEBUG, "(%t) My_Active_Object::Asynch_fun() is called.\n"));
125
126 ACE_Future<u_long> resultant_future;
127
128 //Create and enqueue method object onto the activation queue
129 this->activation_queue_.enqueue
130 (new Asynch_fun_Request(this,resultant_future));
131
132 return resultant_future;
133 }
Asynch_fun_i()方法为实际的实现函数,这个函数只不过是模拟慢操作,睡眠2秒钟。
135 u_long My_Active_Object::Asynch_fun_i()
136 {
137 static u_long re = 8888;
138 ACE_DEBUG ((LM_DEBUG, "(%t) My_Active_Object::Asynch_fun_i() is called.\n"));
139 //Go to sleep for a while to simulate slow I/O device
140 ACE_OS::sleep(2);
141 return re++;
142 }
总结:用户使用主动模式时,只需继承ACE_Task类,并在其中包含一个ACE_Activation_Queue队列,提供给用户相应的异步调用函数,异步调用函数中分配一个ACE_Method_Request子类对象,并放置到ACE_Activation_Queue队列。主动对象类中svc线程将异步请求取下队列,执行请求,并设置返回值。