1. 程式人生 > >一種使用函式指標實現狀態機的方法

一種使用函式指標實現狀態機的方法

結構定義
 1 struct state_machine {
 2     int state;
 3     
 4 };
 5 
 6 enum { 
 7     s1,
 8     s2,
 9     
10     sn
11 };   假設s1為初始狀態,狀態變遷為s1->s2->...->sn。

常規實現
   狀態機處理函式state_machine_handle通常在一個迴圈內或被事件驅動框架呼叫,輸入data會隨時序變化,從而引起狀態的變遷,虛擬碼框架如下。
 1void handle_s1(struct state_machine *sm, void*data)
 2{
 3    //do something about state 1 4if(is_satisfy_s2(data))
 5        sm->state = s2;
 6}
 7
 8void handle_s2(struct state_machine *sm, void*data)
 9{
10    //do something about state 211if(is_satisfy_s3(data))
12        sm->state = s3;
13}
14
15void handle_sn_1(struct state_machine *sm, void*data)
16{
17    
//do something about state n-118if(is_satisfy_sn(data))
19        sm->state = sn;
20}
21
22void state_machine_handle(struct state_machine *sm, void*data)
23{
24    switch(sm->state){
25        case s1:
26            handle_s1(sm,data);
27            break;
28            
29        case s2:
30            handle_s2(sm,data);
31            break;            
32            
33        case sn:
34            handle_sn(sm,data);
35            break;
36    }
37}
   sm->state初始化為s1。

改進實現    為了免去醜陋的switch case分支結構,在state_machine內用成員函式指標handler替代了state,改進後的框架如下。  1struct state_machine;
 2typedef void (*state_handler)(struct state_machine*void*);
 3
 4struct state_machine {
 5    state_handler handler; 6    
 7}
;
 8
 9void handle_s1(struct state_machine *sm, void*data)
10{
11    //do something about state 112if(is_satisfy_s2(data))
13        sm->handler = handle_s2;14}
15
16void handle_s2(struct state_machine *sm, void*data)
17{
18    //do something about state 219if(is_satisfy_s3(data))
20        sm->handler = handle_s3;
21}
22
23void handle_sn_1(struct state_machine *sm, void*data)
24{
25    //do something about state n-126if(is_satisfy_sn(data))
27        sm->handler = handle_sn;
28}
29
30void state_machine_handle(struct state_machine *sm, void*data)
31{
32    sm->handler(sm, data);
33}
   sm->handler初始化為handle_s1,該方法在效能上應略優於常規方法,而且邏輯更清晰自然,非常適合於網路流的處理,在nginx中分析http和email協議時,得到了廣泛應用。 posted on 2016-05-05 09:46 春秋十二月 閱讀(2341) 評論(1)  編輯 收藏 引用 所屬分類: C/C++