增加了大量注释

This commit is contained in:
NeoZng
2023-01-01 17:32:22 +08:00
parent c2f8b5c8c3
commit c05513587c
56 changed files with 773 additions and 598 deletions

View File

@@ -8,7 +8,7 @@ static char sname[MAX_EVENT_COUNT][MAX_EVENT_NAME_LEN + 1];
static void *p_ptr[MAX_EVENT_COUNT] = {NULL};
static void **s_pptr[MAX_EVENT_COUNT] = {NULL}; // 因为要修改指针,所以需要二重指针
/* ----------------------------------第三方指针传递版的实现----------------------------------- */
/* ----------------------------------第三方指针传递版的实现,deprecated----------------------------------- */
void MessageInit()
{
@@ -68,11 +68,12 @@ void SubscribeEvent(char *name, void **data_ptr)
/* ----------------------------------链表-队列版的实现----------------------------------- */
/* message_center是fake node,是方便链表编写的技巧,这样不需要处理链表头的特殊情况 */
/* message_center是fake head node,是方便链表编写的技巧,这样不需要处理链表头的特殊情况 */
static Publisher_t message_center = {
.event_name = "Message_Manager",
.first_subs = NULL,
.next_event_node = NULL};
.next_event_node = NULL
};
static void CheckName(char *name)
{
@@ -88,7 +89,7 @@ static void CheckLen(uint8_t len1, uint8_t len2)
if (len1 != len2)
{
while (1)
; // 相同事件的消息长度不同
; // 进入这里说明相同事件的消息长度不同
}
}
@@ -111,14 +112,14 @@ Subscriber_t *SubRegister(char *name, uint8_t data_len)
{ // 给消息队列的每一个元素分配空间,queue里保存的实际上是数据执指针,这样可以兼容不同的数据长度
ret->queue[i] = malloc(sizeof(data_len));
}
//如果之前没有订阅者,特殊处理一下
//如果是第一个订阅者,特殊处理一下
if(node->first_subs==NULL)
{
node->first_subs=ret;
return ret;
}
// 遍历订阅者链表,直到到达尾部
Subscriber_t *sub = node->first_subs; // iterator
Subscriber_t *sub = node->first_subs; // 作为iterator
while (sub->next_subs_queue) // 遍历订阅了该事件的订阅者链表
{
sub = sub->next_subs_queue; // 移动到下一个订阅者,遇到空指针停下,说明到了链表尾部
@@ -182,11 +183,14 @@ uint8_t SubGetMessage(Subscriber_t *sub, void *data_ptr)
uint8_t PubPushMessage(Publisher_t *pub, void *data_ptr)
{
Subscriber_t *iter = pub->first_subs; // iter作为订阅者指针,遍历订阅该事件的所有订阅者;如果为空说明遍历结束
while (iter) // 遍历订阅了当前事件的所有订阅者,依次填入最新消息
static Subscriber_t *iter;
iter = pub->first_subs; // iter作为订阅者指针,遍历订阅事件的所有订阅者;如果为空说明遍历结束
// 遍历订阅了当前事件的所有订阅者,依次填入最新消息
while (iter)
{
if (iter->temp_size == QUEUE_SIZE) // 如果队列已满,则需要删除最老的数据(头部),再填入
{ // 队列头索引前移动,相当于抛弃前一个位置,被抛弃的位置稍后会被写入新的数据
{
// 队列头索引前移动,相当于抛弃前一个位置的数据,被抛弃的位置稍后会被写入新的数据
iter->front_idx = (iter->front_idx + 1) % QUEUE_SIZE;
iter->temp_size--; // 相当于出队,size-1
}

View File

@@ -5,9 +5,9 @@
* @todo 实现基于链表-队列的pubsub机制
* @version 0.1
* @date 2022-11-30
*
*
* @copyright Copyright (c) 2022
*
*
*/
#ifndef PUBSUB_H
@@ -15,102 +15,93 @@
#include "stdint.h"
#define MAX_EVENT_NAME_LEN 32 //最大的事件名长度,每个事件都有字符串来命名
#define MAX_EVENT_COUNT 12 //最多支持的事件数量
#define MAX_EVENT_NAME_LEN 32 // 最大的事件名长度,每个事件都有字符串来命名
#define MAX_EVENT_COUNT 12 // 最多支持的事件数量
#define QUEUE_SIZE 1
/**
* @brief 在所有应用初始化结束之后调用,当作app的"回调函数"
*
*
*/
void MessageInit();
/**
* @brief 注册成为消息发布者
*
*
* @param name 消息标识名,注意不要超过MAX_EVENT_NAME_LEN
* @param data 发布者的数据地址
*/
void PublisherRegister(char* name,void* data);
void PublisherRegister(char *name, void *data);
/**
* @brief 订阅消息,成为消息订阅者
*
*
* @param name 消息标识名
* @param data 保存数据的指针的地址,注意这是一个二级指针,传入的时候对数据指针取地址(&)
*/
void SubscribeEvent(char* name,void** data);
void SubscribeEvent(char *name, void **data);
#endif // !PUBSUB_H
/* 以下是队列版的pubsub,TODO */
typedef struct mqt
{
/* 用数组模拟FIFO队列 */
void* queue[QUEUE_SIZE];
void *queue[QUEUE_SIZE];
uint8_t data_len;
uint8_t front_idx;
uint8_t back_idx;
uint8_t temp_size; // 当前队列长度
/* 指向下一个订阅了相同的事件的订阅者的指针 */
struct mqt* next_subs_queue;
struct mqt *next_subs_queue; // 使得发布者可以通过链表访问所有订阅了相同事件的订阅者
} Subscriber_t;
/**
* @brief 发布者类型.每个发布者拥有发布者实例,这个实例
*
* @brief 发布者类型.每个发布者拥有发布者实例,并且可以通过链表访问所有订阅了自己发布的事件的订阅者
*
*/
typedef struct ent
{
typedef struct ent
{
/* 事件名称 */
char event_name[MAX_EVENT_NAME_LEN+2];
uint8_t data_len;
char event_name[MAX_EVENT_NAME_LEN + 1]; // 1个字节用于存放字符串结束符 '\0'
uint8_t data_len; // 该事件的数据长度
/* 指向第一个订阅了该事件的订阅者,通过链表访问所有订阅者 */
Subscriber_t* first_subs;
Subscriber_t *first_subs;
/* 指向下一个Publisher的指针 */
struct ent* next_event_node;
struct ent *next_event_node;
} Publisher_t;
/**
* @brief 订阅name的事件消息
*
*
* @param name 事件名称
* @param data_len 消息长度,通过sizeof()获取
* @return Subscriber_t* 返回订阅者实例
*/
Subscriber_t* SubRegister(char* name,uint8_t data_len);
Subscriber_t *SubRegister(char *name, uint8_t data_len);
/**
* @brief 注册成为消息发布者
*
*
* @param name 发布者发布的话题名称(事件)
* @return Publisher_t* 返回发布者实例
*/
Publisher_t* PubRegister(char* name,uint8_t data_len);
Publisher_t *PubRegister(char *name, uint8_t data_len);
/**
* @brief 获取消息
*
*
* @param sub 订阅者实例指针
* @param data_ptr 数据指针,接收的消息将会放到此处
* @return uint8_t 返回值为0说明没有新的消息(消息队列为空),为1说明获取到了新的消息
*/
uint8_t SubGetMessage(Subscriber_t* sub,void* data_ptr);
uint8_t SubGetMessage(Subscriber_t *sub, void *data_ptr);
/**
* @brief 发布者给所有订阅了事件的订阅者推送消息
*
*
* @param pub 发布者实例指针
* @param data_ptr 指向要发布的数据的指针
* @return uint8_t 新消息成功推送给几个订阅者
*/
uint8_t PubPushMessage(Publisher_t* pub,void* data_ptr);
uint8_t PubPushMessage(Publisher_t *pub, void *data_ptr);