Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1496400
  • 博文数量: 218
  • 博客积分: 6394
  • 博客等级: 准将
  • 技术积分: 2563
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-08 15:33
个人简介

持之以恒

文章分类

全部博文(218)

文章存档

2013年(8)

2012年(2)

2011年(21)

2010年(55)

2009年(116)

2008年(16)

分类: 网络与安全

2010-01-11 13:08:19

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) |
给主人留下些什么吧!~~