You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

373 lines
11 KiB

/******************************************************************************
版权所有 (C), 2018-2099, Radkil
******************************************************************************
文 件 名 : msg_center.c
版 本 号 : 初稿
作 者 : radkil
生成日期 : 2026年7月13日
最近修改 :
功能描述 : 模块间消息分发中心(跨线程通信)
修改历史 :
1.日 期 : 2026年7月13日
作 者 : radkil
修改内容 : 创建文件
******************************************************************************/
#include "msg_center.h"
#include "rd_thread.h"
#include "ringbuffer.h"
/*----------------------------------------------*
* 外部变量说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 外部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 内部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 全局变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 模块级变量 *
*----------------------------------------------*/
// 模块注册表
typedef struct {
MsgModule_t stModule;
rd_ringbuf_t *pstRingBuf; // 消息队列(ringbuffer)
rd_mutex_t stMutex; // 互斥锁(保护ringbuffer)
rd_sem_t stSem; // 信号量(阻塞等待)
} MsgModuleEntry_t;
static MsgModuleEntry_t g_astModules[MSG_CENTER_MAX_MODULES];
static uint32_t g_uiModuleCount = 0;
static uint32_t g_uiNextModuleID = 1; // 从1开始,0表示无效
/*----------------------------------------------*
* 常量定义 *
*----------------------------------------------*/
// ringbuffer大小:每个模块可缓存的消息数量
#define MSG_RING_BUFFER_SIZE (MSG_CENTER_QUEUE_SIZE * sizeof(Msg_t))
/*----------------------------------------------*
* 宏定义 *
*----------------------------------------------*/
// 查找模块索引
#define FIND_MODULE_INDEX(uiModuleID) \
((uiModuleID) > 0 && (uiModuleID) <= g_uiModuleCount ? \
(uiModuleID) - 1 : -1)
/*****************************************************************************
函 数 名 : MsgCenter_Init
功能描述 : 初始化消息中心
输入参数 : 无
输出参数 : 无
返 回 值 : void
*****************************************************************************/
void MsgCenter_Init(void)
{
g_uiModuleCount = 0;
g_uiNextModuleID = 1;
RD_MEMSET(g_astModules, 0, sizeof(g_astModules));
}
/*****************************************************************************
函 数 名 : MsgCenter_Register
功能描述 : 注册模块到消息中心
输入参数 : const char *pszName 模块名称
MsgHandler_t pfHandler 消息处理回调
输出参数 : 无
返 回 值 : uint32_t 模块ID,失败返回0
*****************************************************************************/
uint32_t MsgCenter_Register(const char *pszName, MsgHandler_t pfHandler)
{
if (NULL == pszName || NULL == pfHandler)
{
return 0;
}
if (g_uiModuleCount >= MSG_CENTER_MAX_MODULES)
{
return 0; // 模块数已满
}
// 检查名称是否重复
for (uint32_t i = 0; i < g_uiModuleCount; i++)
{
if (RD_STRCMP(g_astModules[i].stModule.m_szName, pszName) == 0)
{
return 0; // 名称重复
}
}
// 注册模块
uint32_t uiIndex = g_uiModuleCount;
uint32_t uiModuleID = g_uiNextModuleID++;
RD_STRNCPY(g_astModules[uiIndex].stModule.m_szName, pszName, MSG_CENTER_MAX_NAME_LEN - 1);
g_astModules[uiIndex].stModule.m_szName[MSG_CENTER_MAX_NAME_LEN - 1] = '\0';
g_astModules[uiIndex].stModule.m_uiModuleID = uiModuleID;
g_astModules[uiIndex].stModule.m_pfHandler = pfHandler;
// 创建 ringbuffer
g_astModules[uiIndex].pstRingBuf = rd_RingbufferCreate(MSG_RING_BUFFER_SIZE);
if (NULL == g_astModules[uiIndex].pstRingBuf)
{
return 0;
}
// 初始化互斥锁
if (Rd_MutexInit(&g_astModules[uiIndex].stMutex) != RD_SUCCESS)
{
rd_RingbufferDestroy(g_astModules[uiIndex].pstRingBuf);
return 0;
}
// 初始化信号量(初始值为0,表示无消息)
if (Rd_SemInit(&g_astModules[uiIndex].stSem, 0, 0) != RD_SUCCESS)
{
Rd_MutexDestroy(&g_astModules[uiIndex].stMutex);
rd_RingbufferDestroy(g_astModules[uiIndex].pstRingBuf);
return 0;
}
g_uiModuleCount++;
return uiModuleID;
}
/*****************************************************************************
函 数 名 : MsgCenter_FindModule
功能描述 : 通过名称查找模块ID
输入参数 : const char *pszName 模块名称
输出参数 : 无
返 回 值 : uint32_t 模块ID,未找到返回0
*****************************************************************************/
uint32_t MsgCenter_FindModule(const char *pszName)
{
if (NULL == pszName)
{
return 0;
}
for (uint32_t i = 0; i < g_uiModuleCount; i++)
{
if (RD_STRCMP(g_astModules[i].stModule.m_szName, pszName) == 0)
{
return g_astModules[i].stModule.m_uiModuleID;
}
}
return 0;
}
/*****************************************************************************
函 数 名 : MsgCenter_Send
功能描述 : 发送消息(异步,跨线程安全)
输入参数 : const Msg_t *pstMsg 消息指针
输出参数 : 无
返 回 值 : int 0成功,非0失败
*****************************************************************************/
int MsgCenter_Send(const Msg_t *pstMsg)
{
if (NULL == pstMsg)
{
return RD_NULL;
}
int iDstIndex = FIND_MODULE_INDEX(pstMsg->m_uiDstModule);
if (iDstIndex < 0 || NULL == g_astModules[iDstIndex].pstRingBuf)
{
return RD_FAILURE;
}
// 加锁保护ringbuffer
Rd_MutexLock(&g_astModules[iDstIndex].stMutex, __func__, NULL);
// 写入ringbuffer
int iRet = rd_RingbufferPut(g_astModules[iDstIndex].pstRingBuf,
(const char *)pstMsg, sizeof(Msg_t));
Rd_MutexUnlock(&g_astModules[iDstIndex].stMutex, __func__, NULL);
if (iRet > 0)
{
// 发送信号量,通知有新消息
Rd_SemPost(&g_astModules[iDstIndex].stSem, __func__, NULL);
return RD_SUCCESS;
}
return RD_FAILURE; // 队列满
}
/*****************************************************************************
函 数 名 : MsgCenter_SendTo
功能描述 : 发送消息给指定模块(便捷函数)
输入参数 : const char *pszDstName 目标模块名称
MsgID_t uiMsgID 消息ID
const void *pData 数据指针(可为NULL)
uint32_t uiDataLen 数据长度
输出参数 : 无
返 回 值 : int 0成功,非0失败
*****************************************************************************/
int MsgCenter_SendTo(const char *pszDstName, MsgID_t uiMsgID, const void *pData, uint32_t uiDataLen)
{
if (NULL == pszDstName)
{
return RD_NULL;
}
uint32_t uiDstModuleID = MsgCenter_FindModule(pszDstName);
if (0 == uiDstModuleID)
{
return RD_FAILURE;
}
Msg_t stMsg;
RD_MEMSET(&stMsg, 0, sizeof(Msg_t));
stMsg.m_uiDstModule = uiDstModuleID;
stMsg.m_uiMsgID = uiMsgID;
if (NULL != pData && uiDataLen > 0)
{
if (uiDataLen > MSG_CENTER_MAX_DATA_SIZE)
{
uiDataLen = MSG_CENTER_MAX_DATA_SIZE;
}
RD_MEMCPY(stMsg.m_aucData, pData, uiDataLen);
stMsg.m_uiDataLen = uiDataLen;
}
return MsgCenter_Send(&stMsg);
}
/*****************************************************************************
函 数 名 : MsgCenter_ProcessOne
功能描述 : 从ringbuffer读取一条消息
输入参数 : int iIndex 模块索引
Msg_t *pstMsg 输出消息
输出参数 : 无
返 回 值 : int 1成功,0无数据
*****************************************************************************/
static int MsgCenter_ProcessOne(int iIndex, Msg_t *pstMsg)
{
// 加锁保护ringbuffer
Rd_MutexLock(&g_astModules[iIndex].stMutex, __func__, NULL);
int iRet = rd_RingbufferGet(g_astModules[iIndex].pstRingBuf,
(char *)pstMsg, sizeof(Msg_t));
Rd_MutexUnlock(&g_astModules[iIndex].stMutex, __func__, NULL);
return (iRet > 0) ? 1 : 0;
}
/*****************************************************************************
函 数 名 : MsgCenter_Process
功能描述 : 处理当前模块的消息(在模块线程中调用)
输入参数 : uint32_t uiModuleID 模块ID
输出参数 : 无
返 回 值 : int 处理的消息数量
*****************************************************************************/
int MsgCenter_Process(uint32_t uiModuleID)
{
int iIndex = FIND_MODULE_INDEX(uiModuleID);
if (iIndex < 0 || NULL == g_astModules[iIndex].pstRingBuf)
{
return 0;
}
int iCount = 0;
Msg_t stMsg;
// 非阻塞读取所有待处理消息
while (MsgCenter_ProcessOne(iIndex, &stMsg))
{
if (g_astModules[iIndex].stModule.m_pfHandler != NULL)
{
g_astModules[iIndex].stModule.m_pfHandler(&stMsg);
}
iCount++;
}
return iCount;
}
/*****************************************************************************
函 数 名 : MsgCenter_ProcessWait
功能描述 : 处理当前模块的消息(带超时等待)
输入参数 : uint32_t uiModuleID 模块ID
uint32_t uiTimeoutMs 超时时间(毫秒),0表示不等待
输出参数 : 无
返 回 值 : int 处理的消息数量,-1表示超时
*****************************************************************************/
int MsgCenter_ProcessWait(uint32_t uiModuleID, uint32_t uiTimeoutMs)
{
int iIndex = FIND_MODULE_INDEX(uiModuleID);
if (iIndex < 0 || NULL == g_astModules[iIndex].pstRingBuf)
{
return -1;
}
Msg_t stMsg;
// 等待信号量(有新消息到达)
if (uiTimeoutMs > 0)
{
// 带超时等待
Rd_SemWait(&g_astModules[iIndex].stSem, __func__, NULL);
}
else
{
// 非阻塞,直接检查ringbuffer
if (!MsgCenter_ProcessOne(iIndex, &stMsg))
{
return 0;
}
// 处理第一条消息
if (g_astModules[iIndex].stModule.m_pfHandler != NULL)
{
g_astModules[iIndex].stModule.m_pfHandler(&stMsg);
}
// 继续处理剩余消息
int iCount = 1;
while (MsgCenter_ProcessOne(iIndex, &stMsg))
{
if (g_astModules[iIndex].stModule.m_pfHandler != NULL)
{
g_astModules[iIndex].stModule.m_pfHandler(&stMsg);
}
iCount++;
}
return iCount;
}
// 信号量被触发,处理消息
int iCount = 0;
while (MsgCenter_ProcessOne(iIndex, &stMsg))
{
if (g_astModules[iIndex].stModule.m_pfHandler != NULL)
{
g_astModules[iIndex].stModule.m_pfHandler(&stMsg);
}
iCount++;
}
return iCount;
}