往期知识点记录:
- 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
- OpenHarmony轻量系统服务管理|鸿蒙业务模型重要概念详解
- OpenHarmony轻量系统服务管理|同进程及跨进程间通信的数据结构及过程详解
- OpenHarmony轻量系统服务管理|系统服务间调用之对外接口详解
- OpenHarmony轻量系统服务管理|系统服务管理之基础框架及功能详解
- OpenHarmony轻量系统服务管理|系统服务管理之系统功能管理器详解
- OpenHarmony轻量系统服务管理|消息广播服务及其子功能详解
- OpenHarmony轻量系统服务管理|消息广播功能实例操作详解(一)
- OpenHarmony轻量系统服务管理|消息广播功能实例操作详解(二)
- OpenHarmony POSIX和CMSIS接口适配层解读(1):queue_adapter
- OpenHarmony POSIX和CMSIS接口适配层解读adapter(2):thread/memory/time
- OpenHarmony轻量系统服务管理-samgr主要接口思维导图(1)
- OpenHarmony轻量系统服务管理-samgr主要接口思维导图(2)
- OpenHarmony轻量系统服务管理-samgr:common赏析及实现
- OpenHarmony轻量系统服务管理-samgr:iunknown赏析
- OpenHarmony轻量系统服务管理-samgr:iunknown实现分析
- OpenHarmony轻量系统服务管理samgr-message赏析
- OpenHarmony轻量系统服务管理samgr-message实现分析(1)
- OpenHarmony轻量系统服务管理samgr-message实现分析(2)
- 持续更新中……
接着上文继续分析message中的函数实现。
消息资源回收操作
/*
函数功能:释放exchange对象的成员所指向的内存
函数描述:释放exchange对象的成员所指向的内存分为两步,首先处理exchange->sharedRef指向的内存。
若更新引用数后,指向的值不大于0,则释放exchange->sharedRef指向的内存。否则不释放。
其次处理exchange->request.data和exchange->response.data指向的内存。
若更新后的引用数==0,则释放它两指向的内存,否则不释放。
*/
int32 SAMGR_FreeMsg(Exchange *exchange)
{
if (!FreeReference(exchange)) {
//exchange对象引用数不为0,不能释放
return EC_SUCCESS;
}
//exchange对象引用数不大于0
//释放request.data占用的空间
if (exchange->request.len > 0) {
SAMGR_Free(exchange->request.data);
exchange->request.data = NULL;
}
//释放response.data占用的空间
if (exchange->response.len > 0) {
SAMGR_Free(exchange->response.data);
exchange->response.data = NULL;
}
return EC_SUCCESS;
}
消息广播操作
/*
函数功能:向多个服务或特性发送请求以节省内存。用于为Broadcast服务发布主题,以广播消息。
函数参数:@identity:服务或特性ID
@request:请求
@token:引用计数
@handler:处理响应的函数
函数返回:成功返回共享引用计数,失败返回NULL
*/
uint32 *SAMGR_SendSharedRequest(const Identity *identity, const Request *request, uint32 *token, Handler handler)
{
//参数检查
if (identity == NULL || request == NULL) {
return NULL;
}
//初始化exchange对象
Exchange exchange = {*identity, *request, {NULL, 0}, MSG_NON, handler, token};
exchange.type = (handler == NULL) ? MSG_NON : MSG_CON;
exchange.id.queueId = NULL;
//将共享的exchange对象发送到identity->queueId队列中
int32 err = SharedSend(identity->queueId, &exchange, 0);
if (err != EC_SUCCESS) {
//发送失败,更新exchange的引用
HILOG_ERROR(HILOG_MODULE_SAMGR, "SharedSend [%p] failed(%d)!", identity->queueId, err);
(void)FreeReference(&exchange);
}
//返回引用计数
return exchange.sharedRef;
}
消息处理函数
//发送消息类型为MSG_DIRECT的exchange对象,直接调用处理程序来处理请求和响应,而不使用消息处理函数。
int32 SAMGR_SendSharedDirectRequest(const Identity *id, const Request *req, const Response *resp, uint32 **ref,
Handler handler)
{
//参数检查
if (handler == NULL || ref == NULL) {
return EC_INVALID;
}
//初始化
Exchange exchange = {0};
//配置请求和响应消息
if (req != NULL) {
exchange.request = *req;
}
if (resp != NULL) {
exchange.response = *resp;
}
//响应处理函数
exchange.handler = handler;
//引用
exchange.sharedRef = *ref;
//类型为MSG_DIRECT
exchange.type = MSG_DIRECT;
exchange.id = *id;//身份标识
exchange.id.queueId = NULL;
//将exchange对象发送到指定队列中
int32 err = SharedSend(id->queueId, &exchange, 0);
if (err != EC_SUCCESS) {
//错误日志
HILOG_ERROR(HILOG_MODULE_SAMGR, "SharedSend [%p] failed(%d)!", id->queueId, err);
(void)FreeReference(&exchange);
}
*ref = exchange.sharedRef;//更新引用
return err;
}
消息响应函数
//将exchange对象发送到指定Identity所绑定的消息队列
int32 SAMGR_SendResponseByIdentity(const Identity *id, const Request *request, const Response *response)
{
//参数检查
if (request == NULL || id == NULL) {
return EC_INVALID;
}
//获取exchange对象
Exchange *exchange = GET_OBJECT(request, Exchange, request);
if (exchange->type == MSG_NON) {
return EC_INVALID;
}
//指定消息队列
exchange->id.queueId = id->queueId;
//调用SAMGR_SendResponse()发送响应
return SAMGR_SendResponse(request, response);
}
发送消息,本质上是将消息对象放入队列中
//将exchange对象发送到指定消息队列中,并更新引用计数
static int32 SharedSend(MQueueId queueId, Exchange *exchange, int initRef)
{
//如果msg数据和响应是NULL,直接进行入队操作,不需要共享
if ((exchange->request.data == NULL || exchange->request.len <= 0) &&
(exchange->response.data == NULL || exchange->response.len <= 0)) {
return QUEUE_Put(queueId, exchange, 0, DONT_WAIT);//入队,非阻塞
}
//加锁,更新引用计数
MUTEX_GlobalLock();
if (exchange->sharedRef == NULL) {
//分配内存
exchange->sharedRef = (uint32*)SAMGR_Malloc(sizeof(uint32));
if (exchange->sharedRef == NULL) {
//内存分配失败,解锁并返回EC_NOMEMORY
MUTEX_GlobalUnlock();
return EC_NOMEMORY;
}
*(exchange->sharedRef) = initRef;
}
(*(exchange->sharedRef))++;
MUTEX_GlobalUnlock();
return QUEUE_Put(queueId, exchange, 0, DONT_WAIT);//入队,非阻塞
}
释放引用计数操作
/*
函数功能:更新exchange对象的引用数
函数返回:true表示需要释放exchange的资源,false表示不能释放
函数描述:更新exchange对象的引用数,若引用数不大于0,则释放sharedRef指向的内存空间,并指向NULL。然后返回true,表示可以释放exchange对象
若引用数大于0,则返回false,表示不能释放exchange对象,还有其他对象引用它。
*/
static BOOL FreeReference(Exchange *exchange)
{
//参数检查
if (exchange == NULL) {
return FALSE;
}
BOOL needFree = TRUE;
//检查引用数
MUTEX_GlobalLock();
if (exchange->sharedRef != NULL) {
if (*(exchange->sharedRef) > 0) {
//更新引用数,引用减一
(*(exchange->sharedRef))--;
}
if (*(exchange->sharedRef) > 0) {
//若引用数大于0,则当前对象被其他对象引用,不能释放
needFree = FALSE;
}
}
MUTEX_GlobalUnlock();
//如果needFree为TRUE,则释放sharedRef内存
if (needFree) {
SAMGR_Free(exchange->sharedRef);
exchange->sharedRef = NULL;
}
return needFree;
}