标签:
转载于:http://www.cnblogs.com/TianFang/archive/2006/12/12/590153.html
我们简单的介绍了一下ACE主动对象实现方式,同时提出了两个问题:
要解决这两个问题,首先得介绍一下ACE_Future对象,ACE_Future是表示一个会在将来被赋值的"期货"对象,可以通过ready()函数查询它是否已经被赋值。该对象创建的时候是未赋值的,后期可以通过set()函数来进行赋值,所赋的值可以通过get()函数来获取。
下面代码演示了它的基本用法:
1 #include "ace/Future.h" 2 3 #include <string> 4 #include <iostream> 5 using namespace std; 6 7 void get_info(ACE_Future<string> &fu) 8 { 9 string state = fu.ready()?"ready":"not ready"; 10 cout<<endl<<state<<endl; 11 if(fu.ready()) 12 { 13 string value; 14 fu.get(value); 15 cout<<"value:\t"<<value<<endl; 16 } 17 } 18 19 int main(int argc, char *argv[]) 20 { 21 ACE_Future<string> fu; 22 get_info(fu); 23 fu.set("12345"); 24 get_info(fu); 25 26 return 0; 27 }
通过ACE_Future对象来解决上述两个问题的方法如下:
使用的时候要注意一下ACE_Future对象的生命周期。
为了演示了如何获取主动命令的执行状态和结果,我将上篇文章中的代码改动了一下,日志类记录日志后,会将记录的内容作为返回值返回,该返回值会通过ACE_Future对象返回,代码如下:
1 #include "ace/OS.h" 2 #include "ace/Task.h" 3 #include "ace/Method_Object.h" 4 #include "ace/Activation_Queue.h" 5 #include "ace/Auto_Ptr.h" 6 7 #include "ace/Future.h" 8 9 #include <string> 10 #include <iostream> 11 using namespace std; 12 13 class Logger: public ACE_Task<ACE_MT_SYNCH> 14 { 15 public: 16 Logger() 17 { 18 this->activate(); 19 } 20 21 int svc(); 22 string LogMsg(const string& msg); 23 void LogMsgActive (const string& msg,ACE_Future<string> *result); 24 25 private: 26 ACE_Activation_Queue cmdQueue; //命令队列 27 }; 28 29 class LogMsgCmd: public ACE_Method_Object 30 { 31 public: 32 LogMsgCmd(Logger *plog,const string& msg,ACE_Future<string> *result) 33 { 34 this->log=plog; 35 this->msg=msg; 36 this->result=result; 37 } 38 39 int call() 40 { 41 string reply = this->log->LogMsg(msg); 42 result->set(reply); 43 return 0; 44 } 45 46 private: 47 ACE_Future<string> *result; 48 Logger *log; 49 string msg; 50 }; 51 52 string Logger::LogMsg(const string& msg) 53 { 54 ACE_OS::sleep(2); 55 cout<<endl<<msg<<endl; 56 return msg; 57 } 58 59 //以主动的方式记录日志 60 void Logger::LogMsgActive(const string& msg,ACE_Future<string> *result) 61 { 62 //生成命令对象,插入到命令队列中 63 cmdQueue.enqueue(new LogMsgCmd(this,msg,result)); 64 } 65 66 int Logger::svc() 67 { 68 while(true) 69 { 70 //遍历命令队列,执行命令 71 auto_ptr<ACE_Method_Object> mo 72 (this->cmdQueue.dequeue ()); 73 74 if (mo->call () == -1) 75 break; 76 } 77 return 0; 78 } 79 80 void get_info(ACE_Future<string> &fu) 81 { 82 string state = fu.ready()?"ready":"not ready"; 83 cout<<endl<<state<<endl; 84 if(fu.ready()) 85 { 86 string value; 87 fu.get(value); 88 cout<<"value:\t"<<value<<endl; 89 } 90 } 91 92 int main (int argc, ACE_TCHAR *argv[]) 93 { 94 ACE_Future<string> result; 95 Logger log; 96 log.LogMsgActive ("hello",&result); 97 98 while(true) 99 { 100 get_info(result); 101 if(result.ready()) 102 break; 103 ACE_OS::sleep(1); 104 } 105 106 cout<<endl<<"cmd end"<<endl; 107 108 while(true) 109 ACE_OS::sleep(1); 110 111 return 0; 112 }
代码比较简单,这里就不多解释了。
这种查询模式比较简单有效,但存在一个问题:调用线程必须不断轮询ACE_Future对象以获取返回值,这样的效率比较低。可以通过观察者模式解决这个问题:在ACE_Future对象上注册一个观察者,当ACE_Future对象的值发生改变(异步命令执行完成)时主动通知该观察者,从而获取返回值。
ACE中的观察者模式可以通过ACE_Future_Observer来实现,使用方法如下:
1 #include "ace/Future.h" 2 3 #include <string> 4 #include <iostream> 5 using namespace std; 6 7 class MyObserver:public ACE_Future_Observer<string> 8 { 9 virtual void update (const ACE_Future<string> &future) 10 { 11 string value; 12 future.get(value); 13 cout<<endl<<"change:\t"<<value<<endl; 14 } 15 }; 16 17 int main(int argc, char *argv[]) 18 { 19 MyObserver obv; 20 ACE_Future<string> fu; 21 22 fu.attach(&obv); 23 24 ACE_OS::sleep(3); 25 fu.set("12345"); 26 27 while(true) 28 ACE_OS::sleep(3); 29 30 return 0; 31 }
通过观察者模式,可以更有效,及时的获取异步命令的返回值,但同时也增加了程序结构的复杂度并且难以调试,使用的时候应该根据需要选取合适的方式。
标签:
原文地址:http://www.cnblogs.com/shmilxu/p/4860505.html