一種使用函式指標實現狀態機的方法
阿新 • • 發佈:2018-12-22
結構定義
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++
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)
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
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);
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++