软总线源码分析5: 组网状态机

本文深入解析HarmonyOS软总线的组网状态机,涵盖状态启动、迁移、消息处理等机制。通过状态机管理组网过程中的认证、设备信息同步、在线、离线和退网状态,确保服务进程性能不受阻塞。
摘要由CSDN通过智能技术生成

组网过程首先需要经过设备认证,认证成功后又要交换设备状态信息,成功后设备间才算组完成工。为了管理组网过程中状态的迁移过程和对应处理,组网模块使用状态机来完成整体的业务逻辑。

一.状态机机制

状态机由函数LnnFsmInit完成初始化,其源码如下:

int32_t LnnFsmInit(FsmStateMachine *fsm, char *name, FsmDinitCallback cb)
{
    if (fsm == NULL || name == NULL) {
        return SOFTBUS_INVALID_PARAM;
    }

    (void)memset_s(fsm, sizeof(*fsm), 0, sizeof(*fsm));
    ListInit(&fsm->stateList);
    fsm->looper = GetLooper(LOOP_TYPE_DEFAULT);
    if (fsm->looper == NULL) {
        LOG_ERR("get looper fail");
        return SOFTBUS_ERR;
    }
    fsm->handler.name = name;
    fsm->handler.HandleMessage = FsmStateMsgHandler;
    fsm->handler.looper = fsm->looper;
    fsm->deinitCallback = cb;
    return SOFTBUS_OK;
}

我们可以看到,状态机的结构体为FsmStateMachine,其内部有一个指向Default Looper的指针和对应的handler,为什么状态机要维护Looper和handler呢?

我们可以看一下另外两个接口:1.CreateFsmHandleMsg生成一条提交给状态机的消息;2.PostMessageToFsm将消息提交给状态机。

CreateFsmHandleMsg的源码如下:

static SoftBusMessage *CreateFsmHandleMsg(FsmStateMachine *fsm,
    int32_t what, uint64_t arg1, uint64_t arg2, void *obj)
{
    SoftBusMessage *msg = NULL;
    FsmCtrlMsgObj *ctrlMsgObj = NULL;

    msg = SoftBusCalloc(sizeof(*msg));
    if (msg == NULL) {
        return NULL;
    }
    msg->what = what;
    msg->arg1 = arg1;
    msg->arg2 = arg2;
    msg->handler = &fsm->handler;
    msg->FreeMessage = FreeFsmHandleMsg;

    ctrlMsgObj = SoftBusMalloc(sizeof(*ctrlMsgObj));
    if (ctrlMsgObj == NULL) {
        SoftBusFree(msg);
        return NULL;
    }
    ctrlMsgObj->fsm = fsm;
    ctrlMsgObj->obj = obj;
    msg->obj = ctrlMsgObj;
    return msg;
}

CreateFsmHandleMsg生成一条消息,其结构体为SoftBusMessage,其handler即为状态机维护的handler,关键的HandleMessage函数指针指向的函数为FsmStateMsgHandler。

PostMessageToFsm的源码如下:

static int32_t PostMessageToFsm(FsmStateMachine *fsm, int32_t what, uint64_t arg1, uint64_t arg2, void *obj)
{
    SoftBusMessage *msg = NULL;

    msg = CreateFsmHandleMsg(fsm, what, arg1, arg2, obj);
    if (msg == NULL) {
        LOG_ERR("create fsm handle msg fail");
        return SOFTBUS_ERR;
    }
    fsm->looper->PostMessage(fsm->looper, msg);
    return SOFTBUS_OK;
}

即调用looper的PostMessage方法,将消息提交给状态机的Looper。

关于Looper的机制,我们在前面的章节介绍过,每当有消息提交到Looper内部的消息队列后,LoopTask函数会根据当前的时间和消息中的时间戳,来判断是否处理该消息。如果消息中的时间戳早于或等于当前时间的话,则调用消息中的HandleMessage函数指针处理该消息。

如前面所说,我们状态机的HandleMessage函数指针指向的函数为FsmStateMsgHandler,其源码如下所示:

static void FsmStateMsgHandler(SoftBusMessage *msg)
{
    if (msg == NULL) {
        return;
    }

    if (msg->what != FSM_CTRL_MSG_DATA) {
        LOG_INFO("process fsm ctrl msg: %d", msg->what);
    }
    switch (msg->what) {
        case FSM_CTRL_MSG_START:
            ProcessStartMessage(msg);
            break;
        case FSM_CTRL_MSG_CHANGE_STATE:
            ProcessChangeStateMessage(msg);
            break;
        case FSM_CTRL_MSG_DATA:
            ProcessDataMessage(msg);
            break;
        case FSM_CTRL_MSG_STOP:
            ProcessStopMessage(msg);
            break;
        case FSM_CTRL_MSG_DEINIT:
            ProcessDeinitMessage(msg);
            break;
        default:
            break;
    }
}

即根据消息中的what字段,选择相应的处理。主要分为五种类型:状态启动,状态迁移,消息处理,消息停止,卸载:

下面依次介绍这几种类型对应的函数处理:

1.状态启动

状态启动的函数为ProcessStartMessage,其源码如下:

static void ProcessStartMessage(SoftBusMessage *msg)
{
    FsmCtrlMsgObj *ctrlMsgObj = msg->obj;
    FsmStateMachine *fsm = NULL;
    FsmState *state = NULL;

    if (ctrlMsgObj == NULL) {
        return;
    }
    fsm = ctrlMsgObj->fsm;
    state = (FsmState *)ctrlMsgObj->obj;
    if (fsm == NULL || state == NULL) {
        return;
    }
    if (fsm->curState != NULL || (fsm->flag & FSM_FLAG_RUNNING) != 0) {
        LOG_ERR("unexpected state");
        return;
    }
    if (IsDuplicateSt
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值