boost狀態機說明

2021-10-21 04:09:08 字數 4528 閱讀 2321

1. 狀態

物件在其生命週期內,所處於的運動和發展階段。例如:人可以處於工作中這個狀態,也可以處於娛樂中狀態。

狀態應該有上下文環境。例如:人處於工作中狀態,要屬於職業生涯狀態而不能是退休狀態,也必須是活著的,而不能是死亡的狀態。狀態可以有子狀態。例如:工作中狀態,可以有開會中,會客中,被訓斥中等子狀態。

2. 狀態機

由許多相關狀態構成的集合。把乙個物件,或者乙個系統看做是乙個狀態機。

struct m : state_machine< m, a > {}; //這裡定義了乙個狀態機類m。初始狀態在a

struct a : ******_state{}; //這裡定義乙個了狀態a,屬於m狀態機。

struct a : ******_state{}; //這裡定義乙個了狀態a,屬於m狀態機。a狀態有初始子狀態a1

其實可以狀態機看做狀態,把狀態看做狀態機,區別不是很大。

如果不考慮「歷史狀態」,當進入狀態m後,會自動進入初始狀態a,然後自動進入a1。如果a1有子狀態a11,就會進入a11。

3. 狀態本地儲存

一般的,狀態物件裡不存放任何變數。我們把資料存放到狀態機m裡。這樣做不方便。例如:我們工作相關的資料和娛樂相關的資料都放到「生存」這個狀態機類裡,首先就失去了資料封裝隱藏的好處了。其次,每個狀態或子狀態只要能訪問到狀態機,就可讀寫任意其他狀態需要的重要資訊,容易導致類似「全域性變數」帶來的壞處。

利用context<>, state_cast<>等機制,我們可以容易的訪問當前狀態的「容器狀態」和「啟用的子狀態」的引用,然後呼叫set,get方法去改變他們的資料值。

4.事件

狀態機對外部或內部事件感興趣,引起狀態轉移。例如:當人處於混混欲睡狀態時,突然收到乙個好訊息事件,人就改變為興奮狀態了。

struct evt: sc::event< evt > {}; //事件類。當然可以加入自己想傳達的任何資訊。

struct evt: sc::event< evt > ; //可以加一些成員變數進去。

5. 狀態轉移

當狀態感覺到乙個事件發生時,可以對這個事件做出反應。狀態轉移就是一條「規則」,指明如何反應。例如:

當有人罵你這個事件發生時,你可以根據「惡意度」,罵人者與你的「親密程度」,選擇忽略這個事件,或者轉移到「暴怒狀態」,或者做出一定回擊。

struct a1 : ******_state; //狀態轉移規則用typedef說明,注意reactions不能拼錯。

typedef transition< evt, b  > reactions; //當遇到事件evt是,就轉移到狀態b。

狀態轉移能從乙個狀態跳轉到任意的乙個狀態,即使狀態是巢狀的深層子狀態。

d->c->b->a

innermostcommonouter->machime

z->y->x 

假設d是最深層的巢狀子狀態,可以從d跳轉到y。首先要跳出d(執行d的exit action),依次跳出c,b,a。

不會離開innermostcommonouter狀態,進入x(執行x的entry action),進入y。

6. 監護條件

當乙個事件發生時,根據乙個條件表示式的bool值,決定此轉換的目標。最好的監護條件實現是if語句或者swich語句。boost提供custom_reaction<>自定義轉換機制,方便實現監護條件。

struct a : sc::******_state{

typedef sc::custom_reaction< evt > reactions;

sc::result react( const evt &evt )

//實現transition action

cout<<"transition action called"if (evt.m_raised_salary > 0){

return transit< c >(); //跳轉到狀態c    

if (evt.m_raised_salary < 0){

return transit< b >(); //跳轉到狀態b    

else{

return discard_event(); //什麼也不做

7. 轉移動作transition action

同乙個轉移關聯的動作。可以用custom_reaction<>機制實現。也可以用下述方法實現。

struct a : ******_state{

typedef transition< evt, b,  s, &s::transtion_action  > reactions;

其中,s要求至少是狀態a,b的innermostcommonouter,其outer環境也可以,當然狀態機m更可以。

struct s : sc::state_machine< s, 。。。 > {

void transtion_action(const evt &){ //transtion_action必須是這樣的函式簽名。

std::cout<<"s::transtion_action() called"<8. 投遞事件

最簡單是process_event函式

s s;

s.initiate();

s.process_event(evt()); 

事件首先被投遞給最深層的當前子狀態,讓後向外層投遞。

假設c->b->a,其中c是當前最深子狀態,並且abc三者都定義了對事件evt的轉移規則。

則c先獲得事件evt的處理。一般來說b,a將不能感知到事件。

c可以呼叫forward_event()將事件拋給b處理。這是當c不能處理乙個事件x(未定義狀態轉移)時,預設行為(拋給直接上級狀態處理)。

9. 進入/退出動作

struct a : ******_state{

a(){

std::cout<<"a建構函式被呼叫, entry action"<~a(){

std::cout<<"~a析構函式被呼叫,exit action"《使用建構函式和析構函式實現了狀態的進入,退出action

10. 歷史狀態

struct a : ******_state{

狀態a有乙個特殊的偽子狀態---淺歷史狀態。其初始值可以認為是a1(等於初始子狀態)。

當從a轉移出後,能記住最後乙個直接子狀態例如:a9。

當從別處重新回到a狀態時,能直接進入到a9。(而不是進入初始子狀態。)

「淺」是指:只記住a的直接子狀態;「深」是指:能記住a的最深的巢狀子狀態。

struct x : ******_statetypedef sc::transition> reactions;

回到a,進入歷史狀態

11. 多事件

typedef boost::mpl::list<

sc::transition< evt1, b >

sc::transition< evt2, c >

> reactions;

乙個狀態對多種事件的反應規則

12. 標頭檔案

#include

#include

#include

#include

#include

#include

#include

#include

13. 延遲事件

struct b : sc::******_state{

typedef sc::deferral< evtdefer > reactions;

處於b狀態時,暫時不能處理evtdefer,但是希望離開b狀態時,才處理事件evtdefer。

延遲事件同post_event()不同之處在於,post_event能把事件放入狀態機主事件佇列,在action執行完成後,

就會立刻執行被post的事件(沒有等待b結束,這個重要條件)

14. 狀態機terminate()

terminate()會造成狀態機離開當前活動狀態,到達偽終態。

typedef boost::mpl::list<

sc::transition< evt2a,a >,

sc::deferral< evtdefer >,

sc::termination< evtkill >

> reactions;

或者sc::result a::react( const evtkill & )

return terminate();

15. sc::result

sc::result a::react( const evt& )

return discard_event(); //忽略事件

sc::result a::react( const evt& )

return forward_event(); //請求向上級狀態處理此事件

sc::result a::react( const evt& )

return transit(); //轉移到b狀態

sc::result a::react( const evt& )

return terminate(); //狀態機自殺

16. 查詢狀態機是否在執行

bool lb = s.terminated(); //其中s是乙個狀態機物件

狀態機 狀態機0

近半年都忙於做專案,沒有太多的時間去整理和總結在專案中用過的技術 個人還是覺得技術需要總結提煉和沉澱的,忙到沒時間去總結提公升其實不 是什麼好事,這次講下狀態機,在戰鬥型別的遊戲中角色有多種不同的狀態,而狀態的切換錯綜複雜,23種設計模式中有一種模式叫做狀態模式,不過 這種模式是把狀態切換條件放到各...

python 狀態機 Python 狀態機

class statemachine def init self self.handlers 狀態轉移函式字典 self.startstate none 初始狀態 self.endstate 最終狀態集合 引數name為狀態名,handler為狀態轉移函式,end state表明是否為最終狀態 de...

狀態機小記

工作上有個功能模組用到了類似狀態機的東東,於是上網科普了一番。狀態機是由一系列輸入驅動,然後系統由其中一種狀態轉換為另一種狀態並產生某種輸出,這樣子的乙個系統叫做狀態機。狀態機分為兩種,一種是輸出只和系統狀態有關,叫做摩爾狀態機,另一種是輸出和輸入以及系統狀態都相關,叫做公尺莉狀態機。有關輸入 狀態...