在嵌入式開發領域,當需要高效利用有限資源或應對大量異步操作時,采用事件驅動架構能顯著提升系統的性能和可靠性。
本次推薦一個輕量級事件管理庫——lwevt。
lwevt 簡介
基本介紹
//github.com/MaJerle/lwevt
lwevt 是一款專為嵌入式系統打造的輕量級事件管理庫,基于 C 語言開發。它的設計目標是提供高效、簡潔的事件處理機制,幫助開發者快速實現事件驅動的應用程序。
該庫具有良好的跨平臺性,能夠在多種嵌入式操作系統和硬件平臺上穩定運行,為嵌入式設備的事件管理提供了可靠的解決方案。
特性
- 獨立于平臺,沒有特定的架構代碼
- 靈活的應用程序定義的事件類型和相關數據
- 易于使用和維護
- 用戶友好的MIT許可
lwevt 使用
下載源碼:
git clone --recurse-submodules //github.com/MaJerle/lwevt
下面演示lvevt的使用:
#include
#include
#include "lwevt/lwevt.h"
static void prv_evt_fn_1(lwevt_t* e) {
switch ((unsigned)e->type){
case LWEVT_TYPE_MY_EXT_1: {
printf("Event fn 1, LWEVT_TYPE_MY_EXT_1 - with data: a: %d, b: %d\r\n",
(int)e->msg.a.a, (int)e->msg.a.b);
break;
}
default:
break;
}
}
static void prv_evt_fn_2(lwevt_t* e) {
switch ((unsigned)e->type){
case LWEVT_TYPE_MY_EXT_2: {
printf("Event fn 2, LWEVT_TYPE_MY_EXT_2 - with data: a: %d, b: %d\r\n",
(int)e->msg.b.a, (int)e->msg.b.a);
break;
}
default:
break;
}
}
int main(void) {
lwevt_t* evt;
lwevt_t evt_local;
// 初始化事件系統
lwevt_init();
// 注冊兩個用戶事件監聽器
lwevt_register(prv_evt_fn_1);
lwevt_register(prv_evt_fn_2);
evt = lwevt_get_handle(); // 獲取默認事件句柄
evt->msg.a.a = 1;
evt->msg.a.b = 2;
lwevt_dispatch(LWEVT_TYPE_MY_EXT_1); // 分發事件,所有監聽器都會收到
evt_local.msg.b.a = 3;
evt_local.msg.b.b = 4;
lwevt_dispatch_ex(&evt_local, LWEVT_TYPE_MY_EXT_2); // 用本地句柄分發事件
return0;
}
為了優化內存消耗,在LwEVT中將主事件句柄定義為靜態全局變量。它可以通過lwevt_get_handle()函數訪問,并允許使用默認的lwevt_dispatch()函數分發事件。
lwevt_get_handle()和lwevt_dispatch()只有當LWEVT_CFG_ENABLE_DEFAULT_HANDLE(lwevt/src/include/lwevt/lwevt_opt.h)被啟用時才可用。
在多線程環境中,應用程序必須保證get句柄和dispatch調用之間的線程安全。
為了避免使用信號量或互斥鎖,可以定義基于lwevt_t的本地變量,并使用lwevt_dispatch_ex()函數分發事件。
在LwEVT中,事件類型和事件數據的定義采用了X-Macro技術。
在 C 語言中,X-Macro 技術是一種利用預處理宏(Preprocessor Macro)實現代碼復用與一致性維護的編程技巧。它的核心思想是:將一組相關的數據或結構以 “宏列表” 的形式定義,然后通過重新定義宏的展開方式,在不同場景下對這組數據進行不同形式的處理,從而避免重復編寫相似代碼,同時保證數據與相關操作的一致性。
使得事件類型和事件數據可以通過單獨的lwevt_types.h文件來維護,如lwevt_types.h的內容可以根據需要自定義定義事件類型及事件數據:
LWEVT_TYPE_BASIC(LWEVT_TYPE_MY_BASIC_1)
LWEVT_TYPE_BASIC(LWEVT_TYPE_MY_BASIC_2)
LWEVT_TYPE_BASIC(LWEVT_TYPE_MY_BASIC_3)
LWEVT_TYPE_EXT(
LWEVT_TYPE_MY_EXT_1, struct {
int a;
int b;
} a)
LWEVT_TYPE_EXT(
LWEVT_TYPE_MY_EXT_2, struct {
int a;
int b;
} b)
LWEVT_TYPE_EXT(
LWEVT_TYPE_MY_EXT_3, struct {
int a;
int b;
} c)
/* Add more types here ... */
lwevt.h采用了X-Macro技術定義LwEVT的核心接口和數據結構,主要內容如下:
事件類型定義
typedef enum {
#define LWEVT_TYPE_BASIC(name) name,
#define LWEVT_TYPE_EXT(name, data) name,
#include "lwevt/lwevt_type.h"
LWEVT_TYPE_LAST
} lwevt_type_t;
lwevt_type.h:
#ifndef LWEVT_TYPE_BASIC
#define LWEVT_TYPE_BASIC(name)
#endif
#ifndef LWEVT_TYPE_EXT
#define LWEVT_TYPE_EXT(name, data)
#endif
/* Include user types */
#include "lwevt_types.h"
/* Undefine type back - after use */
#undef LWEVT_TYPE_BASIC
#undef LWEVT_TYPE_EXT
事件類型通過宏展開和 lwevt_type.h
文件定義,支持擴展。
事件結構體
typedef struct {
lwevt_type_t type; // 事件類型
union {
#define LWEVT_TYPE_EXT(name, data) data;
#include "lwevt/lwevt_type.h"
const unsigned int dummy;
} msg; // 事件消息體,支持擴展數據
} lwevt_t;
type
字段標識事件類型。msg
聯合體用于存儲擴展事件的數據(通過宏和lwevt_type.h
支持多種事件數據結構)。