AUTOSAR_EXP_ARAComAPI的5章笔记(6)

返回目录

5.3.5.5 Event-Driven vs Polling-Based access

ara::com实现完全支持事件驱动轮询的方式来访问新数据。

对于轮询方式,典型的用例是,一个应用程序被周期性地触发在特定的截止时间前进行一些处理。这是调节器/控制算法的典型模式 —— 循环激活由一个实时定时器驱动,以确保最小的抖动。在这样的设置中,在每个激活周期中调用*GetNewSamples(),然后将那些更新的缓存数据用作当前处理迭代的输入。此时,应用程序在调度处理算法时获取最新的数据进行处理就完全足够了。如果ara::com实现在任何有新数据可用的时通知你的应用程序,那将适得其反:这只会意味着对你的应用程序进程进行不必要的上下文切换,因为在你收到通知的时候,你可能并不想处理那些新数据,因为还没到处理它的时候。

然而,也有其他用例。如果你的应用程序没有这样一种周期性的、由截止时间驱动的方法,而是应当在某些事件发生时简单地做出反应,那么设置周期性调用*GetNewSamples()来轮询新事件就有点不合适并且效率低下。在这种情况下,你明确希望ara::com实现通知应用程序,从而对应用程序进程进行异步上下文切换。我们通过以下 API 机制来支持这种方式:

ara::core::Result<void> SetReceiveHandler(ara::com::EventReceiveHandler handler);

这个 API允许你注册一个用户定义的回调函数,当自上次调用 GetNewSamples()以来有新的事件数据可用时,通信管理必须调用这个回调函数。注册的回调函数不需要是可重入的,因为ara::com实现必须序列化注册的回调函数,明确允许从注册的回调函数内部调用GetNewSamples()!

请注意,用户可以随时在事件驱动轮询方法之间切换,因为他也可以使用事件包装类提供的UnsetReceiveHandler()方法撤回用户特定的 “接收处理程序”。

以下简短的代码片段是一个关于在服务消费者如何使用事件的简单示例。在这个示例中,在main函数中创建了一个RadarService类型的Proxy实例,并注册了一个接收处理程序,每当接收到新的BrakeEvent事件时,ara::com实现就会调用这个处理程序。这意味着我们使用了“事件驱动” 方法。

在我们的示例中,我们在接收处理程序中用新接收到的事件更新我们的本地缓存,从而过滤掉所有不满足特定属性的BrakeEvent事件,之后,我们调用一个处理函数,该函数处理我们决定保留的Sample。

 #include "RadarServiceProxy.hpp"#include <memory>#include <deque>using namespace com::mycompany::division::radarservice;using namespace ara::com;/*** our radar proxy - initially the unique ptr is invalid.*/std::unique_ptr<proxy::RadarServiceProxy> myRadarProxy;/*** a storage for BrakeEvent samples in fifo style*/std::deque<SamplePtr<const proxy::events::BrakeEvent::SampleType>> stNActiveSamples;/*** \brief application function, which processes current set of BrakeEvent* samples.* \param samples*/void processLastBrakeEvents(std::deque<SamplePtr<const proxy::events::BrakeEvent::SampleType>>&mples) {// do whatever with those BrakeEvent samples ...}/*** \brief event reception handler for BrakeEvent events, which we registerget informed about new events.*/void handleBrakeEventReception() {/*** we get newly arrived BrakeEvent events into our process space.* For each sample we get passed in, we check for a certain property* "active" and if it fulfills the check, we move it into our Last10-orage.* So this few lines basically implement filtering and a LastN policy.*/myRadarProxy->BrakeEvent.GetNewSamples([](SamplePtr<proxy::events::BrakeEvent::SampleType> samplePtr) {if(samplePtr->active) {lastNActiveSamples.push_back(std::move(samplePtr));if (lastNActiveSamples.size() > 10)lastNActiveSamples.pop_front();}});// ... now process those samples ...processLastBrakeEvents(lastNActiveSamples);}int main(int argc, char** argv) {/* Instance Specifier from model */ara::core::InstanceSpecifier instspec {...}auto handles = proxy::RadarServiceProxy::FindService(instspec);if (!handles.empty()) {/* we have at least one valid handle - we are not very particular* here and take the first one to create our proxy */myRadarProxy = std::make_unique<proxy::RadarServiceProxy>(handles[0]);/* we are interested in receiving the event "BrakeEvent" - so we* subscribe for it. We want to access up to 10 events, since our* sample algo averages over at most 10.*/myRadarProxy->BrakeEvent.Subscribe(10);/* whenever new BrakeEvent events come in, we want be called, so we* register a callback for it!* Note: If the entity we would subscribe to, would be a field* instead of an event, it would be crucial, to register our* reception handler BEFORE subscribing, to avoid race conditions.* After a field subscription, you would get instantly so called* "initial events" and to be sure not to miss them, you should care* for that your reception handler is registered before.*/myRadarProxy->BrakeEvent.SetReceiveHandler( handleBrakeEventReception);}// ... wait for application shutdown trigger by application exec mgmt.}

5.3.5.6 Buffering Strategies

以下图形描绘了一个简单的部署情况,其中有一个服务提供一个事件,两个不同的本地服务消费者(SWC)通过它们各自的Proxy的事件包装类订阅了这个事件。正如在图中看到的,两个Proxy都有一个本地事件缓存,可以通过GetNewSamples()填充的缓存。这幅图还描绘了服务实现将其事件数据发送到一个通信管理缓冲区,这个缓冲区显然在服务实现的进程空间之外 —— 图中假设这个缓冲区由内核拥有,或者为通信的Proxy和Skeleton之间的共享内存,或者由一个单独的特定于绑定实现的 “守护” 进程拥有。

3282cf9dd72a46418742d4d96f2630ca.png

图中假设如下:应用程序被实现为具有独立 / 受保护的内存 / 地址空间的进程。

服务实现(通过Skeleton)发送出的事件数据不能在服务 / 骨架进程的私有地址空间内缓冲:如果是这样的话,代理对事件数据的访问通常会导致切换到服务应用程序进程的上下文。我们希望在服务端通过方法调用处理模式(见 5.4.5 小节)对事件访问完全控制,不应该由服务消费者的通信行为触发。现在让我们大致看一下 “发送事件” 的目标缓冲区可能位于的三个不同位置:

  1. 内核空间:数据被发送到一个不在应用程序进程的内存区域。当绑定实现使用诸如管道套接字这样的进程间通信原语时,通常就是这种情况,写入这样一个原语的数据最终会在内核缓冲区空间中。
  2. 共享内存:数据被发送到一个内存区域,这个区域也可以直接被接收者 / 代理读取。不同方之间的写入 / 读取是专门同步的(使用内存屏障显式互斥锁进行轻量级同步)。
  3. 进程间通信守护进程空间:数据被发送到一个明确的非应用程序进程,这个进程充当进程间通信 / 绑定实现的一种守护进程。请注意,从技术上讲,这种方法可能建立在一个进程间通信原语之上,比如通过内核空间或共享内存进行通信,以便将数据从服务进程传输到守护进程。

这些方法中的每一种在缓冲区空间的灵活性 / 大小、访问速度 / 开销效率以及防止恶意访问 / 写入缓冲区的保护方面可能都有不同的优缺点。因此,在一个汽车开放平台(AP)产品及其使用中考虑不同的约束可能会导致不同的解决方案。

在这个例子中需要强调的是,鼓励 AP 产品供应商使用基于引用的方法来访问事件数据:事件包装类的ara::com API 有意地通过SamplePtr来建模访问,这些指针被传递给回调函数,而不是值!在那些相当典型的 1:N 事件通信场景中,允许在 “本地事件缓存” 中不是事件数据值本身,而是指向包含在中央通信管理缓冲区中的数据的指针 / 引用。然后,通过GetNewSamples()更新本地缓存可以实现为不是值的复制,而是引用的更新。

说实话:这显然是关于缓冲区使用优化可能性的一个粗略图景!正如这里所暗示的(7.1 节),传输到应用程序进程的数据通常必须在应用程序访问之前进行反序列化。由于反序列化必须特定于服务消费者的应用程序的对齐方式,因此,已经反序列化的数据在中央共享可能很棘手。但至少你明白了这一点,即:服务消费者的事件数据访问的API设计为消费者之间的事件数据共享提供了空间。

♦️♦️总结♦️♦️

1. Event - Driven vs Polling - Based access

1.1 轮询方式(Polling - Based access)

  • 典型用例:应用程序周期性被触发,在特定截止时间前处理,常见于调节器 / 控制算法,循环激活由实时定时器驱动以确保最小抖动。在每个激活周期调用*GetNewSamples(),用更新的缓存数据作为当前处理迭代输入,这种情况下,应用程序按调度获取最新数据处理即可,若有新数据就通知应用程序则可能造成不必要的上下文切换。

1.2 事件驱动方式(Event - Driven access)

  • 适用场景:当应用程序不是周期性、截止时间驱动,而是需在某些事件发生时简单做出反应,周期性调用*GetNewSamples()轮询新事件就不合适且效率低下,此时希望ara::com实现通知应用程序进行异步上下文切换。
  • 实现机制
    • 通过ara::core::Result<void> SetReceiveHandler(ara::com::EventReceiveHandler handler) API 注册用户定义的回调函数,当有新事件数据可用时通信管理调用该回调函数,注册的回调函数无需可重入,因为ara::com实现会序列化注册的回调函数,且允许从注册的回调函数内部调用GetNewSamples()
    • 用户可通过事件包装类提供的UnsetReceiveHandler()方法在事件驱动和轮询方法之间切换。
  • 示例代码
    • 创建RadarService类型的Proxy实例,并注册接收处理程序,当接收到新的BrakeEvent事件时ara::com实现调用该处理程序,在接收处理程序中更新本地缓存、过滤不满足特定属性的BrakeEvent事件并调用处理函数处理决定保留的Sample

2. Buffering Strategies

2.1 部署情况

  • 一个服务提供一个事件,两个本地服务消费者(SWC)通过各自Proxy的事件包装类订阅该事件,Proxy有本地事件缓存(通过GetNewSamples()填充),服务实现将事件数据发送到通信管理缓冲区,该缓冲区可能在以下位置:
    • 内核空间:数据发送到不在应用程序进程内存区域,使用进程间通信原语(如管道或套接字)时常见,数据最终在内核缓冲区空间。
    • 共享内存:数据发送到接收者 / 代理可直接读取的内存区域,不同方的写入 / 读取通过内存屏障或显式互斥锁进行轻量级同步。
    • 进程间通信守护进程空间:数据发送到明确的非应用程序进程(充当进程间通信 / 绑定实现的守护进程),从技术上讲可基于进程间通信原语(如通过内核空间或共享内存)将数据从服务进程传输到守护进程。

2.2 设计考虑

  • 鼓励汽车开放平台(AP)产品供应商使用基于引用的方法访问事件数据,事件包装类的ara::com API 通过SamplePtr建模访问(传递指针给回调函数而非值),在典型的 1:N 事件通信场景中,本地事件缓存中是指向中央通信管理缓冲区数据的指针 / 引用,GetNewSamples()更新本地缓存可实现为引用更新。虽然传输到应用程序进程的数据在访问前通常需反序列化且共享已反序列化的数据可能棘手,但 API 设计为消费者之间的事件数据共享提供了空间。

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Visual Studio安装教程

这次我给大家讲一下Visual Studio安装 一、官网下载 官网下载地址&#xff1a;https://visualstudio.microsoft.com/zh-hans/downloads/ 下载下来的是一个.exe文件 双击打开&#xff0c;出现下面的界面 二、安装visual studio &#xff08;一&#xff09;更改安装路径 首先&am…

如何提升RAG检索的准确率及答案的完整性?

RAG&#xff08;检索增强生成&#xff09;&#xff0c;重点在于检索&#xff0c;即通过解析文档&#xff0c;然后使用嵌入模型进行向量化&#xff0c;通过欧式距离、向量积乘、最近临等算法来计算向量的相似度&#xff0c;找到与提问语义相似的上下文。然后通过将上下文提交给大…

【LeetCode】每日一题 2024_9_15 与车相交的点(差分)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 今天的题目曾经的我做过了 . . . 又是复习的一天 题目&#xff1a;与车相交的点 代码与解题思路 func numberOfPoints(nums [][]int) (ans int) { diff : [102]int{}for _, p : range nums {diff[p[0]]d…

基于java网吧管理系统设计与实现

博主介绍&#xff1a;专注于Java .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的可以…

c++基础入门二

C基础入门(二) 一、函数重载 在自然语言中&#xff0c;一句话或者一个词有不同的意思。例如&#xff1a;国乒和别人比赛是“谁也赢不了”&#xff0c;而国足和别人比赛是“谁也赢不了” 函数重载&#xff1a;是函数的一种特殊情况&#xff0c;C允许在同一作用域中声明几个功…

开放系统,面向各类业务需求可提供定制化服务的智慧物流开源了。

智慧物流视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。构建基于Ai技术的…

c++中的二叉搜索树

一概念&#xff1a; 静图展示&#xff1a; 动图展示&#xff1a; ①左子树不为空&#xff0c;则左子树节点值小于根节点值。 ②右子树不为空&#xff0c;则右子树节点值大于根节点值。 ③左右子树均为二叉搜索树。 ④对于它可以插入相等的也可以插入不相等的,这里如果插入的…

JavaSE语法阶段复习知识整理3之封装

文章目录 一、封装1.1 封装的概念1.2 访问限定符1.3封装扩展之包 二、static成员2.1static关键字的引入2.2静态成员变量初始化2.3访问静态成员变量2.4用实际问题加深静态成员变量的理解2.5静态成员变量的总结要点2.6静态成员方法的总结要点 三、代码块3.1普通代码块3.2构造代码…

QXDM 如何更新软件?

如何更新QXDM等高通软件&#xff1f;之前做过这个事情&#xff0c;但过几个月给别人讲的时候就忘记了&#xff0c;特做如下记录。 一. 背景知识&#xff1a; 1. QXDM 依赖于Qualcomm package Managers 3(QPM in short)。 目前的时间是2024年9月15日&#xff0c;但不知从何…

学习笔记JVM篇(一)

1、类加载的过程 加载->验证->准备->解析->初始化->使用->卸载 2、JVM内存组成部分&#xff08;HotSpot&#xff09; 名称作用特点元空间&#xff08;JDK8之前在方法区&#xff09;用于存储类的元数信息&#xff0c;例如名称、方法名、字段等&#xff1b;…

[苍穹外卖]-09Spring Task定时任务

Spring Task spring Task是spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑 只要是需要定时处理的场景都可以使用Spring Task定时任务框架 cron表达式就是一个字符串,可以定义任务触发的时间 构成规则: 分为6或7个域, 由空格隔开,每个域代表一个含义每…

Java 全面指南:从入门到精通

目录 1. 引言 Java 的背景 Java 的起源及历史发展 主要的应用场景 Java 的核心特性 面向对象 跨平台性&#xff08;JVM 的角色&#xff09; 自动内存管理与垃圾回收机制 Java 版本与发展历程 Java SE 8, 11, 17 等主要版本特性 新增功能概述&#xff08;如 Lambda 表…

SpringBoot新技能:零停机更新代码

在个人或者企业服务器上&#xff0c;总归有要更新代码的时候&#xff0c;普通的做法必须先终止原来进程&#xff0c;因为新进程和老进程端口是一个&#xff0c;新进程在启动时候&#xff0c;必定会出现端口占用的情况&#xff0c;但是&#xff0c;还有黑科技可以让两个SpringBo…

【机器学习】--- 深度学习中的注意力机制

深度学习中的注意力机制 在深度学习领域&#xff0c;注意力机制&#xff08;Attention Mechanism&#xff09;已经成为近年来最受瞩目的研究热点之一。它不仅提升了现有模型的性能&#xff0c;更启发了全新的网络结构&#xff0c;如Transformer模型。注意力机制被广泛应用于自…

c语言中的局部跳转以及全局跳转

一、前言 在c语言中&#xff0c;当我们在处理某些异常情况的时候&#xff0c;经常会使用goto语句来进行跳转。goto用起来很方便&#xff0c;但可能很多人都不知道&#xff0c;goto只能在一个函数里面跳转&#xff0c;并不能够跨函数跳转。本文将介绍能够跨函数跳转的接口setjm…

升级VMware

1、vm17pro安装包 VMware Workstation 17 Pro软件下载&#xff1a; 官网下载&#xff1a;Download VMware Workstation Pro 2、点击下一步更改地址 3、注册码 VMware Workstation 17 Pro注册码&#xff1a; 4A4RR-813DK-M81A9-4U35H-06KND 4、打开虚拟机 注&#xff1a; 升…

ip地址数字范围是多少?ip地址四段数字的含义是什么

IP地址&#xff0c;作为互联网上的唯一标识&#xff0c;是由一串数字组成的。这些数字不仅代表了设备的网络位置&#xff0c;还蕴含了丰富的信息。本文将深入探讨IP地址的数字范围以及四段数字的具体含义。 一、IP地址数字范围是多少 IP地址由四段数字组成&#xff0c;每一段数…

JavaEE:文件内容操作(二)

文章目录 文件内容操作读文件(字节流)read介绍read() 使用read(byte[] b) 使用 read(byte[] b, int off, int len) 使用 写文件(字节流)write介绍write(int b) 使用write(byte[] b) 使用write(byte[] b, int off, int len) 使用 读文件(字符流)read() 使用read(char[] cbuf) 使…

基于python+django+vue的鲜花商城系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于pythondjangovueMySQL的线…

如何做系统架构?从动态系统思考的角度

在动态系统思考的背景下&#xff0c;系统架构不再只是一个静态的、结构化的设计&#xff0c;而是一个随着时间推移、基于不同要素互动产生涌现行为的动态过程。系统架构师的任务不仅仅是定义系统的形态和结构&#xff0c;更是通过剖析系统的互动网络、功能涌现和使用场景&#…