1.主动对象(Active Objects)
是一种专门的设计模式,给线程间的协作式处理提供了基于对象的解决方案。
需求基础:两个主动对象应该能通过看起来像是常规方法调用的方式进行通信,但这些方法将在接收者的上下文、而不是调用者的上下文中执行。每个主动对象都拥有私有控制线程,用于执行客户在这个对象上调用的任何方法。
2.模式的参与者
(1)Method_Request(方法请求)
以对象的形式封装方法调用(method call)的对象(Command模式)。接收者接口上的每个方法都有一个方法请求类与之关联。为了调用Receiver Implementation上的方法,方法请求需要拥有指向Receiver Implementation的引用。
(2)Receiver Implementation(接收者对象实现)
相应具体的方法的实现
(3)Receiver Proxy(接收者对象代理)
客户将通过接收者对象代理来发出请求。这个类把方法调用(method invocation)转变成方法请求(method request),并把它们插入激活队列中。代理对象保存一个引用,指向真正的接收者实现对象(Receiver Implementation)(因为上面的那个转变的过程需要这个对象)(Proxy模式)。
(4)Scheduler(调度者)ACE_Task
拥有用一个指向激活队列(Activation Queue)的引用,主动对象所使用的私有控制线程会在这个队列上保持阻塞,直到有新的方法请求到来。当请求到达时,该私有线程会苏醒过来,从队列中取出请求,然后执行它。
(5)Activation Queue(激活队列)
调度者优先级队列。所有的方法请求都由代理对象(实际通过Scheduler)放在这个队列中,并由主动对象的私有线程拾取。
(6)Future(期货)
返回给客户的一个令牌,可以在后面进行“兑换”,获取异步操作的结果。
(7)Future Observer(期货观察者)
与某个期货相关联的回调对象(Command模式),当异步调用的返回值在期货对象中被设置时,这个回调对象会被调用,也就是说,该对象会在异步操作完成时被调用。
Active Objects结合了Command模式和Proxy模式。
3.模式参与者的关系图
4.例子
//main.cpp
#pragma comment(lib,"ACEd.lib")
#define NTRACE 0
#include <ace/OS.h>
#include <ace/Log_Msg.h>
#include <ace/Thread_Manager.h>
#include <ace/Future.h>
#include "HA_ControllerAgentProxy.h"
int ACE_TMAIN(int, ACE_TCHAR *[])
{
HA_ControllerAgentProxy controller;
ACE_Future<int> results[10];//Future(期货)
for (int i = 0 ; i < 10; i++)
results[i] = controller.status_update();
ACE_OS::sleep(5); // Do other work.
// Get results...
for (int j = 0; j < 10; j++)
{
int result;
results[j].get(result);
ACE_DEBUG((LM_DEBUG,
ACE_TEXT("New status_update %d\n"),
result));
}
// Cause the status_updater threads to exit.
controller.exit();
ACE_Thread_Manager::instance()->wait();
getchar();
return 0;
}
|
//HA_ControllerAgentProxy.h
Receiver Proxy(接收者对象代理)
#pragma once
#define NTRACE 0
#include <ace/Log_Msg.h>
#include <ace/Future.h>
#include "ExitMethod.h"
#include "Scheduler.h"
#include "StatusUpdate.h"
#include "HA_ControllerAgent.h"
#pragma once
class HA_ControllerAgentProxy
{
private:
Scheduler scheduler_;//use it to to a Method_Request to //Activation Queue
HA_ControllerAgent controller_;//Receiver
// This acts as a Proxy to the controller impl object.
public:
ACE_Future<int> status_update(void)
{
ACE_TRACE(ACE_TEXT("HA_ControllerAgentProxy::status_update"));
ACE_Future<int> result;
// Create and enqueue a method request on the scheduler.
this->scheduler_.enqueue(new StatusUpdate(this->controller_, result));
// Return Future to the client.
return result;
}
void exit(void)
{
ACE_TRACE(ACE_TEXT("HA_ControllerAgentProxy::exit"));
this->scheduler_.enqueue(new ExitMethod);
}
};
|
StatusUpdate.h
Method_Request
#pragma once
#include <ace/Log_Msg.h>
#include <ace/Future.h>
#include <ace/Method_Request.h>
#include "HA_ControllerAgent.h"
class StatusUpdate : public ACE_Method_Request
{
private:
HA_ControllerAgent & controller_;
ACE_Future<int> returnVal_;
public:
StatusUpdate(HA_ControllerAgent& controller,
ACE_Future<int>& returnVal)
: controller_(controller), returnVal_(returnVal)
{
ACE_TRACE(ACE_TEXT("StatusUpdate::StatusUpdate"));
}
virtual int call(void)
{
ACE_TRACE(ACE_TEXT("StatusUpdate::call"));
// status_update with the controller.
this->returnVal_.set(this->controller_.status_update());
return 0;
}
};
|
ExitMethod.h
Method_Request
#pragma once
#include <ace/Method_Request.h>
class ExitMethod : public ACE_Method_Request
{
public:
virtual int call(void)
{
// Cause exit.
return -1;
}
};
|
HA_ControllerAgent.h
Receiver Implementation
#pragma once
#include <ace/Log_Msg.h>
class HA_ControllerAgent
{
private:
int next_result_id(void)
{
ACE_TRACE(ACE_TEXT("HA_ControllerAgent::next_cmd_id"));
return status_result_++;
}
int status_result_;
// Proxy to the HA_Controller that is on the network.
public:
HA_ControllerAgent()
{
ACE_TRACE(ACE_TEXT("HA_ControllerAgent::HA_ControllerAgent"));
status_result_ = 1;
}
int status_update(void)
{
ACE_TRACE(ACE_TEXT("HA_ControllerAgent::status_update"));
ACE_DEBUG((LM_DEBUG,
ACE_TEXT("Obtaining a status_update in %t ")
ACE_TEXT("thread of control\n")));
// Simulate time to send message and get status.
ACE_OS::sleep(2);
return next_result_id();
}
};
|
Scheduler.h
Scheduler
#pragma once
#include <ace/Log_Msg.h>
#include <ace/Auto_Ptr.h>
#include <ace/Task.h>
#include <ace/Method_Request.h>
#include <ace/Activation_Queue.h>
class Scheduler : public ACE_Task_Base
{
private:
ACE_Activation_Queue activation_queue_;//Activation Queue(激活队列)
public:
Scheduler()
{
ACE_TRACE(ACE_TEXT("Scheduler::Scheduler"));
this->activate();
}
virtual int svc(void)
{
ACE_TRACE(ACE_TEXT("Scheduler::svc"));
while (1)
{
// Dequeue the next method object
auto_ptr<ACE_Method_Request> request(this->activation_queue_.dequeue());
// Invoke the method request.
if(request->call() == -1)
break;
}
return 0;
}
int enqueue(ACE_Method_Request *request)
{
ACE_TRACE(ACE_TEXT("Scheduler::enqueue"));
return this->activation_queue_.enqueue(request);
}
};
|
5.程序的运行结果
1308==>主线程
2784==》
Scheduler线程
参考:http://hi.baidu.com/pass86/blog/item/ccbbff24cc3060034d088d5c.html
阅读(2633) | 评论(0) | 转发(0) |