操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    狀態機模式是一種行為模式,在 《設計模式》 這本書中對其有詳細的描述,通過多態實現不同狀態的調轉行為的確是一種很好的方法,只可惜在嵌入式環境下,有時只能寫純C代碼狀態機模式 c語言,并且還需要考慮代碼的重入和多任務請求跳轉等情形,因此實現起來著實需要一番考慮。

    近日在看了一個開源系統時,看到了一個狀態機的實現,也學著寫了一個,與大家分享。

    首先,分析一下一個普通的狀態機究竟要實現哪些內容。

    狀態機存儲從開始時刻到現在的變化,并根據當前輸入,決定下一個狀態。這意味著,狀態機要存儲狀態、獲得輸入(我們把它叫做跳轉條件)、做出響應。

    如上圖所示,{BSM, NOS, RSS}均為狀態,箭頭/表示在BSM狀態、輸入為時,跳轉到NOS,并進行操作。

    下方為一組輸入,狀態機應做出如下反應:

    當某個狀態遇到不能識別的輸入時,就默認進入陷阱狀態,在陷阱狀態中,不論遇到怎樣的輸入都不能跳出

    為了表達上面這個狀態機,我們定義它們的狀態和輸入類型:

    typedef int State;
    typedef int Condition;
    #define STATES 3 + 1 //總的狀態數
    #define STATE_BSM 0
    #define STATE_NOS 1
    #define STATE_RSS 2
    #define STATE_TRAP 3
    #define CONDITIONS 2 //總的條件數
    #define CONDITION_1 0
    #define CONDITION_2 1
    

    在嵌入式環境中,由于存儲空間比較小,因此把它們全部定義成宏。此外,為了降低執行時間的不確定性,我們使用O(1)的跳轉表來模擬狀態的跳轉。

    首先定義跳轉類型:

    typedef void (*ActionType)(State state, Condition condition);
    typedef struct
    {
        State NextState;//下一個狀態
        ActionType action;//執行的動作
    } Trasition, * pTrasition;
    

    然后按照上圖中的跳轉關系,把三個跳轉和一個陷阱跳轉先定義出來:

    // 當前狀態   跳轉條件   下一個狀態   執行動作
    // BSM       condition1    NOS       action1
    Trasition TraBSM={
        .NextState = STATE_NOS,
        .action = actionBSM
    };
    // 當前狀態   跳轉條件   下一個狀態   執行動作
    // NOS       condition2    RSS       action2
    Trasition TraNOS={
        .NextState = STATE_RSS,
        .action = actionNOS
    };
    // 當前狀態   跳轉條件   下一個狀態   執行動作
    // RSS       condition1    NOS       action3
    Trasition TraRSS={
        .NextState = STATE_NOS,
        .action = actionRSS
    };
    // 當前狀態   跳轉條件   下一個狀態   執行動作
    //                        TRAP        trap
    Trasition TraTrap={
        .NextState = STATE_TRAP,
        .action = actionTRAP
    };
    

    其中的動作,由用戶自己完成,在這里僅定義一條輸出語句:

    void actionBSM(State state, Condition condition)
    {
        PRINTF("Action BSM triggered.n");
    }
    void actionNOS(State state, Condition condition)
    {
        PRINTF("Action NOS triggered.n");
    }
    void actionRSS(State state, Condition condition)
    {
        PRINTF("Action RSS triggered.n");
    }
    void actionTRAP(State state, Condition condition)
    {
        PRINTF("Action TRAP triggered.n");
    }
    

    為了表達跳轉關系,定義如下跳轉表:

    pTrasition transtion_table[STATES][CONDITIONS] = {
         &TraBSM,             &TraTrap,
         &TraTrap,            &TraNOS,
         &TraNOS,             &TraTrap,
        &TraTrap,            &TraTrap,
    };
    

    最后定義狀態機,如果不考慮多任務請求,那么狀態機僅需要存儲當前狀態便行了。例如:

    //執行當前狀態機的動作,并將目前狀態指向下一個狀態
    State PerformStateMachine(pStateMachine machine,Condition condition)
    {
        pTrasition Trastate = transtion_table[machine->CurrentState][condition];//獲取對應的狀態機
        (*(Trastate->action))(machine->CurrentState,condition);//執行狀態機的動作
        machine->CurrentState = Trastate->NextState;//指向下一個狀態機
        return machine->CurrentState;
    }
    

    但是考慮到當一個跳轉正在進行的時候,同時又有其他任務請求跳轉,則會出現數據不一致的問題。

    舉個例子:task1(BSM, / –> NOS)和task2(NOS, /–> RSS)先后執行,是可以順利到達RSS狀態的,但若操作運行的時候狀態機模式 c語言,執行權限被task2搶占,則task2此時看到的當前狀態還是BSM,BSM遇到就進入陷阱狀態,而不會到達RSS了,也就是說,狀態的跳轉發生了不確定,這是不能容忍的。

    因此要重新設計狀態機,增加一個“事務中”條件和一個用于存儲輸入的條件隊列。修改后的代碼如下:

    typedef struct{
        State CurrentState;
        bool inTrasaction;
        queue_t ConditionQueue;
    }StateMachine_t, * pStateMachine;
    #define SIZE  5//數組初始長度
    #define E_OK  0
    #define E_NO_DATA 1
    #define E_OVERFLOW 2
    #define STATE_INTRANSACTION  6
    typedef struct queue{
    	Condition  data[SIZE];
    	int front;
    	int rear;
        bool overflow;
    }queue_t,*pqueue_t;
    static State _step(pStateMachine machine,Condition condition)
    {
        State current = machine->CurrentState;
        pTrasition Trastate = transtion_table[machine->CurrentState][condition];//獲取對應的狀態機
        (*(Trastate->action))(machine->CurrentState,condition);//執行狀態機的動作
        current = Trastate->NextState;
        machine->CurrentState = current;//指向下一個狀態機
        return current;
    }
    //執行當前狀態機的動作,并將目前狀態指向下一個狀態
    State PerformStateMachine(pStateMachine machine,Condition condition)
    {
        Condition next_condition;
        int status;
        State current;
        if(machine->inTrasaction){
            En_Queue(&(machine->ConditionQueue),condition);
            return STATE_INTRANSACTION;
        }else{
            machine->inTrasaction = true;
            current = _step(machine,condition);
            status = De_Queue(&(machine->ConditionQueue),next_condition);
            while(status==E_OK){
                _step(machine,condition);
                status = De_Queue(&(machine->ConditionQueue),next_condition);
            }
            machine->inTrasaction = false;
            return current;
        }
        return machine->CurrentState;
    }
    void Init_Seq_Queue(pqueue_t *head)
    {
    	*head = (pqueue_t)malloc(sizeof(queue_t));//給結構體變量申請空間
    	if(*head == NULL){
    		// printf("*head  malloc failure %sn",__FUNCTION__);//申請錯誤打印錯誤函數,返回
    		return;
    	}
    	(*head)->front = -1;
    	(*head)->rear = -1;
        (*head)->overflow = false;
    	return ;
    }
    int En_Queue(pqueue_t pt,Condition Data)
    {
    	if(pt->rear == SIZE-1){
    		// printf("不好意思隊滿了n");
            pt->overflow = true;
    		return E_OVERFLOW;
    	}
    	pt->rear++;
    	pt->data[pt->rear] = Data;
    	return E_OK; 
    }
    int De_Queue(pqueue_t pt,Condition *data)
    {
    	if(pt->front == pt->rear){
    		// printf("不好意思,隊空了沒辦法出了n");
    		return E_NO_DATA;
    	}
    	pt->front++;
    	*data = pt->data[pt->front];
        pt->overflow = false;
    	return E_OK;
    }
    void initialize(pStateMachine machine, State s)
    {
        machine->CurrentState = s;
        machine->inTrasaction = false;
        Init_Seq_Queue(&(machine->ConditionQueue));
    }
    

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有