一個有限狀態機的C++實現

HULK一線技術雜談發表於2018-11-05

女主宣言

有限狀態機:表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。它對數字系統的設計具有十分重要的作用。常見的計算機就是使用有限狀態機作為計算模型的;電腦遊戲設計中也經常使用有限狀態機模型。本文就講講一個狀態機的C++實現。

PS:豐富的一線技術、多元化的表現形式,盡在“HULK一線技術雜談”,點關注哦!

有限狀態機

什麼是有限狀態機?

簡單說就是作一件事可能會經過多個不同狀態的轉換, 轉換依賴於在不同時間發生的不同事件來觸發, 舉個例子,比如 TCP的狀態轉換圖, 在實現上就可以用FSM.

一個有限狀態機的C++實現

傳統的實現方案

if...else : 搞一大堆if else, 一個函式寫很長很長......

swich...case : 也搞一大堆一個函式寫很長很長......

FSM的實現方案

根據具體的業務需要, 將業務的處理流程定義為一個狀態機, 此狀態機中存在以下必要元素

  1. 根據業務需要, 拆解抽象出若干個不同狀態 State, 並確定此狀態機的初始狀態;

  2. 根據實現需要, 抽象出用於觸發狀態轉換的事件 Event;

  3. 為了處理一個Event, 需要定義狀態的轉換過程Transition;

  4. 狀態機要先判斷當前所處的狀態是否與當前發生的Event匹配(注意: 相同的狀態可能同時匹配多個Event)。

用張簡圖來說明一下

一個有限狀態機的C++實現


  1. MachineSet可以同時管理多個Machine;

  2. 外部觸發的Event進入到MachineSet的事件佇列;

  3. 事件佇列裡的Event被順序處理, 被Dispatch到match的Machine;

  4. Machine根據當前的所處的state和Event型別來判斷當前Event是否有效;

  5. 如果上面(4)中的Event有效, 則進行狀態轉換;

  6. 狀態轉換具體來說涉及到三個回撥函式:

            6.1 當前state離開, 是第一個回撥,需要使用者根據實際需要處理;

            6.2 trasition這個轉換過程, 是第二個回撥;
            6.3 新state的進入, 是第三個回撥;

一個簡單的狀態機,差不多就是上面這些內容, 剩下的就是用程式語言把它實現出來了;

FSM的C++ 實現

一個用C++11實現的FSM的程式碼

https://github.com/DavidLiuXh/kuafu

實現簡介:

主要就是按deamo裡的思路, 封裝了以下幾個模組

MachineSet,
Machine,
Event,
Transition,
Predicate

對於Event的處理, 提供兩種方案:

  1. 直接使用MachineSet提供的StartBackground, 開啟一個work thread, 在這個work thread中不斷從儲存event的fifo佇列中獲取event後dispatch到各個machine;

  2. 不使用MachineSet提供的event fifo, 實現自己的MachineSetHandler, 將其例項註冊到MachineSet, 從event的派發;

一個具體的實現

我們來使用上面的FSM的實現來模擬一個使用者登陸的場景;

定義用到的Event和幾種不同的事件型別

一個有限狀態機的C++實現

定義用到的狀態機, 從 kuafu::StateMachine 繼承, 其中包括用過的幾種state和transition一個有限狀態機的C++實現

在Birth()函式中構造 state和 transition, Birth()是StateMachine的一個虛擬函式, 每個使用者實現的Machine都需要實現它:

一個有限狀態機的C++實現

建立MachineSet, 並開始event處理執行緒

一個有限狀態機的C++實現

建立使用者定義的Machine, 設定初始狀態

一個有限狀態機的C++實現

設定state和transition相應的回撥

一個有限狀態機的C++實現

模擬event發生:

一個有限狀態機的C++實現

相關原始碼:

MachineSet:https://github.com/DavidLiuXh/kuafu/blob/master/fsm/machine_set.h

Machine:https://github.com/DavidLiuXh/kuafu/blob/master/fsm/machine.h

Event:https://github.com/DavidLiuXh/kuafu/blob/master/fsm/event.h

Transition:https://github.com/DavidLiuXh/kuafu/blob/master/fsm/transition.h

Predicate:https://github.com/DavidLiuXh/kuafu/blob/master/fsm/transition_predicate.h

kuafu::StateMachine:https://github.com/DavidLiuXh/kuafu/blob/master/fsm/machine.h

HULK一線技術雜談

由360雲平臺團隊打造的技術分享公眾號,內容涉及雲端計算資料庫大資料監控泛前端自動化測試等眾多技術領域,通過夯實的技術積累和豐富的一線實戰經驗,為你帶來最有料的技術分享

原文連結:https://mp.weixin.qq.com/s/2Un2Vy33dkxPwe8n7d_Yng

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31555491/viewspace-2218737/,如需轉載,請註明出處,否則將追究法律責任。

相關文章