| <html><head> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
| <title>Functor front-end</title><link rel="stylesheet" href="boostbook.css" type="text/css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2"><link rel="home" href="index.html" title="Meta State Machine (MSM) V2.12"><link rel="up" href="ch03.html" title="Chapter 3. Tutorial"><link rel="prev" href="ch03s02.html" title="Basic front-end"><link rel="next" href="ch03s04.html" title="eUML (experimental)"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Functor front-end</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch03s02.html">Prev</a> </td><th width="60%" align="center">Chapter 3. Tutorial</th><td width="20%" align="right"> <a accesskey="n" href="ch03s04.html">Next</a></td></tr></table><hr></div><div class="sect1" title="Functor front-end"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e1206"></a><span class="command"><strong><a name="functor-front-end"></a></strong></span>Functor front-end</h2></div></div></div><p>The functor front-end is the preferred front-end at the moment. It is more |
| powerful than the standard front-end and has a more readable transition table. |
| It also makes it easier to reuse parts of state machines. Like <span class="command"><strong><a class="command" href="ch03s04.html#eUML-front-end">eUML</a></strong></span>, it also comes with a good deal |
| of predefined actions. Actually, eUML generates a functor front-end through |
| Boost.Typeof and Boost.Proto so both offer the same functionality.</p><p>The rows which MSM offered in the previous front-end come in different |
| flavors. We saw the a_row, g_row, _row, row, not counting internal rows. This is |
| already much to know, so why define new rows? These types have some |
| disadvantages: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>They are more typing and information than we would wish. This |
| means syntactic noise and more to learn.</p></li><li class="listitem"><p>Function pointers are weird in C++.</p></li><li class="listitem"><p>The action/guard signature is limited and does not allow for more |
| variations of parameters (source state, target state, current state |
| machine, etc.)</p></li><li class="listitem"><p>It is not easy to reuse action code from a state machine to |
| another.</p></li></ul></div><div class="sect2" title="Transition table"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1230"></a> Transition table </h3></div></div></div><p>We can change the definition of the simple tutorial's transition table |
| to:</p><pre class="programlisting"> |
| struct transition_table : mpl::vector< |
| // Start Event Target Action Guard |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| Row < Stopped , play , Playing , start_playback , none >, |
| Row < Stopped , open_close , Open , open_drawer , none >, |
| Row < Stopped , stop , Stopped , none , none >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| Row < Open , open_close , Empty , close_drawer , none >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| Row < Empty , open_close , Open , open_drawer , none >, |
| Row < Empty , cd_detected, Stopped , store_cd_info , good_disk_format >, |
| g_row< Empty , cd_detected, Playing , &player_::store_cd_info , &player_::auto_start >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| Row < Playing , stop , Stopped , stop_playback , none >, |
| Row < Playing , pause , Paused , pause_playback , none >, |
| Row < Playing , open_close , Open , stop_and_open , none >, |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| Row < Paused , end_pause , Playing , resume_playback , none >, |
| Row < Paused , stop , Stopped , stop_playback , none >, |
| Row < Paused , open_close , Open , stop_and_open , none > |
| // +---------+------------+-----------+---------------------------+----------------------------+ |
| > {}; |
| </pre><p>Transitions are now of type "Row" with exactly 5 template arguments: |
| source state, event, target state, action and guard. Wherever there is |
| nothing (for example actions and guards), write "none". Actions and guards |
| are no more methods but functors getting as arguments the detected event, |
| the state machine, source and target state:</p><pre class="programlisting">struct store_cd_info |
| { |
| template <class Fsm,class Evt,class SourceState,class TargetState> |
| void operator()(Evt const&, Fsm& fsm, SourceState&,TargetState& ) |
| { |
| cout << "player::store_cd_info" << endl; |
| fsm.process_event(play()); |
| } |
| }; </pre><p>The advantage of functors compared to functions are that functors are |
| generic and reusable. They also allow passing more parameters than just |
| events. The guard functors are the same but have an operator() returning a |
| bool.</p><p>It is also possible to mix rows from different front-ends. To show this, a |
| g_row has been left in the transition table. <span class="underline">Note:</span> in case the action functor is used in the transition |
| table of a state machine contained inside a top-level state machine, the |
| “fsm” parameter refers to the lowest-level state machine (referencing this |
| action), not the top-level one.</p><p>To illustrate the reusable point, MSM comes with a whole set of predefined |
| functors. Please refer to eUML for the <a class="link" href="pt02.html#Reference-begin">full list</a>. For example, we are now going to replace the first |
| action by an action sequence and the guard by a more complex functor.</p><p>We decide we now want to execute two actions in the first transition |
| (Stopped -> Playing). We only need to change the action start_playback to |
| </p><pre class="programlisting">ActionSequence_< mpl::vector<some_action, start_playback> ></pre><p>and |
| now will execute some_action and start_playback every time the transition is |
| taken. ActionSequence_ is a functor calling each action of the mpl::vector |
| in sequence.</p><p>We also want to replace good_disk_format by a condition of the type: |
| “good_disk_format && (some_condition || some_other_condition)”. We |
| can achieve this using And_ and Or_ functors: |
| </p><pre class="programlisting">And_<good_disk_format,Or_< some_condition , some_other_condition> ></pre><p>It |
| even starts looking like functional programming. MSM ships with functors for |
| operators, state machine usage, STL algorithms or container methods.</p></div><div class="sect2" title="Defining states with entry/exit actions"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1263"></a>Defining states with entry/exit actions</h3></div></div></div><p>You probably noticed that we just showed a different transition table and |
| that we even mixed rows from different front-ends. This means that you can |
| do this and leave the definitions for states unchanged. Most examples are |
| doing this as it is the simplest solution. You still enjoy the simplicity of |
| the first front-end with the extended power of the new transition types. |
| This <a class="link" href="examples/SimpleWithFunctors.cpp" target="_top">tutorial</a>, |
| adapted from the earlier example does just this.</p><p>Of course, it is also possible to define states where entry and exit |
| actions are also provided as functors as these are generated by eUML and |
| both front-ends are equivalent. For example, we can define a state |
| as:</p><pre class="programlisting">struct Empty_Entry |
| { |
| template <class Event,class Fsm,class State> |
| void operator()(Event const&,Fsm&,State&) |
| { |
| ... |
| } |
| }; // same for Empty_Exit |
| struct Empty : public msm::front::euml::func_state<Empty_Entry,Empty_Exit>{};</pre><p>This also means that you can, like in the transition table, write entry / |
| exit actions made of more complicated action combinations. The previous |
| example can therefore <a class="link" href="examples/SimpleWithFunctors2.cpp" target="_top">be |
| rewritten</a>.</p><p>Usually, however, one will probably use the standard state definition as |
| it provides the same capabilities as this front-end state definition, unless |
| one needs some of the shipped predefined functors or is a fan of functional |
| programming.</p></div><div class="sect2" title="Defining a simple state machine"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1282"></a>Defining a simple state machine</h3></div></div></div><p>Like states, state machines can be defined using the previous front-end, |
| as the previous example showed, or with the functor front-end, which allows |
| you to define a state machine entry and exit functions as functors, as in |
| <a class="link" href="examples/SimpleWithFunctors2.cpp" target="_top">this |
| example</a>.</p></div><div class="sect2" title="Anonymous transitions"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1290"></a>Anonymous transitions</h3></div></div></div><p>Anonymous (completion) transitions are transitions without a named event. |
| We saw how this front-end uses <code class="code">none</code> when no action or guard is |
| required. We can also use <code class="code">none</code> instead of an event to mark an |
| anonymous transition. For example, the following transition makes an |
| immediate transition from State1 to State2:</p><pre class="programlisting">Row < State1 , none , State2 ></pre><p>The following transition does the same but calling an action in the |
| process:</p><pre class="programlisting">Row < State1 , none , State2 , State1ToState2, none ></pre><p>The following diagram shows an example and its <a class="link" href="examples/AnonymousTutorialWithFunctors.cpp" target="_top">implementation</a>:</p><p><span class="inlinemediaobject"><img src="../images/Anonymous.jpg" width="70%"></span></p></div><div class="sect2" title="Internal transitions"><div class="titlepage"><div><div><h3 class="title"><a name="d0e1316"></a><span class="command"><strong><a name="functor-internal-transitions"></a></strong></span>Internal |
| transitions</h3></div></div></div><p>The <a class="link" href="examples/SimpleTutorialInternalFunctors.cpp" target="_top">following example</a> uses internal transitions with the functor |
| front-end. As for the simple standard front-end, both methods of defining |
| internal transitions are supported:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>providing a <code class="code">Row</code> in the state machine's transition |
| table with <code class="code">none</code> as target state defines an internal |
| transition.</p></li><li class="listitem"><p>providing an <code class="code">internal_transition_table</code> made of |
| <code class="code">Internal</code> rows inside a state or submachine |
| defines UML-conform internal transitions with higher |
| priority.</p></li><li class="listitem"><p>transitions defined inside |
| <code class="code">internal_transition_table</code> require no source or |
| target state as the source state is known (<code class="code">Internal</code> |
| really are <code class="code">Row</code> without a source or target state) |
| .</p></li></ul></div><p>Like for the <span class="command"><strong><a class="command" href="ch03s02.html#internal-transitions-note">standard front-end internal transitions</a></strong></span>, internal transition |
| tables are added into the main state machine's table, thus allowing you to |
| distribute the transition table definition and reuse states.</p><p>There is an added bonus offered for submachines, which can have both the |
| standard transition_table and an internal_transition_table (which has higher |
| priority). This makes it easier if you decide to make a full submachine from |
| a state later. It is also slightly faster than the standard alternative, |
| adding orthogonal regions, because event dispatching will, if accepted by |
| the internal table, not continue to the subregions. This gives you a O(1) |
| dispatch instead of O(number of regions). While the example is with eUML, |
| the same is also possible with this front-end.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch03s02.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="ch03.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ch03s04.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Basic front-end </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> eUML (experimental)</td></tr></table></div></body></html> |