【问题标题】:Finite-State Machine implementation有限状态机实现
【发布时间】:2012-06-26 08:08:46
【问题描述】:

我正在尝试用 C 语言实现有限状态机,并且需要它非常快。 所以我决定使用函数指针作为“状态”:

void *state1(void){ /* function body here */ }
void *state2(void){ /* ... */ }
void *state3(void){ /* ... */ }

那么,FSM 主循环就可以很简单了:

void *(*fp)(void);
fp = state1;

while(fp)
    fp = fp();

有一个问题:

1) 是否可以避免在函数返回类型中使用 void 指针?理想情况下,状态函数应该具有某种类型定义的类型,以确保在 FSM 中仅使用具有这种类型的函数。

2) 在 C 中实现 FSM 的传统方法是使用枚举作为状态和基于开关的调度程序循环,因此与基于函数指针的实现相比,会有一个间接级别。
但我不确定,指令缓存或分支预测是否存在一些问题?换句话说,是否存在可以胜过我的解决方案的实现?

谢谢。

【问题讨论】:

  • 我闻到微优化的味道了吗?状态机每毫秒需要运行多少次?
  • @Seva Alekseyev 一些状态相对较大且速度较慢,但​​有些状态非常小且简单。当 FSM 处于“大”状态之一时,性能并不重要,但必须尽可能快地执行小状态。
  • 如果您希望它更快,请使用 one-hot 编码状态机。你过早的优化不会有很长的路要走。你最好写出可读、可维护和可扩展的代码。此外,对于 C++ - boost.org/doc/libs/1_49_0/libs/statechart/doc/index.html

标签: c function-pointers fsm


【解决方案1】:

要在 C 中创建这样的递归类型定义,您需要在某处使用struct,因为您不能“前向声明”类型定义。例如,您可以将函数指针包装在 struct 中:

struct state {
    struct state (*func)(void);
};

然后在循环中:

struct state state = { state1 };

while (state.func) {
    state = state.func();
}

【讨论】:

    【解决方案2】:

    您可以在这里找到问题的答案:http://code.google.com/p/fwprofile/

    它是实现状态机的开源版本 (GNU GPLv3) 在 C 中。概念和实现非常适合用于 关键任务应用程序。工业领域有部署 应用程序。

    【讨论】:

      【解决方案3】:

      在 C 中不可能声明一个返回指向其自身类型函数的指针的函数。此外,您不能使用void *,因为C 不允许函数和对象指针之间的转换。相反,您可以使用:

      typedef void (*generic_func_ptr)(void);
      typedef generic_func_ptr (*state_func_ptr)(void);
      generic_func_ptr state1(void), state2(void), state3(void);
      state_func_ptr fp;
      
      while(fp)
          fp = (state_func_ptr)fp();
      

      丑陋,但它有效。相反,我会考虑使用 switch 语句。实现状态机要干净得多。

      【讨论】:

        【解决方案4】:

        1)typedef void(*state_fp)(void);

        state_fp state1(void) { }
        

        2) 取决于,在函数中内置代码的小循环将比进行函数调用更快。例如,一个 switch 语句,其中每个状态都在 switch 语句中实现,但是,如果有太多的 case 语句,这将在函数调用之下降级

        【讨论】:

        • 这将需要在返回时进行强制转换,因为函数返回的类型与指向函数本身的指针的类型不同(它仍然比 OP 更好,至少你是从一种函数指针类型转换为另一种函数指针类型,因此它是明确定义的)。
        【解决方案5】:

        如果其他人想要使用免费的 fsm 框架,请查看http://www.block-net.de/Programmierung/cpp/fsm/fsm.html 有一个 C 和 C++ 有限状态机框架,包括带有 PlantUML 的状态图生成器。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-03-31
          • 2020-11-18
          • 2018-11-13
          • 2014-01-09
          • 1970-01-01
          • 2017-01-04
          • 1970-01-01
          相关资源
          最近更新 更多