状态机 - 保持状态,事件和pFunc的结构

时间:2011-07-22 06:09:57

标签: c++ finite-automata fsm state-machine

如果我制作状态机并希望使用这样的界面:

AddState ( state1, state2, Key_UP );
AddEvent ( Key_UP );
AddEventFunction ( Key_UP, &UP_Function);
AddStateFunction ( state1, &State1_In_Function, &State1_Out_Function);
AddStateFunction ( state2, &State2_In_Function, &State2_Out_Function);

State1_In_Function  ( void ) { printf ( "In #1 \n" ); }
State1_Out_Function ( void ) { printf ( "Out #1 \n" ); }
State2_In_Function  ( void ) { printf ( "In #2 \n" ); }
State2_Out_Function ( void ) { printf ( "Out #2 \n" ); }
UP_Function         ( void ) { printf ( "Goin UP \n" ); }

这样当我在state1并且FSM收到Key_UP时,程序会打印出来:

Out #1
Goin UP
In #2

问题是如何在类中存储状态和过渡信息,而不需要程序员更改数组大小。我以为我可以使用2D数组并像往常一样使它成为一个状态表,并使其更具可移植性我将通过使用矢量类型根据需要调整大小来处理事件和状态的添加。向量的问题是没有多少嵌入式设备可以使用内存分配调用。我的第二个选择是使用状态机调用构造函数并将其传递给表所需的大小,但如果我添加任何新状态或事件,我还需要更改这些值...

那么我应该如何存储我的状态,事件和函数指针?!

3 个答案:

答案 0 :(得分:3)

你可以简单地将它们存储在堆栈中,虽然这有点困难:)

不过,这是一个有趣的解决方案,所以你走了。基本原则是扮演装饰者和可变性。代码示例:

State state1, state2; // creates a state
Event KEY_UP;
Event KEY_DOWN;

Transition t0(state1, KEY_UP, state2);
Transition t1(state2, KEY_DOWN, state1);

它是如何运作的?

而不是state1是一个“简单”的对象,它会稍微复杂一些。类似的东西:

struct State;

struct StateImpl {
  StateImpl(char const* n): name(n) {}
  char const* name;
};

struct StateNode {
  StateNode(Event e, State const& s, StateNode const* n):
    event(e), state(s), next(n) {}

  Event event;
  State const& destination;
  StateNode const* next;
};

struct State {
  State(char const* name):
    me(0), impl(name) {}

  StateNode const* me;
  StateImpl impl;
};

然后我们定义Transition

struct Transition {
  Transition(State& origin, Event e, State const& destination):
    node(e, destination, origin.me)
  {
    origin.me = node;
  }
  StateNode node;
};

非正式地,我们正在建立一个单链表,头部位于State。我们每次添加转换时都会更新头部。

在事件发生时,需要遍历此列表,直到遇到事件,从而适当地调度,或者到达空指针,表明在此状态下不会收到事件。

答案 1 :(得分:0)

我建议您查看Boost.StateChart,如果需要,可以使用您想要的API在其周围构建一个薄层。

这应该可以解决您设计适当数据结构的需要。

答案 2 :(得分:0)

顺便说一句,你可以get cute and do it this way