ESP 事件循环库解析

ESP 事件循环库解析

事件循环库介绍

事件循环库(Event Loop Library)是一种用于管理事件驱动程序的库或框架。在事件驱动编程模型中,程序的执行流程是由事件的发生和处理来驱动的,而不是简单的按照顺序逐行执行。事件循环库提供了一种机制,使得程序可以异步地处理事件,从而提高程序的性能和响应速度。
官方介绍: Event Loop Library

库头文件

首先查看头文件,主要有三个文件需要关注:esp_event_internal.h、esp_event.h、sys\queue.h
其中esp_event提供函数API,esp_event_internal提供结构体支持,sys\queue提供链表支持。
API部分直接看官方介绍和注释就可以搞懂,主要关注点是esp_event_internal文件。

/// Event loop
typedef struct esp_event_loop_instance {
    const char* name;                                            
    QueueHandle_t queue;                                           
    TaskHandle_t task;                                              
    TaskHandle_t running_task;                               
    SemaphoreHandle_t mutex;                                       
    esp_event_loop_nodes_t loop_nodes;                            
} esp_event_loop_instance_t;

/// Event posted to the event queue
typedef struct esp_event_post_instance {
    esp_event_base_t base;                              
    int32_t id;                                             
    esp_event_post_data_t data;                              
} esp_event_post_instance_t;

这是就是API函数中的loop_handle,只是在函数中为esp_event_loop_handle_t,进行了一次替换。
结构体首先是loop的名称,然后是一个队列头,用于事件发送和接收,传输的数据也很简单,struct esp_event_post_instance一个事件基本集合事件ID,以及用户自定义的数据指针data。接下来是两个TaskHandle_t数据,用于系统调度。还有一个互斥量做保护作用。 重头戏就是这个esp_event_loop_nodes_t变量,它包含许多个链表。

//回调函数 结构体
typedef struct esp_event_handler_context {
    esp_event_handler_t handler;   		//回调函数指针                               
    void* arg;							//回调函数输入参数
} esp_event_handler_instance_context_t;                         
/// Event handler
typedef struct esp_event_handler_node {
    esp_event_handler_instance_context_t* handler_ctx;         
    SLIST_ENTRY(esp_event_handler_node) next;                
} esp_event_handler_node_t;
typedef SLIST_HEAD(esp_event_handler_instances, esp_event_handler_node) esp_event_handler_nodes_t;

typedef struct esp_event_loop_node {
    esp_event_handler_nodes_t handlers;     
    esp_event_base_nodes_t base_nodes;      
    SLIST_ENTRY(esp_event_loop_node) next;  
} esp_event_loop_node_t;

typedef SLIST_HEAD(esp_event_loop_nodes, esp_event_loop_node) esp_event_loop_nodes_t;

首先是**esp_event_handler_nodes_t **表示一个回调函数单向链表,在loop_node中的添加的回调函数表示事件和ID集都是ANY。

// 特定BASE事件和特定ID事件链表
typedef struct esp_event_id_node {
    int32_t id;                                                     
    esp_event_handler_nodes_t handlers;   
    SLIST_ENTRY(esp_event_id_node) next;                    list */
} esp_event_id_node_t;
typedef SLIST_HEAD(esp_event_id_nodes, esp_event_id_node) esp_event_id_nodes_t;
// 特定BASE事件链表,但其ID事件为所有ID集
typedef struct esp_event_base_node {
    esp_event_base_t base;                                           
    esp_event_handler_nodes_t handlers;                             
    esp_event_id_nodes_t id_nodes;                                
    SLIST_ENTRY(esp_event_base_node) next;                 
} esp_event_base_node_t;
typedef SLIST_HEAD(esp_event_base_nodes, esp_event_base_node) esp_event_base_nodes_t;

然后是esp_event_base_nodes_t,和前面的loop_node一样,在每个链表中都有回调函数的链表。base中包含esp_event_id_nodes_t链表和注册事件代码base,符合事件且ID为ANY会执行这里面的回调函数。id_node中包含注册事件ID代码,只要base和id都对应才会执行这里面的回调函数。

库C文件

C文件就只要一个esp_event.c,挑几个重要的介绍一下。

//回调函数执行
static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_node_t *handler, esp_event_post_instance_t post)
//添加回调函数到链表中
static esp_err_t handler_instances_add(esp_event_handler_nodes_t* handlers, esp_event_handler_t event_handler, void* event_handler_arg, esp_event_handler_instance_context_t **handler_ctx, bool legacy)
//移除一个回调函数
static esp_err_t handler_instances_remove(esp_event_handler_nodes_t* handlers, esp_event_handler_instance_context_t* handler_ctx, bool legacy)
//创建事件循环组
esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, esp_event_loop_handle_t* event_loop)
//运行事件循环组,接收队列消息,执行对应回调函数
esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t ticks_to_run)
//删除事件循环组
esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop)
//添加事件到循环组中
esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base,int32_t event_id, esp_event_handler_t event_handler, void* event_handler_arg)
//推送事件到循环组
esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop,esp_event_base_t event_base,int32_t event_id,const void *event_data,size_t event_data_size,TickType_t ticks_to_wait);

总结

ESP事件组使用用链表加队列的形式完成。在创建事件组时会创建指定大小的消息队列,事件组运行函数一直接收消息队列数据,并按照事件和事件ID执行相对应的回调函数。事件组注册回调函数时按照三种不同的事件响应策列,把回调函数添加到不同的回调函数链表中,推送函数会把事件和事件ID发送到事件组的队列中。
数据结构

  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值