I recently fell in love with the simplicity of the concurrency model based on the Erlang action, and I play with ideas to implement some of its parts in C ++. Along these lines, I also like the idea of implementing a finite state machine as a collection of functions representing states where transitions are performed by calling the tail from one function to the next.
I would like to try something similar in C ++. But a naive implementation of this is likely to run into the fact that the tail calling my compiler (GCC 4.1 with -O0 ) will eventually lead to a stack overflow. So instead, I want each state / function to return a functor (the next state to enter) and contain a base loop that just calls the functor, then calls the returned functor, then calls the functor returned this way, etc. Sort of:
typedef ... context_t; // A statefunctor is a functor which takes a context_t and // returns a statefunctor // // FIXME: of course, this typedef won't compile. typedef boost::function<statefunctor (context_t& )> statefunctor; // NULL boost::function<> represents the exit condition. static const statefunctor EXIT_FSM; // primary loop which runs the FSM void run_fsm(context_t& ctx, statefunctor initial_state) { while (initial_state) { initial_state=initial_state(boost::ref(ctx)); } } // states 'foo', 'bar', and 'baz'; statefunctor foo(context_t& ctx); statefunctor bar(context_t& ctx, int inval); statefunctor baz(context_t& ctx); // State 'foo' statefunctor foo(context_t& ctx) { // act somehow on the external context int magic_number_1=ctx.get_magic_number(); int magic_number_2=ctx.get_magic_number(); // Always transition to 'bar' return boost::bind(&bar, _1, magic_number_1-magic_number_2); } // State 'bar' statefunctor bar(context_t& ctx, int inval) { inval+=ctx.get_magic_number(); // Act on external context somehow // transition to foo or baz if (inval>0) { return &foo; } else { return &baz; } } // State 'baz' statefunctor baz(context_t& ctx) { // Transition to foo or exit if (ctx.get_magic_number()==5) {return EXIT_FSM;} else {return &foo;} } int main() { context_t ctx; // start the state machine in state 'foo' run_fsm(ctx, &foo); }
So my question is: how to define a statefunctor ? In particular, I want it to contain arbitrary functors (for example, boost::bind(...) could create), and not just function pointers.
NOTE: I use boost::bind , boost::function , boost::ref instead of my std:: counterparts because I am stuck using GCC 4.1 which does not support C ++ 11. Solutions valid in C ++ 03 are evaluated :-).
source share