一种使用函数指针实现状态机的方法

一种使用函数指针实现状态机的方法
结构定义
 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会随时序变化,从而引起状态的变迁,伪代码框架如下。
 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        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,改进后的框架如下。
 1 struct  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;
21}

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;
28}

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协议时,得到了广泛应用。

你可能感兴趣的:(一种使用函数指针实现状态机的方法)