REventBus背景
在實(shí)際的項(xiàng)目開發(fā)中,經(jīng)常會(huì)遇到業(yè)務(wù)與業(yè)務(wù),組件與組件,業(yè)務(wù)與組件之間的通信,舉個(gè)例子:當(dāng)有煙霧傳感器檢測(cè)到煙霧超標(biāo)時(shí),需要打開排氣扇排氣,同時(shí)顯示煙霧濃度顯示到顯示器中,供管理人員檢視。處理這樣的邏輯有幾種策略。如下:
排氣扇任務(wù)和顯示器任務(wù),不斷的查詢煙霧濃度,各自處理檢測(cè)煙霧濃度是否超標(biāo)。
煙霧模塊提供注冊(cè)監(jiān)聽接口,排氣扇任務(wù)和顯示器任務(wù)分別注冊(cè)監(jiān)聽,當(dāng)濃度超標(biāo)時(shí),告知監(jiān)聽任務(wù)。
以上兩種策略都存在很大的問題,問題分析:
第一種策略,每一個(gè)任務(wù)都需要不斷檢查判斷,這會(huì)導(dǎo)致資源的浪費(fèi),而且代碼也會(huì)有很多重復(fù)的。
第二種策略,雖然解決了第一種策略的的問題,但是如果場(chǎng)景中存在不止一個(gè)傳感器時(shí),那么所需要注冊(cè)的監(jiān)聽接口將隨之增加。而且監(jiān)聽接口是跟具體的業(yè)務(wù)綁定的。
綜上所述:為了能夠解決上面的問題,REventBus組件應(yīng)運(yùn)而生。開源鏈接:https://gitee.com/RiceChen0/revent_bus
REventBus工作流程圖解
Publisher使用publish發(fā)出ige一個(gè)事件,Subscriber在其回調(diào)函數(shù)中接收事件。
REventBus依賴組件
為了提供更好的組件化,風(fēng)火輪科技 和《Rice嵌入式開發(fā)技術(shù)分享》公眾號(hào)聯(lián)合推出R組件集,REventbus組件就是R組件集的其中一員,組件與組件之后存在依賴關(guān)系.REventBus組件同樣依賴一些組件,如下:
RPlatform組件:平臺(tái)適配層,為了能讓R組件能夠在不同RTOS或Linux中運(yùn)行,針對(duì)不同平臺(tái)做的適配層。鏈接:https://gitee.com/RiceChen0/rplatform。
RThread_pool組件:一個(gè)跨平臺(tái),易移植,接口簡(jiǎn)單的線程池組件。鏈接:https://gitee.com/RiceChen0/rthread_pool。
REventBus的使用
REventBus整體包含5部分:Subscribe,Publish,Event,EventCb,Broker。
Subscribe --訂閱者訂閱自己需要監(jiān)聽的事件接口。
Publish --發(fā)布者發(fā)布事件,它支持同步發(fā)送和異步發(fā)送。
Event --訂閱者監(jiān)聽的事件,只有存在訂閱事件,才會(huì)有與之對(duì)應(yīng)的發(fā)布事件。
EventCb --事件產(chǎn)生的回調(diào)接口,訂閱者注冊(cè),發(fā)布者發(fā)布對(duì)應(yīng)事件之后產(chǎn)生回調(diào)。
Broker --事件代理,管理事件注冊(cè),注銷,監(jiān)聽。
REventBus接口說明
接口 | 說明 |
---|---|
reb_init | REventBus初始化接口 |
reb_deinit | REventBus去初始化接口 |
reb_subscribe | REventBus訂閱事件接口 |
reb_unsbscribe | REventBus取消訂閱事件接口 |
reb_publish | REventBus同步發(fā)布事件接口 |
reb_async_publish | REventBus異步發(fā)布事件接口 |
REventBus初始化接口
使用RThread_pool組件創(chuàng)建一個(gè)線程池
創(chuàng)建互斥量,解決共享資源問題。
初始化broker鏈表,用于事件代理。
pf_err_treb_init(void);
REventBus去初始化接口
線程池注銷,互斥量傷處,
pf_err_treb_deinit(void);
REventBus訂閱事件接口: pf_err_t reb_subscribe(const char *event, reb_handler_cb handler)
參數(shù) | 描述 |
---|---|
event | 訂閱的事件,其是一個(gè)字符串類型 |
handler | 事件處理函數(shù),由訂閱者提供,事件產(chǎn)生時(shí)回調(diào)此函數(shù) |
返回 | —— |
PF_EOK | 訂閱事件成功 |
OTher | 訂閱事件失敗 |
REventBus訂閱事件接口: pf_err_t reb_unsbscribe(const char *event, reb_handler_cb handler)
參數(shù) | 描述 |
---|---|
event | 訂閱的事件,其是一個(gè)字符串類型 |
handler | 事件處理函數(shù),訂閱事件時(shí)所訂閱的回調(diào)函數(shù) |
返回 | —— |
PF_EOK | 取消訂閱事件成功 |
OTher | 取消訂閱事件失敗 |
REventBus同步發(fā)布事件接口:pf_err_t reb_publish(const char *event, void *payload, uint16_t lenght)
參數(shù) | 描述 |
---|---|
event | 訂閱者訂閱的事件類型 |
payload | 發(fā)布事件的消息類型 |
lenght | 發(fā)布事件的消息長(zhǎng)度 |
返回 | —— |
PF_EOK | 發(fā)布事件成功 |
OTher | 發(fā)布事件失敗 |
REventBus異步發(fā)布事件接口:pf_err_t reb_async_publish(const char *event, reb_priority priority, void *payload, uint16_t lenght)
參數(shù) | 描述 |
---|---|
event | 訂閱者訂閱的事件類型 |
priority | 發(fā)布事件的優(yōu)先級(jí),REB_PRIORITY_HIGH和REB_PRIORITY_ORDINARY(目前未實(shí)現(xiàn)) |
payload | 發(fā)布事件的消息類型 |
lenght | 發(fā)布事件的消息長(zhǎng)度 |
返回 | —— |
PF_EOK | 發(fā)布事件成功 |
OTher | 發(fā)布事件失敗 |
REventBus演示
訂閱事件demo:
注意:同一個(gè)模塊定義多次定義同一個(gè)事件,只有第一個(gè)事件訂閱有效
#include#include #include #include"revent_bus.h" voidreb_handler(constchar*event,void*payload,uint16_tlenght) { rt_kprintf("Recv:event:%s,payload:%.*s ",event,lenght,payload); } intmain(void) { reb_init(); reb_subscribe("event1",reb_handler); reb_subscribe("event1",reb_handler); reb_subscribe("event2",reb_handler); reb_info_dump(); }
效果:
發(fā)布同步事件demo:
注意:發(fā)布同步事件,它是按照順序發(fā)布的,只有第一個(gè)事件處理完,才會(huì)處理第二個(gè)事件。
#include#include #include #include"revent_bus.h" voidreb_handler(constchar*event,void*payload,uint16_tlenght) { rt_kprintf("Recv:event:%s,payload:%.*s ",event,lenght,payload); } intmain(void) { rt_kprintf("---------------------- "); rt_kprintf("-Webcometoyouyeetoo- "); rt_kprintf("---------------------- "); 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:eventbus",rt_strlen("youyeetoo:eventbus")); reb_publish("event2","Publishsyncmsg",rt_strlen("Publishsyncmsg")); rt_thread_delay(1000); } }
效果:
發(fā)布異步事件demo:
注意:發(fā)布異步事件,發(fā)布的事件不一定立馬執(zhí)行,他會(huì)等待線程池的任務(wù)空閑時(shí),才會(huì)執(zhí)行。也就是執(zhí)行時(shí)間不確定。
#include#include #include #include"revent_bus.h" voidreb_handler(constchar*event,void*payload,uint16_tlenght) { rt_kprintf("Recv:event:%s,payload:%.*s ",event,lenght,payload); } intmain(void) { rt_kprintf("---------------------- "); rt_kprintf("-Webcometoyouyeetoo- "); rt_kprintf("---------------------- "); 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:eventbus",rt_strlen("youyeetoo:eventbus")); reb_publish("event2","Publishsyncmsg",rt_strlen("Publishsyncmsg")); rt_thread_delay(100); reb_async_publish("event1",REB_PRIORITY_ORDINARY,"GoodGood",rt_strlen("GoodGood")); reb_async_publish("event2",REB_PRIORITY_ORDINARY,"Publishasyncmsg",rt_strlen("Publishasyncmsg")); rt_thread_delay(100); } }
效果:
REventBus的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
簡(jiǎn)化組件與組件,業(yè)務(wù)與業(yè)務(wù),組件與業(yè)務(wù)之間的通信方式。
對(duì)通信雙方做到完全解耦。
使用RThread pool靈活切換工作線程,一定程度提供了事件處理效率
支持同步事件發(fā)布,和異步事件發(fā)布。
資源占用極小。
缺點(diǎn):
當(dāng)業(yè)務(wù)多的時(shí)候,需要定義很多事件類型。
訂閱事件的時(shí)候,需要遍歷事件列表是否已經(jīng)存在事件;發(fā)布的時(shí)候,也需要遍歷事件列表是否已經(jīng)存在事件,性能不高。
-
顯示器
+關(guān)注
關(guān)注
21文章
5015瀏覽量
140453 -
接口
+關(guān)注
關(guān)注
33文章
8712瀏覽量
151995 -
開源
+關(guān)注
關(guān)注
3文章
3412瀏覽量
42732
原文標(biāo)題:框架解耦神器 -- REventBus
文章出處:【微信號(hào):風(fēng)火輪技術(shù)團(tuán)隊(duì),微信公眾號(hào):風(fēng)火輪技術(shù)團(tuán)隊(duì)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
電氣CAD文件中高效的工作流程
幫忙分析下這個(gè)設(shè)計(jì)的工作流程
Simulink是什么?Simulink的工作流程是怎樣進(jìn)行的?
測(cè)試工程師工作流程有哪些
工作流程圖怎么用?有哪些繪制工作流程圖的軟件
NX CAD軟件:數(shù)字化工作流程解決方案(CAD工作流程)
![NX CAD軟件:數(shù)字化<b class='flag-5'>工作流程</b>解決方案(CAD<b class='flag-5'>工作流程</b>)](https://file1.elecfans.com/web2/M00/05/C8/wKgZomberEOAN841AAAsGK6TY38525.png)
評(píng)論