IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    春秋十二月发表于 2016-05-05 01:46:00
    love 0
    结构定义
     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
     4    if(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 2
    11    if(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-1
    18    if(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 1
    12    if(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 2
    19    if(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-1
    26    if(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协议时,得到了广泛应用。


    春秋十二月 2016-05-05 09:46 发表评论


沪ICP备19023445号-2号
友情链接