
<!-- ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| section -->
<section id="example">
<title>Example: a compile-time FSM generator</>

<para>
Finite state machines (<acronym>FSMs</>) are an important tool for describing and implementing program behavior <citation><xref linkend="ref.hu79"></>, <citation><xref linkend="ref.mar98"></>. They also are a good example of a  domain in which &mping; can be applied to reduce the amount of repetitive and boilerplate operations one must perform in order to implement these simple mathematical models in code. Below we present a simple state machine generator that has been implemented using &BMPL; facilities. The generator takes a compile-time automata description, and converts it into &Cxx; code that implements the FSM at run-time. 
</>

<para>
The FSM description is basically a combination of states and events plus a state transition table (<acronym>STT</>), which ties them all together. The generator walks through the table and generates the state machine's <literal>process_event</> method that is the essence of an FSM.
</>

<para>
Suppose we want to implement a simple music player using a finite state machine model. The state transition table 
for the FSM is shown in <xref linkend="example.fsm.stt">. The STT format reflects the way one usually describes the behavior of an FSM in plain English. For example, the first line of the table can be read as follows: <quote>If the model is in the <literal>stopped</> state and the <literal>play_event</> is received, then the <literal>do_play</> transition function is called, and the model transitions to the <literal>playing</> state</>.
</>

<table id="example.fsm.stt" frame="none">
<title>Player's state transition table with actions</>

<tgroup cols="4" align="left">
<thead>
<row>
    <entry>State</>
    <entry>Event</>
    <entry>Next state</>
    <entry>Transition function</>
</>
</>

<tbody>
<row>
    <entry><literal>stopped</></>
    <entry><literal>play_event</></> 
    <entry><literal>playing</></>
    <entry><literal>do_play</></>
</>
<row>
    <entry><literal>playing</></>
    <entry><literal>stop_event</></>
    <entry><literal>stopped</></>
    <entry><literal>do_stop</></>
</>
<row>
    <entry><literal>playing</></>
    <entry><literal>pause_event</></>
    <entry><literal>paused</></>
    <entry><literal>do_pause</></>
</>
<row>
    <entry><literal>paused</></>
    <entry><literal>play_event</></>
    <entry><literal>playing</></>
    <entry><literal>do_resume</></>
</>
<row>
    <entry><literal>paused</></>
    <entry><literal>stop_event</></>
    <entry><literal>stopped</></>
    <entry><literal>do_stop</></>
</>
</>
</tgroup>

</table>

<para>
The transition table provides us with a complete formal definition of the target FSM, and there are several ways to 
transform that definition into code. For instance, if we define states as members of an enumeration type, and events as classes derived from some base <literal>event</> class

<footnote id="note.fsm"><para>The events need to be passed to action functions, as they may contain some event-specific information for an action.</></>

, like so:
</>

<programlisting>
<![CDATA[
class player
{
 public:
    // event declarations
    struct event;
    struct play_event;
    struct stop_event;
    struct pause_event;

    // "input" function
    void process_event(event const&); // throws

 private:
    // states
    enum state_t { stopped, playing, paused };

    // transition functions
    void do_play(play_event const&);
    void do_stop(stop_event const&);
    void do_pause(pause_event const&);
    void do_resume(play_event const&);

 private:
    state_t m_state;
};
]]>
</>

<para>
then the most straightforward way to derive the FSM implementation from the above table would be something 
like this:
</>

<programlisting>
<![CDATA[
void player::process_event(event const& e)
{
    if (m_state == stopped)
    {
        if (typeid(e) == typeid(play_event))
        {
            do_play(static_cast<play_event const&>(e));
            m_state = playing;
            return;
        }
    }
    else if (m_state == playing)
    {
        if (typeid(e) == typeid(stop_event))
        {
            do_stop(static_cast<stop_event const&>(e));
            m_state = stopped;
            return;
        }

        if (typeid(e) == typeid(pause_event))
        {
            do_pause(static_cast<pause_event const&>(e));
            m_state = paused;
            return;
        }
    }
    else if (m_state == paused)
    {
        if (typeid(e) == typeid(stop_event))
        {
            do_stop(static_cast<stop_event const&>(e));
            m_state = stopped;
            return;
        }

        if (typeid(e) == typeid(play_event))
        {
            do_play(static_cast<play_event const&>(e));
            m_state = playing;
            return;
        }
    }
    else
    {
        throw logic_error(
            boost::format("unknown state: %d")
                % static_cast<int>(m_state)
            );
    }

    throw std::logic_error(
        "unexpected event: " + typeid(e).name()
        );
}
]]>
</>

<para>
Although there is nothing particularly wrong with implementing an FSM's structure using nested <literal>if</> (or <literal>switch-case</>) statements, the obvious weakness of this approach is that most of the above code is boilerplate. What one tends to do with boilerplate code is to copy and paste it, then change names etc. to adjust it to its new location; and that's where the errors are most likely to creep in. Since all the lines of event processing look alike (structurally), it's very easy to overlook or forget something that needs to be changed, and many such errors won't appear until the runtime.
</>

<para>
The transition table of our FSM is just five lines long; ideally, we would like the skeleton implementation of the automata's controlling logic to be equally short (or, at least, to look equally short, i.e. to be encapsulated in some form so we never worry about it). 
</>

<!-- ||||||||||||||||||||||||||||| subsection -->
<section id="example.impl">
<title>Implementation</>

<para>
To represent the STT in a &Cxx; program, we define a <literal>transition</> class template that represents a single line of the table. Then the table itself can be represented as a sequence of such lines:
</>

<programlisting>
<![CDATA[
typedef mpl::list<
      transition<stopped, play_event,  playing, &player::do_play>
    , transition<playing, stop_event,  stopped, &player::do_stop>
    , transition<playing, pause_event, paused,  &player::do_pause>
    , transition<paused,  play_event,  playing, &player::do_resume>
    , transition<paused,  stop_event,  stopped, &player::do_stop>
    >::type transition_table;
]]></>

<para>
Now, the complete FSM will look like this:
</>

<programlisting>
<![CDATA[
class player
    : state_machine<player>
{
 private:
    typedef player self_t;

    // state invariants
    void stopped_state_invariant();
    void playing_state_invariant();
    void paused_state_invariant();

    // states (invariants are passed as non-type template arguments,
    // and are called then the FSM enters the corresponding state)
    typedef state<0, &self_t::stopped_state_invariant> stopped;
    typedef state<1, &self_t::playing_state_invariant> playing;
    typedef state<2, &self_t::paused_state_invariant> paused;

 private:
    // event declarations; events are represented as types, 
    // and can carry a specific data for each event;
    // but it's not needed for generator, so we define them later
    struct play_event;
    struct stop_event;
    struct pause_event;

    // transition functions
    void do_play(play_event const&);
    void do_stop(stop_event const&);
    void do_pause(pause_event const&);
    void do_resume(play_event const&);

    // STT
    friend class state_machine<player>;
    typedef mpl::list<
          transition<stopped, play_event,  playing, &player::do_play>
        , transition<playing, stop_event,  stopped, &player::do_stop>
        , transition<playing, pause_event, paused,  &player::do_pause>
        , transition<paused,  play_event,  playing, &player::do_resume>
        , transition<paused,  stop_event,  stopped, &player::do_stop>
        >::type transition_table;
};
]]>
</>

<para>
That's all &mdash; the above will generate a complete FSM implementation according to our specification. The only thing we need before using it is the definition of the event types (that were just forward declared before):
</>

<programlisting>
<![CDATA[
// event definitions
struct player::play_event
    : player::event
{
};

// ...
]]>
</>

<para>
The usage is simple as well:
</>

<programlisting>
<![CDATA[
int main()
{
    // usage example
    player p;
    p.process_event(player::play_event());
    p.process_event(player::pause_event());
    p.process_event(player::play_event());
    p.process_event(player::stop_event());
    return 0;
}
]]>
</>
</section>

<!-- ||||||||||||||||||||||||||||| subsection -->
<section id="example.relatedwork">
<title>Related work</>

<para>
A notable prior work in the field of automation of general-purpose state machine implementation in &Cxx; is the Robert Martin's <emphasis>State Machine Compiler</> <citation><xref linkend="ref.smc"></>. The SMC takes an ASCII description of the machine's state transition table and produces &Cxx; code that implements the FSM using a variation of State design pattern <citation><xref linkend="ref.hun91"></>, <citation><xref linkend="ref.ghj95"></>. Lafreniere <citation><xref linkend="ref.laf00"></> presents another approach, where no external tools are used, and the FSMs are table driven. 
</>
</section>

</section>
