AUTOSAR_EXP_ARAComAPI的5章笔记(6)

news2024/9/27 15:25:30

返回目录

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 register
 get 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.coloradmin.cn/o/2137695.html

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

相关文章

如何清除KylinOS桌面操作系统桌面密钥环?

如何清除KylinOS桌面操作系统桌面密钥环&#xff1f; 1、问题现象2、解决 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1、问题现象 打开桌面应用会出现【解锁秘钥环提示】&#xff1a; 2、解决 1、安装seahorse sudo apt-get insta…

【JavaEE】IP协议 应用层协议

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 &#x1f576;️一.IP地址 IP协议&#xff08;Internet Protocol&#xff09;是TCP/IP协议族中最核心的协议之一&#xff0c;它定义了数据包在网络中传输的标准…

Word中插入当前日期与时间

Word中插入当前日期与时间 通过构建基块的方法快速插入当前日期与时间 快捷键操作 快捷键具体功能说明 Alt Shift D 插入当前日期date Alt Shift T 插如当前时间time Ctrl Shift F9 使得域文本变为正常文本 Ctrl F11 锁定域更新域菜单工具会变为黑色 C…

音视频入门基础:AAC专题(5)——FFmpeg源码中,判断某文件是否为AAC裸流文件的实现

一、引言 通过FFmpeg命令&#xff1a; ./ffmpeg -i XXX.aac 可以判断出某个文件是否为AAC裸流文件&#xff1a; 所以FFmpeg是怎样判断出某个文件是否为AAC裸流文件呢&#xff1f;它内部其实是通过adts_aac_probe函数来判断的。从《FFmpeg源码&#xff1a;av_probe_input_for…

Qt/C++ 了解NTFS文件系统,获取首张MFT表数据,解析文件记录头内容找到第一个属性偏移地址

系列文章目录 一、Qt/C 了解NTFS文件系统&#xff0c;了解MFT(Master File Table)主文件表&#xff08;一&#xff09; 二、Qt/C 了解NTFS文件系统&#xff0c;解析盘符引导扇区数据获取MFT(Master File Table)主文件表偏移地址 三、Qt/C 了解NTFS文件系统&#xff0c;获取首张…

还在为企微联系人烦恼?一招解决!企业微信2024年效率升级全攻略

现在信息多得让人眼花&#xff0c;微信里头那些企业微信的联系人是不是让你头疼&#xff1f; 看着满屏的绿色头像&#xff0c;心里想&#xff1a;“我就想和朋友聊聊天&#xff0c;怎么就这么难&#xff1f;”别急&#xff0c;今天教你个办法&#xff0c;轻松搞定这些小烦恼&am…

【无标题】达瓦达瓦

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

胤娲科技:解锁AI奥秘——产品经理的智能进化之旅

当AI不再是遥不可及的科幻 想象一下&#xff0c;你走进一家未来感十足的咖啡厅&#xff0c;无需言语&#xff0c;智能咖啡机就能根据你的偏好调制出一杯完美的拿铁&#xff1b; 打开手机&#xff0c;AI助手不仅提醒你今天有雨&#xff0c;还贴心推荐了最适合雨中漫步的音乐列表…

C语言中的GCC的优化和数组的存放方式、Cache机制、访问局部性

“我们仍需共生命的慷慨与繁华相爱&#xff0c;即使岁月以刻薄和荒芜相欺” 文章目录 前言文章有误敬请斧正 不胜感恩&#xff01;第一题&#xff1a;***什么是gcc&#xff1a;***C 语言中&#xff0c;“gcc -O2”是使用 GCC 编译器时的一个编译选项。第一部分&#xff1a;为什…

利用yolov8模型实现的西红柿成熟程度检测系统包含源码+配置说明(基于YOLOv8的西红柿成熟程度检测系统)

西红柿成熟程度的检测对于农业生产尤为重要&#xff0c;可以提高收获效率和产品质量。本项目利用YOLOv8&#xff08;You Only Look Once v8&#xff09;模型实现了一个高效的西红柿成熟程度检测系统。该系统可以自动识别西红柿的颜色&#xff0c;从而判断其成熟程度。 关键特性…

pycharm从VCS获取项目报错unable to access:Recv failure:Connection was reset

&#xff08;已老实求放过&#xff09; 版本&#xff1a;PyCharm Community Edition 2024.2.1 【解决办法】取消Git的网络代理&#xff0c;在目标路径所在文件夹处右键选择Git Bash Here&#xff0c;输入以下命令&#xff1a; git config --global --unset http.proxy git …

2024最新版零基础学习Modbus通信协议(保姆级教程)

合集 - 上位机开发(2) 1.零基础学习Modbus通信协议09-13 2.RS485与ModbusRTU09-10 收起 大家好&#xff01;我是付工。 2012年开始接触Modbus协议&#xff0c;至今已经有10多年了&#xff0c;从开始的懵懂&#xff0c;到后来的顿悟&#xff0c;再到现在的开悟&#xff0c;…

STM32的寄存器深度解析

目录 一、STM32 寄存器概述 二、寄存器的定义与作用 三、寄存器分类 1.内核寄存器 2.外设寄存器 四、重要寄存器详解 1.GPIO 相关寄存器 2.定时器相关寄存器 3.中断相关寄存器 4.RCC 相关寄存器 五、寄存器操作方法 1.直接操作寄存器 2.使用库函数操作寄存器 六…

4个方法教你图片转PDF怎么弄。

我们有时候会接触了一些重要的图片文件或者资料&#xff0c;想要装换成可编辑的PDF格式&#xff0c;更方便自己管理。这时候就会需要转换的工具&#xff0c;我这里就有&#xff14;款可以完成这种转换的高效工具可以分享给大家。 1、365PDF转换软件 直通车&#xff1a;www.pdf…

软件设计之JavaWeb(3)

软件设计之JavaWeb(3) 此篇应在MySQL之后进行学习: 路线图推荐&#xff1a; 【Java学习路线-极速版】【Java架构师技术图谱】 尚硅谷全新JavaWeb教程&#xff0c;企业主流javaweb技术栈 资料可以去尚硅谷官网免费领取 此章节最好学完JDBC观看 学习内容&#xff1a; 请求转发…

jenkins流水线+k8s部署springcloud微服务架构项目

文章目录 1.k8s安装2.jenkins安装3.k8s重要知识1.简介2.核心概念3.重要命令1.查看集群消息2.命名空间3.资源创建/更新4.资源查看5.描述某个资源的详细信息6.资源编辑7.资源删除8.资源重启9.查看资源日志10.资源标签 4.k8s控制台1.登录2.界面基本操作1.选择命名空间2.查看命名空…

损耗金属件检测系统源码分享

损耗金属件检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer V…

全球和局部精细化:提升大模型推理能力的新方法

人工智能咨询培训老师叶梓 转载标明出处 尽管大模型在数学、科学或编程任务上表现出优异的推理精细化能力&#xff0c;但它们在没有外部反馈的情况下&#xff0c;很难识别何时何地需要精细化。为了解决这一问题&#xff0c;来自Meta的FAIR团队和佐治亚理工学院的研究者们提出了…

智能营销才是营销的未来

智能营销新纪元&#xff1a;大模型如何为运营与产品经理赋能 在数字化浪潮席卷全球的今天&#xff0c;营销行业正经历着一场前所未有的变革。随着人工智能技术的飞速发展&#xff0c;特别是大模型技术的兴起&#xff0c;为产品经理和运营人员提供了前所未有的工具与视野&#…

雷·达利欧(Ray Dalio)的20条《原则》

达利欧在《原则》&#xff08;Principles&#xff09;一书中总结了许多实用的原则。这些原则被广泛认同&#xff0c;并且适用于多种情景。以下是20条核心原则的英语原文以及中文翻译&#xff1a; 1. Embrace reality and deal with it. 翻译: 拥抱现实并应对它。适合场景: 适用…