OpenHarmony轻量系统服务管理|消息广播服务及其子功能详解

一、前言

本文相关代码实现位于distributedschedule_samgr_lite\communication\broadcast\source\目录下的broadcast_service.cpub_sub_feature.c。 本文将对以下数据结构及函数进行详解。

    struct BroadcastService:
    struct ConsumerNode:
    struct Relation:
    struct PubSubFeature:
    在broadcast_service.c中
    Init:注册广播服务
    GetName:获取广播服务的名称
    Initialize:广播服务的初始化函数
    MessageHandle:广播服务的消息处理函数
    GetTaskConfig:获取广播服务的任务配置
    在pub_sub_feature.c中
    Init:初始化全局广播变量
    GetName:获取功能名称
    OnInitialize:初始化ID
    OnStop:停止功能
    OnMessage:广播子功能的消息处理函数
    GetRelation:获取子功能与主题的关系
    IsTopicEqual:判断两个主题是否相等

二、数据结构分析

广播服务的数据结构
//广播服务消息类型
enum BroadcastMsgType {
    BROADCAST_MSG,      //消息类型
};
typedef struct BroadcastService BroadcastService;
//广播服务
struct BroadcastService {
    INHERIT_SERVICE;    //继承服务基类
};
//全局广播服务
static BroadcastService g_broadcastService = {
    GetName,
    Initialize,
    MessageHandle,
    GetTaskConfig,
};
广播服务子功能
//消费者结点
typedef struct ConsumerNode {
    UTILS_DL_LIST node;     //双向链表,包含prev和next指针
    Consumer *consumer;     //消费者
} ConsumerNode;
//关系,topic和消费者,一个topic对应多个消费者,消费者存储在双向链表中
typedef struct Relation {
    UTILS_DL_LIST node;     //双向链表,包含prev和next指针
    ConsumerNode callbacks; //消费者结点集合,为一个双向循环链表
    Topic topic;            //消息标识
} Relation;
typedef struct PubSubFeature PubSubFeature;
//一个id对应一个关系双向链表,关系中又包含了一个topic和一个消费者双向链表
//一个PubSubFeature结点可以由identity标识,包含一系列关系组合
//一个relation结点可以由topic标识,包含一组消费者集合
struct PubSubFeature {
    INHERIT_FEATURE;    //继承功能基类
    //函数指针,用于获取指定功能下的topic和消费者的关系
    Relation *(*GetRelation)(PubSubFeature *feature, const Topic *topic);
    MutexId mutex;          //锁
    Relation relations;     //关系,双向循环链表
    Identity identity;      //身份标识,标识服务ID、功能ID和消息队列ID
};

三、函数实现详解

广播服务的函数

注册广播服务
//注册广播服务
static void Init(void)
{
    SAMGR_GetInstance()->RegisterService((Service *)&g_broadcastService);
}
SYS_SERVICE_INIT(Init);
获取服务名称
//获取广播服务的名称
static const char *GetName(Service *service)
{
    (void)service;
    return BROADCAST_SERVICE;
}
初始化广播服务
//广播服务的初始化函数,当前代码版本暂未实现
static BOOL Initialize(Service *service, Identity identity)
{
    (void)identity;
    if (service == NULL) {
        return FALSE;
    }
    return TRUE;
}
广播服务的处理函数
//广播服务的消息处理函数,当前代码版本暂未实现
static BOOL MessageHandle(Service *service, Request *request)
{
    (void)service;
    switch (request->msgId) {
        case BROADCAST_MSG:
            break;
        default:
            break;
    }
    return TRUE;
}
获取广播服务的任务配置
//获取广播服务的任务配置
static TaskConfig GetTaskConfig(Service *service)
{
    (void)service;
    //默认配置
    TaskConfig config = {LEVEL_HIGH, PRI_ABOVE_NORMAL, 0x800, 40, SPECIFIED_TASK};
    return config;
}

广播功能的函数

初始化广播功能
//初始化g_broadcastFeature,并注册feature和feature的接口
static void Init(void)
{
    //获取全局广播服务子功能
    PubSubFeature *feature = &g_broadcastFeature;
    //初始化关系链表的头结点
    feature->relations.topic = -1;
    feature->relations.callbacks.consumer = NULL;
    //初始化关系的双向链表,让prev和next都指向自身
    UtilsListInit(&feature->relations.callbacks.node);
    UtilsListInit(&feature->relations.node);
    //申请锁
    feature->mutex = MUTEX_InitValue();
    //将feature注册到服务BROADCAST_SERVICE中
    SAMGR_GetInstance()->RegisterFeature(BROADCAST_SERVICE, (Feature *)feature);
    //通过feature创建一个PubSubImplement实例
    PubSubImplement *apiEntry = BCE_CreateInstance((Feature *)feature);
    //为feature注册接口
    SAMGR_GetInstance()->RegisterFeatureApi(BROADCAST_SERVICE, PUB_SUB_FEATURE, GET_IUNKNOWN(*apiEntry));
}
SYS_FEATURE_INIT(Init);
获取功能名称
//初始化g_broadcastFeature,并注册feature和feature的接口
static void Init(void)
{
    //获取全局广播服务子功能
    PubSubFeature *feature = &g_broadcastFeature;
    //初始化关系链表的头结点
    feature->relations.topic = -1;
    feature->relations.callbacks.consumer = NULL;
    //初始化关系的双向链表,让prev和next都指向自身
    UtilsListInit(&feature->relations.callbacks.node);
    UtilsListInit(&feature->relations.node);
    //申请锁
    feature->mutex = MUTEX_InitValue();
    //将feature注册到服务BROADCAST_SERVICE中
    SAMGR_GetInstance()->RegisterFeature(BROADCAST_SERVICE, (Feature *)feature);
    //通过feature创建一个PubSubImplement实例
    PubSubImplement *apiEntry = BCE_CreateInstance((Feature *)feature);
    //为feature注册接口
    SAMGR_GetInstance()->RegisterFeatureApi(BROADCAST_SERVICE, PUB_SUB_FEATURE, GET_IUNKNOWN(*apiEntry));
}
SYS_FEATURE_INIT(Init);
初始化身份标识
//为feature配置身份标识
static void OnInitialize(Feature *feature, Service *parent, Identity identity)
{
    (void)parent;
    ((PubSubFeature *)feature)->identity = identity;
}
停止广播功能
//停止指定的功能
static void OnStop(Feature *feature, Identity identity)
{
    (void)feature;
    (void)identity;
}
广播功能的消息处理
/*
    函数功能:广播功能的消息处理函数
    函数参数:@feature:功能对象
             @request:请求消息
    函数返回:处理成功 返回TRUE,处理失败 返回FALSE
    函数描述:根据请求消息的消息类型执行不同的处理逻辑。这里只实现了MSG_PUBLISH类型的消息的处理方法。
*/
static BOOL OnMessage(Feature *feature, Request *request)
{
    //获取广播功能对象
    PubSubFeature *broadcast = (PubSubFeature *)feature;
    switch (request->msgId) {//获取消息ID
        case MSG_PUBLISH: {//消息类型为发布
            //获取消息值,存储的是topic值,使用msgValue一般传输的是小消息,更快和便携。而使用data传输大消息
            Topic topic = request->msgValue;
            //获取广播功能与topic的关系
            Relation *relation = broadcast->GetRelation(broadcast, &topic);
            if (relation == NULL) {
                //无关系,则返回false
                return FALSE;
            }//找到关系
            //加锁
            MUTEX_Lock(broadcast->mutex);
            ConsumerNode *item = NULL;
            /*
                UTILS_DL_LIST_FOR_EACH_ENTRY(item, list, type, member)用于迭代给定类型的双链表
                UTILS_DL_LIST_ENTRY(item, type, member)用于获取指向包含双链表的结构的指针
            */
            //遍历指定关系下的消费者集合的双向链表,遍历topic下的每一个消费者的信息
            UTILS_DL_LIST_FOR_EACH_ENTRY(item, &relation->callbacks.node, ConsumerNode, node) {
                //消费者的身份ID为NULL
                if (item->consumer->identity == NULL) {
                    //消费者处理已发布的topic中的事件或数据
                    item->consumer->Notify(item->consumer, &topic, request);
                }
            }
            MUTEX_Unlock(broadcast->mutex);
        }
            break;
        default:
            break;
    }
    return TRUE;
}
获取广播功能中特定topic的关系
//获取给定的topic在feature中的关系
static Relation *GetRelation(PubSubFeature *feature, const Topic *topic)
{
    //参数检查
    if (feature == NULL || topic == NULL) {
        return NULL;
    }
    //获取指定功能的关系集合头结点,这是一个双向链表
    UTILS_DL_LIST *list = &feature->relations.node;
    Relation *item = NULL;
    MUTEX_Lock(feature->mutex);
    //遍历关系集合的链表,获取每一个关系的信息
    UTILS_DL_LIST_FOR_EACH_ENTRY(item, list, Relation, node) {
        if (IsTopicEqual(&item->topic, topic)) {//判断两个topic的值是否相等
            //topic匹配成功,返回对应的relation
            MUTEX_Unlock(feature->mutex);
            return item;
        }
    }
    MUTEX_Unlock(feature->mutex);
    return NULL;
}
判断topic是否相同
//判断两个topic的值是否相等
static BOOL IsTopicEqual(const Topic *current, const Topic *other)
{
    return *current == *other;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值