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

结构定义

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是变化的,不同的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分支结构,用成员函数指针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协议时,得到了广泛应用。

posted @ 2016-05-09 12:02  投机者  阅读(269)  评论(0编辑  收藏  举报