鸿蒙源码分析(五十)

pub_sub_feature.c代码分析

该文件主要功能
文件路径

一、背景知识

1.结构体和宏定义

消费节点结构体

typedef struct ConsumerNode {
    
    
    UTILS_DL_LIST node;
    Consumer *consumer;
} ConsumerNode;

关系结构体

typedef struct Relation {
    
    
    UTILS_DL_LIST node;  //节点
    ConsumerNode callbacks;  ///回调的消费节点
    Topic topic; //定义关系主题
} Relation;
typedef struct PubSubFeature PubSubFeature;

PubSub 模式,是 Publish/Subscribe 的缩写,意为“发布/订阅”模式。
在实际使用中,我们应该也会接触到 PubSub 模式,例如 Nodejs 中的 EventEmitter、Backbone 中的事件模型、以及 jQuery 中的事件。 以 EventEmitter 为栗子,它提供了 addListener(event, listener),removeListener(event, listener),emit(event, [arg1], [arg2], […]) 方法。

struct PubSubFeature {
    
    
    INHERIT_FEATURE;  //特征信息
    Relation *(*GetRelation)(PubSubFeature *feature, const Topic *topic);
    MutexId mutex;  //定义一个互斥锁
    Relation relations; //定义一个关系结点
    Identity identity; //一个身份信息 
};

来自.c文件的结构体
将不同函数封装一下

static PubSubFeature g_broadcastFeature = {
    
    
    .GetName = GetName,  //获取名字
    .OnInitialize = OnInitialize,  //初始化变量
    .OnStop = OnStop,  //停止
    .OnMessage = OnMessage,  //消息信息的处理
    .GetRelation = GetRelation,
};

二、代码分析

//初始化函数,一个初始化功能的封装。将一些常用全局变量进行初始化赋值
static void Init(void)
{
    
    
    PubSubFeature *feature = &g_broadcastFeature;
    feature->relations.topic = -1;
    feature->relations.callbacks.consumer = NULL;
    UtilsListInit(&feature->relations.callbacks.node);
    UtilsListInit(&feature->relations.node);
    feature->mutex = MUTEX_InitValue();
    SAMGR_GetInstance()->RegisterFeature(BROADCAST_SERVICE, (Feature *)feature);

    PubSubImplement *apiEntry = BCE_CreateInstance((Feature *)feature);
    SAMGR_GetInstance()->RegisterFeatureApi(BROADCAST_SERVICE, PUB_SUB_FEATURE, GET_IUNKNOWN(*apiEntry));
}

消息写进topic进行比对,遍历链表判断身份值

//处理消息
static BOOL OnMessage(Feature *feature, Request *request)
{
    
    
    PubSubFeature *broadcast = (PubSubFeature *)feature;
    switch (request->msgId) {
    
    
        //对消息的id
        case MSG_PUBLISH: {
    
    //id为1的处理
            Topic topic = request->msgValue;//消息值写进topic
            Relation *relation = broadcast->GetRelation(broadcast, &topic);
            //根据topic和broadcast来获取关系
            if (relation == NULL) {
    
    
                return FALSE;
            }
            MUTEX_Lock(broadcast->mutex);
            ConsumerNode *item = NULL;
            UTILS_DL_LIST_FOR_EACH_ENTRY(item, &relation->callbacks.node, ConsumerNode, node) {
    
    
            //遍历链表,判断身份是否为空
                if (item->consumer->identity == NULL) {
    
    
                    item->consumer->Notify(item->consumer, &topic, request);
                }
            }
            MUTEX_Unlock(broadcast->mutex);
            //遍历结束就释放锁
        }
            break;
        default:
            break;
    }
    return TRUE;
}
//一个获取relation的函数,传入特征和topic就能指定具体一个relation
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是否一致
            MUTEX_Unlock(feature->mutex);
            //释放锁
            return item;
        }
    }
    MUTEX_Unlock(feature->mutex);
    return NULL;
}
//一个bool函数来判断topic是否相等
static BOOL IsTopicEqual(const Topic *current, const Topic *other)
{
    
    
    return *current == *other;
    //判断当前主题和传入的other主题是否一致
}

感谢阅读和点赞

猜你喜欢

转载自blog.csdn.net/m0_46976252/article/details/120144722