mirror of
https://gitee.com/dlmu-cone/bf_original_balance_chassis
synced 2026-07-23 19:25:09 +08:00
完成了队列版本的pubsub机制,但尚未测试
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "message_center.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
|
||||
/* 消息初始化用 */
|
||||
@@ -14,22 +15,27 @@ void MessageInit()
|
||||
for (size_t i = 0; i < MAX_EVENT_COUNT; i++)
|
||||
{
|
||||
if(s_pptr[i]!=NULL)
|
||||
{
|
||||
for (size_t j = 0; j < MAX_EVENT_COUNT; j++) //遍历publisher
|
||||
{
|
||||
if(p_ptr[j]!=NULL) //不为空
|
||||
if(strcmp(&sname[i],pname[j])==0) //比较消息名是否一致
|
||||
{volatile size_t ss=strlen(sname[i]);
|
||||
volatile size_t sss=strlen(pname[j]);
|
||||
{
|
||||
if(strcmp(sname[i],pname[j])==0) //比较消息名是否一致
|
||||
{
|
||||
*s_pptr[i]=p_ptr[j]; // 将sub的指针指向pub的数据
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else //到结尾,退出
|
||||
{
|
||||
while(1); //如果你卡在这里,说明没有找到消息发布者!请确认消息名称是否键入错误
|
||||
}
|
||||
}
|
||||
}
|
||||
else //说明已经遍历完所有的subs
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,4 +58,110 @@ void SubscribeEvent(char* name,void** data_ptr)
|
||||
static uint8_t idx;
|
||||
strcpy(sname[idx],name);
|
||||
s_pptr[idx++]=data_ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* 以下是队列版的pubsub,TODO */
|
||||
|
||||
/* message_center是fake node,方便链表编写的技巧,这样不需要处理链表头的特殊情况 */
|
||||
static Publisher_t message_center={
|
||||
.event_name="Message_Manager",
|
||||
.first_subs=NULL,
|
||||
.next_event_node=NULL
|
||||
};
|
||||
|
||||
Subscriber_t* SubRegister(char* name,uint8_t data_len)
|
||||
{
|
||||
Publisher_t* node=&message_center;
|
||||
while(node->next_event_node) // 遍历链表
|
||||
{
|
||||
node=node->next_event_node;
|
||||
if(strcmp(name,node->event_name)==0) //如果事件名相同就订阅这个事件
|
||||
{
|
||||
Subscriber_t* sub=node->first_subs; //指向第一个事件
|
||||
while (sub->next_subs_queue) //遍历订阅了该事件的链表
|
||||
{
|
||||
sub=sub->next_subs_queue;
|
||||
} //遇到空指针停下,创建新的订阅节点
|
||||
Subscriber_t* ret=(Subscriber_t*)malloc(sizeof(Subscriber_t));
|
||||
memset(ret,0,sizeof(Subscriber_t));
|
||||
ret->data_len=data_len;
|
||||
for (size_t i = 0; i < QUEUE_SIZE; i++)
|
||||
{ //给消息队列分配空间,queue里保存的实际上是数据执指针,这样可以兼容不同的数据长度
|
||||
ret->queue[i]=malloc(sizeof(data_len));
|
||||
}
|
||||
sub->next_subs_queue=ret; //接到尾部,延长该订阅该事件的subs链表
|
||||
return ret;
|
||||
}
|
||||
// 时间名不同,在下一轮循环访问下一个结点
|
||||
}
|
||||
//遍历完,发现尚未注册事件,那么创建一个事件.此时node是publisher链表的最后一个结点
|
||||
node->next_event_node=(Publisher_t*)malloc(sizeof(Publisher_t));
|
||||
strcpy(node->next_event_node->event_name,name);
|
||||
node->next_event_node->next_event_node=NULL; //新publisher的下一个节点置为NULL
|
||||
//创建subscriber作为新事件的第一个订阅者
|
||||
Subscriber_t* ret=(Subscriber_t*)malloc(sizeof(Subscriber_t));
|
||||
memset(ret,0,sizeof(Subscriber_t));
|
||||
ret->data_len=data_len;
|
||||
for (size_t i = 0; i < QUEUE_SIZE; i++)
|
||||
{ //给消息队列分配空间
|
||||
ret->queue[i]=malloc(sizeof(data_len));
|
||||
}
|
||||
node->next_event_node->first_subs=ret;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
Publisher_t* PubRegister(char* name,uint8_t data_len)
|
||||
{
|
||||
Publisher_t* node=&message_center;
|
||||
while(node->next_event_node) //message_center会直接跳过,不需要特殊处理
|
||||
{
|
||||
node=node->next_event_node;
|
||||
if(strcmp(node->event_name,name)==0)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
} //遍历完发现尚未创建name对应的事件
|
||||
node->next_event_node=(Publisher_t*)malloc(sizeof(Publisher_t));
|
||||
memset(node->next_event_node,0,sizeof(Publisher_t));
|
||||
node->next_event_node->data_len=data_len;
|
||||
strcpy(node->next_event_node->event_name,name);
|
||||
return node->next_event_node;
|
||||
}
|
||||
|
||||
/* 如果队列为空,会返回0;成功获取数据,返回1 */
|
||||
uint8_t SubGetMessage(Subscriber_t* sub,void* data_ptr)
|
||||
{
|
||||
if(sub->temp_size==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy(sub->queue[sub->front_idx],data_ptr,sub->data_len);
|
||||
sub->front_idx=(sub->front_idx++)%QUEUE_SIZE;
|
||||
sub->temp_size--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PubPushMessage(Publisher_t* pub,void* data_ptr)
|
||||
{
|
||||
static Subscriber_t* node;
|
||||
node->next_subs_queue=pub->first_subs;
|
||||
while (node->next_subs_queue) //遍历订阅了当前事件的所有订阅者,依次填入最新消息
|
||||
{
|
||||
node=node->next_subs_queue;
|
||||
if(node->temp_size==QUEUE_SIZE) //如果队列已满,则需要删除最老的数据(头部),再填入
|
||||
{ //头索引增加,相当于移动到新一个位置上
|
||||
node->front_idx=(node->front_idx+1)%QUEUE_SIZE;
|
||||
node->temp_size--; //相当于出队,size-1
|
||||
}
|
||||
// 将Pub的数据复制到队列的尾部(最新)
|
||||
memcpy(node->queue[node->back_idx],data_ptr,pub->data_len);
|
||||
node->back_idx=(node->back_idx+1)%QUEUE_SIZE; //队列尾部前移
|
||||
node->temp_size++; //入队,size+1
|
||||
}
|
||||
}
|
||||
@@ -13,12 +13,12 @@
|
||||
#ifndef PUBSUB_H
|
||||
#define PUBSUB_H
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "stdint-gcc.h"
|
||||
|
||||
|
||||
#define MAX_EVENT_NAME_LEN 32 //最大的事件名长度,每个事件都有字符串来命名
|
||||
#define MAX_EVENT_COUNT 12 //最多支持的事件数量
|
||||
#define QUEUE_SIZE 1
|
||||
|
||||
|
||||
/**
|
||||
@@ -47,5 +47,69 @@ void SubscribeEvent(char* name,void** data);
|
||||
|
||||
|
||||
|
||||
|
||||
/* 以下是队列版的pubsub,TODO */
|
||||
|
||||
typedef struct mqt
|
||||
{
|
||||
/* 用数组模拟FIFO队列 */
|
||||
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;
|
||||
} Subscriber_t;
|
||||
|
||||
/**
|
||||
* @brief 发布者类型.每个发布者拥有发布者实例,这个实例
|
||||
*
|
||||
*/
|
||||
typedef struct ent
|
||||
{
|
||||
/* 事件名称 */
|
||||
char event_name[MAX_EVENT_NAME_LEN];
|
||||
uint8_t data_len;
|
||||
/* 指向第一个订阅了该事件的订阅者,通过链表访问所有订阅者 */
|
||||
Subscriber_t* first_subs;
|
||||
/* 指向下一个Publisher的指针 */
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief 注册成为消息发布者
|
||||
*
|
||||
* @param name 发布者发布的话题名称(事件)
|
||||
* @return Publisher_t* 返回发布者实例
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief 发布者给所有订阅了事件的订阅者推送消息
|
||||
*
|
||||
* @param pub 发布者实例指针
|
||||
* @param data_ptr 指向要发布的数据的指针
|
||||
*/
|
||||
void PubPushMessage(Publisher_t* pub,void* data_ptr);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user