一种使用函数指针实现状态机的方法
结构定义
1 struct state_machine {
2 int state;
34 };
5
6 enum {
7 s1,
8 s2,
910 sn
11
};
假设s1为初始状态,状态变迁为s1->s2->...->sn。
常规实现
假设每次调用state_machine_handle时,输入data是变化的,不同的data会改变状态,伪代码框架如下。
1 void handle_s1( struct state_machine * sm, void *
data)
2{
3 // do something about state 1 4 if(is_satisfy_s2(data))
5 sm -> state =s2;
6 } 7 8 void handle_s2( struct state_machine * sm, void *data)
9{
10 // do something about state 2 11 if(is_satisfy_s3(data))
12 sm -> state =s3;
13 } 14 15 void handle_sn_1( struct state_machine * sm, void *data)
16{
17 // do something about state n-1 18 if(is_satisfy_sn(data))
19 sm -> state =sn;
20 } 21 22 void state_machine_handle( struct state_machine * sm, void *data)
23{
24 switch (sm -> state){
25 cases1:
26handle_s1(sm,data);
27 break;
28 29 cases2:
30handle_s2(sm,data);
31 break;
32 33 casesn:
34handle_sn(sm,data);
35 break;
36 } 37 }sm->state初始化为s1。
改进实现
为了免去丑陋的switch case分支结构,用成员函数指针handler替代了state,改进后的框架如下。
1 struct
21
28
state_machine;
2 typedef void ( * state_handler)( struct state_machine * , void *);
3 4 struct state_machine{
5 state_handler handler ; 6 7 };
8 9 void handle_s1( struct state_machine * sm, void *data)
10{
11 // do something about state 1 12 if(is_satisfy_s2(data))
13 sm -> handler = handle_s2 ; 14 } 15 16 void handle_s2( struct state_machine * sm, void *data)
17{
18 // do something about state 2 19 if(is_satisfy_s3(data))
20 sm -> handler = handle_s3;}
22 23 void handle_sn_1( struct state_machine * sm, void *data)
24{
25 // do something about state n-1 26 if(is_satisfy_sn(data))
27 sm -> handler = handle_sn ;}
29 30 void state_machine_handle( struct state_machine * sm, void *data)
31{
32 sm -> handler(sm, data);
33 }sm->handler初始化为handle_s1,该方法在性能上应略优于常规方法,而且逻辑更清晰自然,非常适合于网络流的处理,在nginx中分析http和email协议时,得到了广泛应用。