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.

374 lines
11 KiB

/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: msg_center.c
: 稿
: radkil
: 2026713
:
: 线
:
1. : 2026713
: 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 ID0
*****************************************************************************/
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 ID0
*****************************************************************************/
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 00
*****************************************************************************/
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
uint32_t uiMsgID ID
const void *pData NULL
uint32_t uiDataLen
:
: int 00
*****************************************************************************/
int MsgCenter_SendTo(const char *pszDstName, uint32_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 10
*****************************************************************************/
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;
}