框架解耦神器 -- REventBus

news/2024/11/24 12:27:26/

REventBus背景

在实际的项目开发中,经常会遇到业务与业务,组件与组件,业务与组件之间的通信,举个例子:当有烟雾传感器检测到烟雾超标时,需要打开排气扇排气,同时显示烟雾浓度显示到显示器中,供管理人员检视。处理这样的逻辑有几种策略。如下:

  1. 排气扇任务和显示器任务,不断的查询烟雾浓度,各自处理检测烟雾浓度是否超标。
  2. 烟雾模块提供注册监听接口,排气扇任务和显示器任务分别注册监听,当浓度超标时,告知监听任务。

以上两种策略都存在很大的问题,问题分析:

  1. 第一种策略,每一个任务都需要不断检查判断,这会导致资源的浪费,而且代码也会有很多重复的。
  2. 第二种策略,虽然解决了第一种策略的的问题,但是如果场景中存在不止一个传感器时,那么所需要注册的监听接口将随之增加。而且监听接口是跟具体的业务绑定的。

综上所述:为了能够解决上面的问题,REventBus组件应运而生。

REventBus工作流程图解

Publisher使用publish发出ige一个事件,Subscriber在其回调函数中接收事件。

REventBus依赖组件

为了提供更好的组件化,推出R组件集,REventbus组件就是R组件集的其中一员,组件与组件之后存在依赖关系.
REventBus组件同样依赖一些组件,如下:

  1. RPlatform组件:平台适配层,为了能让R组件能够在不同RTOS或Linux中运行,针对不同平台做的适配层。链接:https://gitee.com/RiceChen0/rplatform。
  2. RThread_pool组件: 一个跨平台,易移植,接口简单的线程池组件。链接:https://gitee.com/RiceChen0/rthread_pool。

REventBus的使用

  • REventBus整体包含5部分:Subscribe,Publish,Event,EventCb,Broker。
  • Subscribe --订阅者订阅自己需要监听的事件接口。
  • Publish --发布者发布事件,它支持同步发送和异步发送。
  • Event --订阅者监听的事件,只有存在订阅事件,才会有与之对应的发布事件。
  • EventCb --事件产生的回调接口,订阅者注册,发布者发布对应事件之后产生回调。
  • Broker --事件代理,管理事件注册,注销,监听。
REventBus接口说明
接口说明
reb_initREventBus初始化接口
reb_deinitREventBus去初始化接口
reb_subscribeREventBus订阅事件接口
reb_unsbscribeREventBus取消订阅事件接口
reb_publishREventBus同步发布事件接口
reb_async_publishREventBus异步发布事件接口
  • REventBus初始化接口
  1. 使用RThread_pool组件创建一个线程池
  2. 创建互斥量,解决共享资源问题。
  3. 初始化broker链表,用于事件代理。
pf_err_t reb_init(void);
  • REventBus去初始化接口
  1. 线程池注销,互斥量伤处,
pf_err_t reb_deinit(void);
  • REventBus订阅事件接口: pf_err_t reb_subscribe(const char *event, reb_handler_cb handler)
参数描述
event订阅的事件,其是一个字符串类型
handler事件处理函数,由订阅者提供,事件产生时回调此函数
返回——
PF_EOK订阅事件成功
OTher订阅事件失败
  • REventBus订阅事件接口: pf_err_t reb_unsbscribe(const char *event, reb_handler_cb handler)
参数描述
event订阅的事件,其是一个字符串类型
handler事件处理函数,订阅事件时所订阅的回调函数
返回——
PF_EOK取消订阅事件成功
OTher取消订阅事件失败
  • REventBus同步发布事件接口:pf_err_t reb_publish(const char *event, void *payload, uint16_t lenght)
参数描述
event订阅者订阅的事件类型
payload发布事件的消息类型
lenght发布事件的消息长度
返回——
PF_EOK发布事件成功
OTher发布事件失败
  • REventBus异步发布事件接口:pf_err_t reb_async_publish(const char *event, reb_priority priority, void *payload, uint16_t lenght)
参数描述
event订阅者订阅的事件类型
priority发布事件的优先级,REB_PRIORITY_HIGH和REB_PRIORITY_ORDINARY(目前未实现)
payload发布事件的消息类型
lenght发布事件的消息长度
返回——
PF_EOK发布事件成功
OTher发布事件失败

REventBus演示

  1. 订阅事件demo:
  • 注意: 同一个模块定义多次定义同一个事件,只有第一个事件订阅有效
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>#include "revent_bus.h"void reb_handler(const char *event, void *payload, uint16_t lenght)
{rt_kprintf("Recv: event: %s, payload: %.*s\r\n", event, lenght, payload);
}int main(void)
{reb_init();reb_subscribe("event1", reb_handler);reb_subscribe("event1", reb_handler);reb_subscribe("event2", reb_handler);reb_info_dump();
}
  • 效果:
  1. 发布同步事件demo:
  • 注意:发布同步事件,它是按照顺序发布的,只有第一个事件处理完,才会处理第二个事件。
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>#include "revent_bus.h"void reb_handler(const char *event, void *payload, uint16_t lenght)
{rt_kprintf("Recv: event: %s, payload: %.*s\r\n", event, lenght, payload);
}int main(void)
{rt_kprintf("----------------------\r\n");rt_kprintf("-Webcome to youyeetoo-\r\n");rt_kprintf("----------------------\r\n");reb_init();reb_subscribe("event1", reb_handler);reb_subscribe("event1", reb_handler);reb_subscribe("event2", reb_handler);reb_info_dump();while (1){reb_publish("event1", "youyeetoo: event bus", rt_strlen("youyeetoo: event bus"));reb_publish("event2", "Publish sync msg", rt_strlen("Publish sync msg"));rt_thread_delay(1000);}
}
  • 效果:
  1. 发布异步事件demo:
  • 注意:发布异步事件,发布的事件不一定立马执行,他会等待线程池的任务空闲时,才会执行。也就是执行时间不确定。
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>#include "revent_bus.h"void reb_handler(const char *event, void *payload, uint16_t lenght)
{rt_kprintf("Recv: event: %s, payload: %.*s\r\n", event, lenght, payload);
}int main(void)
{rt_kprintf("----------------------\r\n");rt_kprintf("-Webcome to youyeetoo-\r\n");rt_kprintf("----------------------\r\n");reb_init();reb_subscribe("event1", reb_handler);reb_subscribe("event1", reb_handler);reb_subscribe("event2", reb_handler);reb_info_dump();while (1){reb_publish("event1", "youyeetoo: event bus", rt_strlen("youyeetoo: event bus"));reb_publish("event2", "Publish sync msg", rt_strlen("Publish sync msg"));rt_thread_delay(100);reb_async_publish("event1", REB_PRIORITY_ORDINARY, "Good Good", rt_strlen("Good Good"));reb_async_publish("event2", REB_PRIORITY_ORDINARY, "Publish async msg", rt_strlen("Publish async msg"));rt_thread_delay(100);}
}
  • 效果:

REventBus的优缺点

  • 优点:

    1. 简化组件与组件,业务与业务,组件与业务之间的通信方式。
    2. 对通信双方做到完全解耦。
    3. 使用RThread pool灵活切换工作线程,一定程度提供了事件处理效率
    4. 支持同步事件发布,和异步事件发布。
    5. 资源占用极小。
  • 缺点:

    1. 当业务多的时候,需要定义很多事件类型。
    2. 订阅事件的时候,需要遍历事件列表是否已经存在事件;发布的时候,也需要遍历事件列表是否已经存在事件,性能不高。

http://www.ppmy.cn/news/142747.html

相关文章

opencv的Mat相关操作

cv Mat类型的使用 下载安装好opencv&#xff0c;使用时只需添加如下头文件&#xff1a; #include<opencv2/opencv.hpp>另外在工程的属性页中要添加opencv的包含目录与库目录&#xff1a; 在写稍大一些工程的时候&#xff0c;尽量不要直接用using namespace cv; 因为在…

尾行注释转行上注释 正则表达式

尾行注释转行上注释 正则表达式 匹配 ( *)(.;)( *// *)(.) 替换为 $1// $4\n$1$2

space-between时尾行排版优化

在使用justify-content: space-between;时,经常会遇到下列问题, ul {width: 500px;height: 500px;display: flex;justify-content: space-between;flex-wrap: wrap;}li {width: 130px;list-style: none;background-color: pink;height: 30px;margin: 20px 0;}ul:last-child::af…

vi中跳到首行或尾行

跳到首行&#xff1a;gg 跳到尾行&#xff1a;G

git 提交代码防止尾行序列LF转为CRLF

在Windows下默认的尾行序列是CRLF&#xff0c;在使用git提交代码时会将LF转为CRLF 通过一下设置保证在文件提交到版本库的时候文件的尾行序列不发生变化 git config --global core.autocrlf false有关尾行序列设置方式&#xff1a; vscode > 设置 > 搜索 eol&#xf…

115://开头的链接怎么下载?

115://开头的链接怎么下载&#xff1f;想要下载115://开头的链接&#xff0c;需要借助115浏览器。确定安装好115浏览器就按照下面的操作步骤来进行吧。 115://开头的链接下载方法介绍 1、登录115官网&#xff0c;下载115浏览器并安装; 2、在115浏览器地址栏输入&#xff1a;chr…

windbg preview下载及其历史版本下载

WinDBG是专门针对Windows NT系列操作系统而设计的调试器。WinDBG的最初版本是微软公司在开发最初Windows NT操作系统&#xff08;NT3.1&#xff09;期间推出的&#xff0c;它是当时NT团队内部开发和调试NT操作系统的最主要工具。WinDBG与NT系列操作系统有着密不可分的联系。Win…

ONNX安装

前言 以下均用清华镜像源安装&#xff0c;官网太慢。 CPU和GPU版&#xff0c;只能安装一个&#xff0c;建议安装 GPU 版。 安装时一定要注意与CUDA、cuDNN版本适配问题&#xff0c;具体适配列表参考&#xff1a;CUDA Execution Provider 安装 onnx pip install onnx -i http…