ACE 中的Active Object模式

 Active Object 设计模式:

       1) 根据对象被调用的方式,可以将对象分为两类:

        Passive Object和Active Object。Passive 和 Object和调用者在同一个线程中,这就是我们通常所用的函数调用。而Active Object和调用在不同的线程中,它有自己的控制线程。Active Object设计模式是一种应用于并发编程的设计模式,它通过解耦对象的访问和对象的执行来增加并发性,从而简化对象的同步访问。

        将方法的调用和方法的执行解耦。方法的调用在客户线程中,而方法的执行在另一个独立的线程中。另外,通过良性设计,使得客户端看起来就像是调用一个普通的方法。具体来说:我们用一个Proxy来描述Active Object的接口,由一个Servant来提供Active Object的实现。Proxy和Servant运行在两个不同的线程中,这样方法的调用和方法的执行就可以并发地运行了。其中Proxy运行在客户线程中,而Servant运行在另一个线程中。在运行期,Proxy将客户端的方法调用转化为方法请求,它们通过一个调度器保存在一个请求链表中,调度器运行在Servant线程中,它将方法请求从链表中取出,交由Servant执行。客户还可以获得运行结果。由于方法的调用和运行在不同的线程中,所以运行结果并不是立即返回的。客户只能通过阻塞等待或者循环查询的方式来获得运行结果,这个结果我们用Future来表示。

       2) 在Active Object设计模式中,有6个关键的参与者:

        Proxy:提供一个接口,客户通过该接口调用Active Object的方法。通过Proxy应用程序可以使用强类型的编程语言,而不是线程间松散的消息。Proxy位于客户线程中。

        方法请求(Method Request):方法请求类定义用于执行Active Object方法的接口。客户每次调用Proxy定义的方法,就会构造一个方法请求对象。一个方法请求包含了方法参数等上下文信息,这些上下文信息用于方法的执行和执行结果的返回。

        请求链表:Proxy将具体的方法请求对象插入到请求链表中。请求链表既用于保存方法请求,又用于判断方法请求的可执行性。请求链表将Proxy线程和Servant线程解耦,使得它们可以并发地运行。

        调度器(Scheduler):调度器运行于Active Object线程,用于调度方法请求。调度器使用请求链表来管理方法请求,调度的策略可以根据应用程序的实际需要进行选择。

        工作者(Servant):定义Active Object的行为和状态。工作者实现的方法需要与Proxy 接口、方法请求一致。当方法请求被调度器调度时,工作者的方法才会得到执行,因此,它总是运行在调度器线程中。

        结果(Future):客户通过Proxy调用一个方法,就可以接收到Future。Future使得客户可以获得方法调用的执行结果。由于客户的请求和方法的执行在不同的线程中,所以Future只能通过阻塞等待或者循环查询的方式获取。

       

#include "ace/Log_Msg.h"
#include "ace/OS.h"
#include "ace/Task.h"
#include "ace/Method_Request.h"
#include "ace/Future.h"
#include "ace/Activation_Queue.h"
#include <memory.h>
using namespace std;

#pragma comment(lib,"ace.lib")

// Servant 类对status_result_ 进行简单的累加工作

class Servant
{
public:
    Servant()
    {
        status_result_ = 1;
    }
    int status_update(void) 
    {
        ACE_DEBUG((LM_DEBUG, ACE_TEXT("Obtaining a status_update in %t ") ACE_TEXT("thread of control\n")));
        ACE_OS::sleep(2);
        return next_result_id();
    }
private:
    int next_result_id(void)
    {
        return status_result_++;  
    };
    int status_result_;
};

class StatusUpdate : public ACE_Method_Request
{
public:
    StatusUpdate(Servant & controller, ACE_Future<int>&returnval)
        : controller_(controller), returnVal_(returnval)
    {
        ACE_DEBUG((LM_DEBUG, "StatusUpdate::StatusUpdate.\n"));
    }
    virtual int call(void)
    {
        ACE_DEBUG((LM_DEBUG, "StatusUpdate::call.\n "));
        this->returnVal_.set(this->controller_.status_update());
        return 0;
    }
    
    private:
    Servant& controller_;
    ACE_Future<int> returnVal_;

};

class ExitMethod : public ACE_Method_Request
{
public:
    virtual int call(void)
    {
        return -1;
    }
};

// 调度器类
class Scheduler : public ACE_Task_Base
{
public:
    Scheduler()
    {
        ACE_DEBUG((LM_DEBUG, "Scheduler::Scheduler.\n"));
        this->activate();
    }

    virtual int svc(void)
    {
        ACE_DEBUG((LM_DEBUG, "Scheduler::svc.\n"));
        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) 
    {
        ACE_DEBUG((LM_DEBUG, "Proxy::status_update.\n"));
        return this->activation_queue_.enqueue(request);
    }
    private:
    ACE_Activation_Queue activation_queue_;
};

        //既然在Active Object设计模式中使用了ACE_Activation_Queue作为消息队列,那么也就没有有必要使用ACE_Task类了,因为ACE_Task使用的消息队列是ACE_Message_Queue。

class Proxy
{
public:
    ACE_Future<int> status_update(void)
    {
        ACE_DEBUG((LM_DEBUG, "Proxy::status_update.\n"));
        ACE_Future<int> result;
        this->scheduler_.enqueue(new StatusUpdate(this->controller_, result));
        return result;
    }
    void exit(void)
    {
         ACE_DEBUG((LM_DEBUG, "Proxy::exit.\n"));
         this->scheduler_.enqueue(new ExitMethod);
    }
    private:
        Scheduler scheduler_;
        Servant controller_;
};

int ACE_TMAIN(int, ACE_TCHAR* [])
{
    Proxy controller;
    ACE_Future<int> results[10];
//客户通过Proxy接口发起累加方法请求
    for (int i = 0; i < 10; i++)
    results[i] = controller.status_update();
    ACE_OS::sleep(5);
//客户获取运行结果
    for (int j = 0; j < 10; j++)
    {
         int result = 0;
         results[j].get(result);
         ACE_DEBUG((LM_DEBUG, "[%D(%t)] result %d\n", result));
    }
    controller.exit();
    ACE_Thread_Manager::instance()->wait();
    return 0;
}  

运行结果如下: 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/397569.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

漏洞挖掘 | 编辑器漏洞之kindeditor

本文由掌控安全学院 - master666 投稿 今天呢给大家复现一个kindeditor<4.1.5上传漏洞。小弟能力有限&#xff0c;还在坚持学习的路上&#xff0c;还请大佬多多指教。自我感觉编辑器漏洞很容易忽视。此文章作为记录本人学习的开始&#xff0c;丰富自己的阅历。我们共同进步…

TLS指纹校验原理和绕过

TLS指纹校验原理和绕过 1.指纹校验案例 当用浏览器访问时能够正常访问&#xff0c;而用代码请求却得不到相应结果 1.1 案例&#xff1a;ascii2d https://ascii2d.net/ 1.2 案例&#xff1a;investing https://cn.investing.com/equities/amazon-com-inc-historical-data 2.T…

【JavaScript】数组操作 遍历、修改、新增、删除等...

目录 一、数组是什么&#xff1f; 二、数组操作 2.1、遍历 2.2、数组求最大值和最小值 2.3、修改 2.4、新增 追加到数组末尾 添加到数组开头 2.5、删除 一、数组是什么&#xff1f; 数组是一种可以按顺序保存数据的数据类型。 二、数组操作 2.1、遍历 let arr [马…

14. UE5 RPG使用曲线表格设置回复血量值

之前的文章中&#xff0c;我使用的都是固定的数值来设置血量回复或者蓝量回复&#xff0c;在这篇文章里面&#xff0c;介绍一下使用曲线表格。通过曲线表格我们可以设置多个数值&#xff0c;然后通过去通过修改索引对应的数值去修改回复的血量或者蓝量。 创建曲线表格 首先创…

【Unity】【VRTK】【VR开发】同时保持高效打包和调试的VRTK项目设置方式

【背景】 开发功能时希望能够快速调试&#xff0c;在Preview和开发编辑器间流畅切换。后期又希望快速打包到目标安卓平台&#xff0c;感受头盔内部的画面和操作效果。麻烦在于&#xff0c;这两者往往不是明确区分的&#xff0c;很可能一会儿只是想快速验证一下某些功能动作&am…

安全名词解析-攻防演练

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 攻防演练 01 攻防演练 《网络安全法》中明确提出&#xff0c;“定期组织关键信息基础设施的运营者进行网络安全应急演练&#xff0c;提高应对网络安全事件的水平和协同配合能力。”攻防演练目前已经…

机器视觉【3】非线性求解相机几何参数

线性求解相机几何参数的缺点 上一章节介绍学习了&#xff08;DLT&#xff09;线性求解相机几何参数&#xff0c;了解到线性求解法当中比较明显的缺点&#xff1a; 没有考虑到镜头畸变的影响不能引入更多的约束条件融入到DLT算法当中优化最关键的是&#xff0c;代数距离并不是…

OpenCV中inRange函数

在OpenCV中&#xff0c;inRange函数用于根据颜色范围从图像中提取特定的颜色区域。这个函数检查输入图像中的每个像素&#xff0c;如果像素值位于指定的范围内&#xff0c;则在输出图像&#xff08;或掩码&#xff09;中对应位置的像素被设置为白色&#xff08;或者说是255&…

QT中事件过滤器

Qt添加事件过滤器&#xff0c;设置拖放listWidget、TreeWidget、TableWidget控件。 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this)…

Lightfm学习记录

推荐参考资料 官方文档仓库地址论文地址LightFM推荐系统框架学习笔记LightFM推荐模型库(利于入门)how-i-would-explain-building-lightfm-hybrid-recommenders-to-a-5-year-old(用处不大)协同推荐 lightfm 根据用户已读诗词推荐(可能有用)Recommendation System in Python: L…

Learn HTML in 1 hour

website address https://www.youtube.com/watch?vHD13eq_Pmp8 excerpt All right, what’s going on? everybody. It’s your Bro, hope you’re doing well, and in this video I’m going to help you started with html; so sit back, relax and enjoy the show. If y…

Vue3自定义全局指令批量注册

指令封装代码&#xff1a; import type { App } from "vue";const content {mounted(el : any, binding : any) {console.dir(binding.value);el.remove();} };const operate {mounted(el : any, binding : any) {console.dir(binding.value);el.remove();} };cons…

01_02_mysql06_视图-存储过程-函数

视图 使用 视图一方面可以帮我们使用表的一部分而不是所有的表&#xff0c;另一方面也可以针对不同的用户制定不同的查询视图。比如&#xff0c;针对一个公司的销售人员&#xff0c;我们只想给他看部分数据&#xff0c;而某些特殊的数据&#xff0c;比如采购的价格&#xff0…

助力精准可信时空智能:卫星授时安全隔离装置

随着信息化、数字化、智能化发展浪潮的不断推进&#xff0c;各行业对卫星导航授时信息的精准可信度需求也越来越高。面对有意/无意的导航信号欺骗干扰&#xff0c;一旦发生时间信息错误&#xff0c;将导致巨大的经济损失甚至严重的安全事故。在复杂的电磁环境下&#xff0c;亟需…

【Web前端笔记08】CSS盒子模型

08 CSS盒子模型 1、盒子模型 2、border&#xff08;边框&#xff09; 3、padding&#xff08;内边距&#xff09; 4、margin&#xff08;外边距&#xff09; 5、怪异盒子 6、弹性盒模型练习 08 CSS盒子模型 1、盒子模型 标准盒子&#xff1a; 内容&#xff08;content…

Jenkins配置node节点

1、添加节点 2、配置node主机的java环境 注意&#xff0c;jdk的位置和版本要和master保持一致 sudo apt-get update sudo apt-get install openjdk-8-jre vim /etc/enviroment写入&#xff1a;export JAVA_HOME/usr/lib/jvm/openjdk-8-jre 按wq!退出 再输入&#xff1a;s…

Linux环境变量配置文件--《一图胜千言》

这张图是一个关于Linux系统中shell启动时配置文件加载顺序的流程图。图中分为登录shell和非登录shell两种情况&#xff0c;来描述不同配置文件的读取过程。 登录shell&#xff1a; 当用户登录时&#xff0c;会首先检查是否存在/etc/profile文件&#xff0c;如果存在&#xff0c…

【医学大模型】MEDDM LLM-Executable CGT 结构化医学知识: 将临床指导树结构化,便于LLM理解和应用

MEDDM LLM-Executable CGT 结构化医学知识: 将临床指导树结构化&#xff0c;便于LLM理解和应用 提出背景对比传统医学大模型流程步骤临床指导树流程图识别临床决策支持系统 总结解决方案设计数据收集与处理系统实施临床决策支持 提出背景 论文&#xff1a;https://arxiv.org/p…

大话设计模式——2.简单工厂模式(Simple Factory Pattern)

定义&#xff1a;又称静态工厂方法&#xff0c;可以根据参数的不同返回不同类的实例&#xff0c;专门定义一个类&#xff08;工厂类&#xff09;来负责创建其他类的实例可通过类名直接调用&#xff0c;被创建的实例通常具有共同的父类。 UML图&#xff1a; 例子&#xff1a; 计…

【JVM】双亲委派机制

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;JVM ⛺️稳中求进&#xff0c;晒太阳 双亲委派机制 在Java中如何使用代码的方式去主动加载一个类呢&#xff1f; 方式1&#xff1a;使用Class.forName方法&#xff0c;使用当前类的类加载…