diff --git a/doc/HTML/ch01.html b/doc/HTML/ch01.html index 56a73d5..ac944f3 100644 --- a/doc/HTML/ch01.html +++ b/doc/HTML/ch01.html @@ -1,6 +1,6 @@ - Chapter 1. Founding idea

Chapter 1. Founding idea

Let's start with an example taken from the C++ Template Metaprogramming + Chapter 1. Founding idea

Chapter 1. Founding idea

Let's start with an example taken from the C++ Template Metaprogramming book:

class player : public state_machine<player>

{

// The list of FSM states enum states { Empty, Open, Stopped, Playing, Paused , initial_state = Empty };

// transition actions void start_playback(play const&) { std::cout diff --git a/doc/HTML/ch02.html b/doc/HTML/ch02.html index ab38f5c..83d8967 100644 --- a/doc/HTML/ch02.html +++ b/doc/HTML/ch02.html @@ -1,6 +1,6 @@ - Chapter 2. UML Short Guide

Chapter 2. UML Short Guide

Table of Contents

What are state machines?
Concepts
State machine, state, transition, event
Submachines, orthogonal regions, pseudostates
+ Chapter 2. UML Short Guide

Chapter 2. UML Short Guide

What are state machines?

State machines are the description of a thing's lifeline. They describe the diff --git a/doc/HTML/ch02s02.html b/doc/HTML/ch02s02.html index 98bdb0a..4e4e1fa 100644 --- a/doc/HTML/ch02s02.html +++ b/doc/HTML/ch02s02.html @@ -1,6 +1,6 @@ - Concepts

Concepts

Thinking in terms of state machines is a bit surprising at first, so let us + Concepts

Concepts

Thinking in terms of state machines is a bit surprising at first, so let us have a quick glance at the concepts.

State machine, state, transition, event

A state machine is a concrete model describing the behavior of a system. It is composed of a finite number of states and transitions.

A simple state has no sub states. It can have data, entry and exit diff --git a/doc/HTML/ch02s03.html b/doc/HTML/ch02s03.html index b268dcb..f3ed042 100644 --- a/doc/HTML/ch02s03.html +++ b/doc/HTML/ch02s03.html @@ -1,6 +1,6 @@ - State machine glossary

State machine glossary

+ State machine glossary

State machine glossary

  • state machine: the life cycle of a thing. It is made of states, regions, transitions and processes incoming events.

  • state: a stage in the life cycle of a state machine. A state (like a submachine) can have an entry and exit behaviors.

  • event: an incident provoking (or not) a reaction of the state diff --git a/doc/HTML/ch03.html b/doc/HTML/ch03.html index b0f853e..8bfc1a3 100644 --- a/doc/HTML/ch03.html +++ b/doc/HTML/ch03.html @@ -1,10 +1,10 @@ - Chapter 3. Tutorial

    Chapter 3. Tutorial

    Table of Contents

    Design
    Basic front-end
    A simple example
    Transition table
    Defining states with entry/exit actions
    Defining a simple state machine
    Defining a submachine
    Orthogonal regions, terminate state, event deferring
    History
    Completion (anonymous) transitions
    Internal transitions
    more row types
    Explicit entry / entry and exit pseudo-state / fork
    Flags
    Event Hierarchy
    Customizing a state machine / Getting more speed
    Choosing the initial event
    Containing state machine (deprecated)
    Functor front-end
    Transition table
    Defining states with entry/exit actions
    Defining a simple state machine
    Anonymous transitions
    Internal - transitions
    eUML (experimental)
    Transition table
    Defining events, actions and states with entry/exit actions
    Defining a simple state machine
    Defining a submachine
    - Attributes / Function call
    Orthogonal regions, flags, event deferring
    + Chapter 3. Tutorial

    Chapter 3. Tutorial

    Table of Contents

    Design
    Basic front-end
    A simple example
    Transition table
    Defining states with entry/exit actions
    Defining a simple state machine
    Defining a submachine
    Orthogonal regions, terminate state, event deferring
    History
    Completion (anonymous) transitions
    Internal transitions
    more row types
    Explicit entry / entry and exit pseudo-state / fork
    Flags
    Event Hierarchy
    Customizing a state machine / Getting more speed
    Choosing the initial event
    Containing state machine (deprecated)
    Functor front-end
    Transition table
    Defining states with entry/exit actions
    Defining a simple state machine
    Anonymous transitions
    Internal + transitions
    eUML (experimental)
    Transition table
    Defining events, actions and states with entry/exit actions
    Defining a simple state machine
    Defining a submachine
    + Attributes / Function call
    Orthogonal regions, flags, event deferring
    Customizing a state machine / Getting - more speed
    Completion / Anonymous transitions
    Internal transitions
    Other state types
    Helper functions
    Phoenix-like STL support
    Back-end
    Creation
    Starting a state machine
    Event dispatching
    Active state(s)
    Base state type
    Visitor
    Flags
    Getting a state
    State machine constructor with arguments
    Trading run-time speed for + more speed
    Completion / Anonymous transitions
    Internal transitions
    Other state types
    Helper functions
    Phoenix-like STL support
    Back-end
    Creation
    Starting a state machine
    Event dispatching
    Active state(s)
    Serialization
    Base state type
    Visitor
    Flags
    Getting a state
    State machine constructor with arguments
    Trading run-time speed for better compile-time / multi-TU compilation

    Design

    MSM is divided between front–ends and back-ends. At the moment, there is just one back-end. On the front-end side, you will find three of them which are as many state machine description languages, with many more possible. For potential diff --git a/doc/HTML/ch03s02.html b/doc/HTML/ch03s02.html index fdbd16e..1d03c74 100644 --- a/doc/HTML/ch03s02.html +++ b/doc/HTML/ch03s02.html @@ -1,183 +1,36 @@ - Basic front-end

    Basic front-end

    This is the historical front-end, inherited from the MPL book. It provides a + Basic front-end

    Basic front-end

    This is the historical front-end, inherited from the MPL book. It provides a transition table made of rows of different names and functionality. Actions and guards are defined as methods and referenced through a pointer in the transition. This front-end provides a simple interface making easy state machines easy to define, but more complex state machines a bit harder.

    A simple example

    Let us have a look at a state machine diagram of the founding example:

    We are now going to build it with MSM's basic front-end. An implementation is also provided.

    Transition table

    As previously stated, MSM is based on the transition table, so let us - define one:

    struct transition_table : mpl::vector<

    -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //StartEventNextActionGuard
    //+---------+-------------+---------+---------------------+----------------------+
    a_row <Stopped ,play,Playing,&player_::start_playback >,
    a_row <Stopped ,open_close,Open,&player_::open_drawer >,
    _row <Stopped ,stop,Stopped >,
    //+----------------------+---------+---------------------+----------------------+
    a_row <Open ,open_close ,Empty ,&player_::close_drawer >,
    //+---------+-------------+---------+---------------------+----------------------+
    a_row <Empty ,open_close ,Open ,&player_::open_drawer >,
    row <Empty ,cd_detected ,Stopped ,&player_::store_cd_info ,&player_::good_disk_format>,
    row <Empty ,cd_detected ,Playing ,&player_::store_cd_info ,&player_::auto_start>,
    //+---------+-------------+---------+---------------------+----------------------+
    a_row <Playing ,stop ,Stopped ,&player_::stop_playback >,
    a_row <Playing ,pause ,Paused ,&player_::pause_playback >,
    a_row <Playing ,open_close ,Open ,&player_::stop_and_open >,
    //+---------+-------------+---------+---------------------+----------------------+
    a_row < Paused ,end_pause ,Playing ,&player_::resume_playback >,
    a_row < Paused ,stop ,Stopped ,&player_::stop_playback >,
    a_row < Paused ,open_close ,Open ,&player_::stop_and_open >
    //+---------+-------------+---------+---------------------+----------------------+
    > {};

    -

    You will notice that this is almost exactly our founding example. The only + define one:

     
    +struct transition_table : mpl::vector<
    +//    Start     Event        Target      Action                      Guard 
    +//   +---------+------------+-----------+---------------------------+----------------------------+ 
    +a_row< Stopped , play       ,  Playing  , &player_::start_playback                               >,
    +a_row< Stopped , open_close ,  Open     , &player_::open_drawer                                  >,
    + _row< Stopped , stop       ,  Stopped                                                           >,
    +//   +---------+------------+-----------+---------------------------+----------------------------+ 
    +a_row< Open    , open_close ,  Empty    , &player_::close_drawer                                 >,
    +//   +---------+------------+-----------+---------------------------+----------------------------+ 
    +a_row< Empty   , open_close ,  Open     , &player_::open_drawer                                  >,
    +  row< Empty   , cd_detected,  Stopped  , &player_::store_cd_info   , &player_::good_disk_format >,
    +  row< Empty   , cd_detected,  Playing  , &player_::store_cd_info   , &player_::auto_start       >,
    +//   +---------+------------+-----------+---------------------------+----------------------------+ 
    +a_row< Playing , stop       ,  Stopped  , &player_::stop_playback                                >,
    +a_row< Playing , pause      ,  Paused   , &player_::pause_playback                               >,
    +a_row< Playing , open_close ,  Open     , &player_::stop_and_open                                >,
    +//   +---------+------------+-----------+---------------------------+----------------------------+ 
    +a_row< Paused  , end_pause  ,  Playing  , &player_::resume_playback                              >,
    +a_row< Paused  , stop       ,  Stopped  , &player_::stop_playback                                >,
    +a_row< Paused  , open_close ,  Open     , &player_::stop_and_open                                >
    +//   +---------+------------+-----------+---------------------------+----------------------------+ 
    +> {};
    +                        

    You will notice that this is almost exactly our founding example. The only change in the transition table is the different types of transitions (rows). The founding example forces one to define an action method and offers no guards. You have 4 basic row types:

    • row takes 5 arguments: start state, event, target @@ -194,7 +47,7 @@ #define BOOST_MPL_LIMIT_VECTOR_SIZE 30 //or whatever you need #define BOOST_MPL_LIMIT_MAP_SIZE 30 //or whatever you need

      The other limitation is that the MPL types are defined only up to 50 entries. For the moment, the only solution to achieve more is to add headers - to the MPL (luckily, this is not very complicated).

    Defining states with entry/exit actions

    While states were enums in the MPL book, they now are classes, which + to the MPL (luckily, this is not very complicated).

    Defining states with entry/exit actions

    While states were enums in the MPL book, they now are classes, which allows them to hold data, provide entry, exit behaviors and be reusable (as they do not know anything about the containing state machine). To define a state, inherit from the desired state type. You will mainly use simple @@ -212,7 +65,7 @@ struct Empty : public msm::front::state<> state machine. Being generic facilitates reuse. There are more state types (terminate, interrupt, pseudo states, etc.) corresponding to the UML standard state types. These will be described in details in the next - sections.

    Defining a simple state machine

    Declaring a state machine is straightforward and is done with a high + sections.

    Defining a simple state machine

    Declaring a state machine is straightforward and is done with a high signal / noise ratio. In our player example, we declare the state machine as:

    struct player_ : public msm::front::state_machine_def<player_>{
                                 /* see below */}

    This declares a state machine using the basic front-end. We now declare @@ -248,85 +101,33 @@ void no_transition(Event const& e, Fsm& ,int state){...}

    activate the initial state, which means in turn that the initial state's entry behavior will be called. The reason why we need this will be explained in the back-end part. After a call - to start, the state machine is ready to process events.

    Defining a submachine

    We now want to extend our last state machine by making the Playing state a + to start, the state machine is ready to process events.

    Defining a submachine

    We now want to extend our last state machine by making the Playing state a state machine itself (a submachine).

    Again, an example is also provided.

    A submachine really is a state machine itself, so we declare Playing as such, choosing a front-end and a back-end:

    struct Playing_ : public msm::front::state_machine_def<Playing_>{...} 
     typedef msm::back::state_machine<Playing_> Playing;

    Like for any state machine, one also needs a transition table and an - initial state:

    struct transition_table : mpl::vector<

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //StartEventNextActionGuard
    //+---------+-------------+---------+------------------------------+----------------------+
    a_row <Song1 ,NextSong,Song2,&Playing_::start_next_song >,
    a_row <Song2 ,PreviousSong,Song1,&Playing_::start_prev_song >,
    a_row <Song2 ,NextSong,Song3,&Playing_::start_next_song >,
    a_row <Song3 ,PreviousSong ,Song2 ,&Playing_::start_prev_song >
    //+---------+-------------+---------+------------------------------+----------------------+
    > {};

    + initial state:

    +

     
    +struct transition_table : mpl::vector<
    +//    Start    Event    Target    Action                      Guard 
    +//   +--------+---------+--------+---------------------------+------+ 
    +a_row< Song1  , NextSong, Song2  , &Playing_::start_next_song        >,
    +a_row< Song2  , NextSong, Song1  , &Playing_::start_prev_song        >,
    +a_row< Song2  , NextSong, Song3  , &Playing_::start_next_song        >,
    +a_row< Song3  , NextSong, Song2  , &Playing_::start_prev_song        >
    +//   +--------+---------+--------+---------------------------+------+ 
    +> {};
    +                        

    +

    typedef Song1 initial_state; 

    This is about all you need to do. MSM will now automatically recognize Playing as a submachine and all events handled by Playing (NextSong and PreviousSong) will now be automatically forwarded to Playing whenever this state is active. All other state machine features described later are also available. You can even decide to use a state machine sometimes as - submachine or sometimes as an independent state machine.

    Orthogonal regions, terminate state, event deferring

    It is a very common problem in many state machines to have to handle + submachine or sometimes as an independent state machine.

    Orthogonal regions, terminate state, event deferring

    It is a very common problem in many state machines to have to handle errors. It usually involves defining a transition from all the states to a special error state. Translation: not fun. It is also not practical to find from which state the error originated. The following diagram shows an @@ -402,7 +203,7 @@ typedef msm::back::state_machine<Playing_> Playing;

    (condition1) defer play event":

    Row   < Empty , play , none    , Defer , condition1   >,
     g_row < Empty , play , Playing , &player_::condition2 >

    -

    Please have a look at this possible implementation.

    History

    UML defines two types of history, Shallow History and Deep History. In the +

    Please have a look at this possible implementation.

    History

    UML defines two types of history, Shallow History and Deep History. In the previous examples, if the player was playing the second song and the user pressed pause, leaving Playing, at the next press on the play button, the Playing state would become active and the first song would play again. Soon @@ -449,7 +250,7 @@ g_row < Empty , play , Playing , &player_::condition2 >

    be added). The reason is that it would conflict with policies which submachines could define. Of course, if for example, Song1 were a state machine itself, it could use the ShallowHistory policy itself thus creating - Deep History for itself. An example is also provided.

    Completion (anonymous) transitions

    The following diagram shows an + Deep History for itself. An example is also provided.

    Completion (anonymous) transitions

    The following diagram shows an example making use of this feature:

    Anonymous transitions are transitions without a named event. This means that the transition automatically fires when the predecessor state is entered (to be exact, after the entry action). Otherwise it is a normal @@ -476,7 +277,7 @@ g_row < Empty , play , Playing , &player_::condition2 >

    for example:

    row < State3 , none , State4 , &p::State3ToState4 , &p::always_true >

    An implementation - of the state machine diagram is also provided.

    Internal transitions

    Internal transitions are transitions executing in the scope of the active + of the state machine diagram is also provided.

    Internal transitions

    Internal transitions are transitions executing in the scope of the active state, a simple state or a submachine. One can see them as a self-transition of this state, without an entry or exit action called. This is useful when all you want is to execute some code for a given event in a given @@ -541,7 +342,7 @@ g_row < Empty , play , Playing , &player_::condition2 >

    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 any front-end.

    more row types

    It is also possible to write transitions using actions and guards not just + with eUML, the same is also possible with any front-end.

    more row types

    It is also possible to write transitions using actions and guards not just from the state machine but also from its contained states. In this case, one must specify not just a method pointer but also the object on which to call it. This transition row is called, not very originally, row2. @@ -558,7 +359,7 @@ g_row < Empty , play , Playing , &player_::condition2 >

    sections.

    These row types allow us to distribute the state machine code among states, making them reusable and more useful. Using transition tables inside states also contributes to this possibility. An example of these new - rows is also provided.

    Explicit entry / entry and exit pseudo-state / fork

    MSM (almost) fully supports these features, described in the small UML tutorial. Almost because + rows is also provided.

    Explicit entry / entry and exit pseudo-state / fork

    MSM (almost) fully supports these features, described in the small UML tutorial. Almost because there are currently two limitations:

    • it is only possible to explicitly enter a sub- state of the target but not a sub-sub state.

    • it is not possible to explicitly exit. Exit points must be used.

    Let us see a concrete example:

    We find in this diagram:

    • A “normal” activation of SubFsm2, triggered by event1. In each @@ -578,7 +379,7 @@ g_row < Empty , play , Playing , &player_::condition2 >

      transition and both regions are exited, as SubFsm2 becomes inactive. Note that if no transition is defined from PseudoExit1, an error (as defined in the UML standard) will be - detected and no_transition called.

    The example is also fully implemented.

    This sounds complicated but the syntax is simple.

    Explicit entry

    First, to define that a state is an explicit entry, you have to make + detected and no_transition called.

The example is also fully implemented.

This sounds complicated but the syntax is simple.

Explicit entry

First, to define that a state is an explicit entry, you have to make it a state and mark it as explicit, giving as template parameters the region id (the region id starts with 0 and corresponds to the first initial state of the initial_state type sequence).

@@ -610,7 +411,7 @@ g_row < Empty , play , Playing , &player_::condition2 >

Note (also valid for forks): At the moment, it is not possible to use a submachine as the target of an explicit entry. Please use entry pseudo states for an almost identical - effect.

Fork

Need a fork instead of an explicit entry? As a fork is an explicit + effect.

Fork

Need a fork instead of an explicit entry? As a fork is an explicit entry into states of different regions, we do not change the state definition compared to the explicit entry and specify as target a list of explicit entry states:

@@ -623,7 +424,7 @@ g_row < Empty , play , Playing , &player_::condition2 >

correct):

struct SubState2b : public msm::front::state<> , 
                     public msm::front::explicit_entry<1>

-

Entry pseudo states

To define an entry pseudo state, you need derive from the +

Entry pseudo states

To define an entry pseudo state, you need derive from the corresponding class and give the region id:

struct PseudoEntry1 : public msm::front::entry_pseudo_state<0>

And add the corresponding transition in the top-level state machine's @@ -633,7 +434,7 @@ g_row < Empty , play , Playing , &player_::condition2 >

defines an entry point as a connection between two transitions), for example this time with an action method:

_row < PseudoEntry1, Event4, SubState3,&SubFsm2_::entry_action >

-

Exit pseudo states

And finally, exit pseudo states are to be used almost the same way, +

Exit pseudo states

And finally, exit pseudo states are to be used almost the same way, but defined differently: it takes as template argument the event to be forwarded (no region id is necessary):

struct PseudoExit1 : public exit_pseudo_state<event6>

@@ -664,7 +465,7 @@ g_row < Empty , play , Playing , &player_::condition2 >

template <class Event> event6(Event const&){} }; //convertible from any event

-

Flags

This tutorial is devoted to a +

Flags

This tutorial is devoted to a concept not defined in UML: flags. It has been added into MSM after proving itself useful on many occasions. Please, do not be frightened as we are not talking about ugly shortcuts made of an improbable collusion of @@ -696,7 +497,7 @@ g_row < Empty , play , Playing , &player_::condition2 >

all of the active states are flagged for the state to be active. You can also AND the active states:

if (p.is_flag_active<CDLoaded,player::Flag_AND>()) ...

-

The following diagram displays the flag situation in the tutorial.

Event Hierarchy

There are cases where one needs transitions based on categories of events. +

The following diagram displays the flag situation in the tutorial.

Event Hierarchy

There are cases where one needs transitions based on categories of events. An example is text parsing. Let's say you want to parse a string and use a state machine to manage your parsing state. You want to parse 4 digits and decide to use a state for every matched digit. Your state machine could look @@ -709,7 +510,7 @@ struct char_0 : public digit {};

And to the same for other digits, we c and this will cause a transition with "digit" as trigger to be taken.

An example with performance measurement, taken from the documentation of Boost.Xpressive illustrates this example. You might notice that the performance is actually - very good (in this case even better).

Customizing a state machine / Getting more speed

MSM is offering many UML features at a high-speed, but sometimes, you just + very good (in this case even better).

Customizing a state machine / Getting more speed

MSM is offering many UML features at a high-speed, but sometimes, you just need more speed and are ready to give up some features in exchange. A process_event is handling several tasks:

  • checking for terminate/interrupt states

  • handling the message queue (for entry/exit/transition actions generating themselves events)

  • handling deferred events

  • catching exceptions (or not)

  • handling the state switching and action calls

Of these tasks, only the last one is absolutely necessary to @@ -735,7 +536,7 @@ struct char_0 : public digit {};

And to the same for other digits, we c };

Important note: As exit pseudo states are using the message queue to forward events out of a submachine, the no_message_queue option cannot be used with state machines - containing an exit pseudo state.

Choosing the initial event

A state machine is started using the start method. This + containing an exit pseudo state.

Choosing the initial event

A state machine is started using the start method. This causes the initial state's entry behavior to be executed. Like every entry behavior, it becomes as parameter the event causing the state to be entered. But when the machine starts, there was no event triggered. In this case, MSM @@ -747,7 +548,7 @@ struct char_0 : public digit {};

And to the same for other digits, we c struct player_ : public msm::front::state_machine_def<player_>{ ... typedef my_initial_event initial_event; -};

Containing state machine (deprecated)

This feature is still supported in MSM for backward compatibility but made +};

Containing state machine (deprecated)

This feature is still supported in MSM for backward compatibility but made obsolete by the fact that every guard/action/entry action/exit action get the state machine passed as argument and might be removed at a later time.

All of the states defined in the state machine are created upon state diff --git a/doc/HTML/ch03s03.html b/doc/HTML/ch03s03.html index 8f20b5b..91be570 100644 --- a/doc/HTML/ch03s03.html +++ b/doc/HTML/ch03s03.html @@ -1,6 +1,6 @@ - Functor front-end

Functor front-end

The functor front-end is the preferred front-end at the moment. It is more + Functor front-end

Functor front-end

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 eUML, it also comes with a good deal of predefined actions. Actually, eUML generates a functor front-end through @@ -11,178 +11,31 @@ means syntactic noise and more to learn.

  • Function pointers are weird in C++.

  • The action/guard signature is limited and does not allow for more variations of parameters (source state, target state, current state machine, etc.)

  • It is not easy to reuse action code from a state machine to - another.

  • Transition table

    We can change the definition of the simple tutorial's transition table - to:

    -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //StartEventNextActionGuard
    //+---------+-------------+---------+---------------------+----------------------+
    Row <Stopped ,play,Playing,start_playback >,
    Row <Stopped ,open_close,Open,open_drawer, none>,
    Row <Stopped ,stop,Stopped, none>,
    //+----------------------+---------+---------------------+----------------------+
    Row <Open ,open_close ,Empty ,close_drawer, none>,
    //+---------+-------------+---------+---------------------+----------------------+
    Row <Empty ,open_close ,Open ,open_drawer >,
    Row <Empty ,cd_detected ,Stopped ,store_cd_info ,good_disk_format>,
    g_row <Empty ,cd_detected ,Playing ,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>
    //+---------+-------------+---------+---------------------+----------------------+
    > {};

    -

    Transitions are now of type "Row" with exactly 5 template arguments: + another.

    Transition table

    We can change the definition of the simple tutorial's transition table + to:

     
    +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                       >
    +//   +---------+------------+-----------+---------------------------+----------------------------+ 
    +> {};
    +                        

    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, @@ -213,7 +66,7 @@ can achieve this using And_ and Or_ functors:

    And_<good_disk_format,Or_< some_condition , some_other_condition> >

    It even starts looking like functional programming. MSM ships with functors for - operators, state machine usage, STL algorithms or container methods.

    Defining states with entry/exit actions

    You probably noticed that we just showed a different transition table and + operators, state machine usage, STL algorithms or container methods.

    Defining states with entry/exit actions

    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 @@ -236,16 +89,16 @@ struct Empty : public msm::front::euml::func_state<Empty_Entry,Empty_Exit> rewritten.

    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.

    Defining a simple state machine

    Like states, state machines can be defined using the previous front-end, + programming.

    Defining a simple state machine

    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 this - example.

    Anonymous transitions

    Anonymous (completion) transitions are transitions without a named event. + example.

    Anonymous transitions

    Anonymous (completion) transitions are transitions without a named event. We saw how this front-end uses none when no action or guard is required. We can also use none instead of an event to mark an anonymous transition. For example, the following transition makes an immediate transition from State1 to State2:

    Row < State1 , none , State2 >

    The following transition does the same but calling an action in the - process:

    Row < State1 , none , State2 , State1ToState2, none >

    The following diagram shows an example and its implementation:

    Internal + process:

    Row < State1 , none , State2 , State1ToState2, none >

    The following diagram shows an example and its implementation:

    Internal transitions

    The following example uses internal transitions with the functor front-end. As for the simple standard front-end, both methods of defining internal transitions are supported:

    • providing a Row in the state machine's transition diff --git a/doc/HTML/ch03s04.html b/doc/HTML/ch03s04.html index 4538182..996e12b 100644 --- a/doc/HTML/ch03s04.html +++ b/doc/HTML/ch03s04.html @@ -1,11 +1,8 @@ - eUML (experimental)

      eUML (experimental)

      Important note: eUML requires a compiler - supporting the C++0x decltype/typeof feature (for example VC >= 9, g++ >= 4.3. - VC8 supports eUML but will crash with middle-size state machines). More - generally, eUML has experimental status because most compilers will start - crashing when a state machine becomes too big. Only g++ 4.3 (unfortunately not - 4.4 which shows a serious regression) seems perfectly resilient.

      The previous front-ends are simple to write but still force an amount of + eUML (experimental)

      eUML (experimental)

      Important note: eUML requires a compiler + supporting Boost.Typeof. More generally, eUML has experimental status because + most compilers will start crashing when a state machine becomes too big.

      The previous front-ends are simple to write but still force an amount of noise, mostly MPL types, so it would be nice to write code looking like C++ (with a C++ action language) directly inside the transition table, like UML designers like to do on their state machine diagrams. If it were functional @@ -22,80 +19,27 @@

      #include <msm/front/euml/euml.hpp>

      To add STL support (at possible cost of longer compilation times), include:

      #include <msm/front/euml/stl.hpp>

      -

      eUML is defined in the namespace msm::front::euml.

      Transition table

      A transition can be defined using eUML as:

      +

      eUML is defined in the namespace msm::front::euml.

      Transition table

      A transition can be defined using eUML as:

      source + event [guard] / action == target

      or as

      target == source + event [guard] / action

      The first version looks like a drawn transition in a diagram, the second - one seems natural to a C++ developer.

      The simple transition table written with the previous front-end can now be - written as:

      -

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      BOOST_MSM_EUML_TRANSITION_TABLE((
      Stopped +play [DummyGuard] / (TestFct,start_playback)== Playing
      Stopped +open_close/ open_drawer== Open
      Stopped +stop== Stopped
      Open +open_close / close_drawer== Empty
      Empty +open_close / open_drawer == Open
      Empty +cd_detected [good_disk_format] / store_cd_info == Stopped
      ),transition_table)

      -

      Or, using the alternative notation, it can be:

      -

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      BOOST_MSM_EUML_TRANSITION_TABLE((
      Playing == Stopped +play [DummyGuard] / (TestFct,start_playback)
      Open ==Stopped +open_close/ open_drawer
      Stopped ==Stopped +stop
      Empty ==Open +open_close / close_drawer
      Open ==Empty +open_close / open_drawer
      Stopped ==Empty +cd_detected [good_disk_format] / store_cd_info
      ),transition_table)

      -

      The transition table now looks like a list of (readable) rules with little + one seems natural to a C++ developer.

      The simple transition table written with the functor front-end can now be + written as:

      BOOST_MSM_EUML_TRANSITION_TABLE(( 
      +Stopped + play [some_guard] / (some_action , start_playback)  == Playing ,
      +Stopped + open_close/ open_drawer                             == Open    ,
      +Stopped + stop                                                == Stopped ,
      +Open    + open_close / close_drawer                           == Empty   ,
      +Empty   + open_close / open_drawer                            == Open    ,
      +Empty   + cd_detected [good_disk_format] / store_cd_info      == Stopped
      +),transition_table)                       

      Or, using the alternative notation, it can be:

      BOOST_MSM_EUML_TRANSITION_TABLE(( 
      +Playing  == Stopped + play [some_guard] / (some_action , start_playback) ,
      +Open     == Stopped + open_close/ open_drawer                            ,
      +Stopped  == Stopped + stop                                               ,
      +Empty    == Open    + open_close / close_drawer                          ,
      +Open     == Empty   + open_close / open_drawer                           ,
      +Stopped  == Empty   + cd_detected [good_disk_format] / store_cd_info
      +),transition_table)           

      The transition table now looks like a list of (readable) rules with little noise.

      UML defines guards between “[ ]” and actions after a “/”, so the chosen syntax is already more readable for UML designers. UML also allows designers to define several actions sequentially (our previous ActionSequence_) @@ -111,7 +55,7 @@ [good_disk_format && (some_condition || some_other_condition)]. This was possible with our previously defined functors, but using a complicated template syntax. This syntax is now possible exactly as written, which means - without any syntactic noise at all.

      Defining events, actions and states with entry/exit actions

      Events

      Events must be proto-enabled. To achieve this, they must inherit from + without any syntactic noise at all.

      Defining events, actions and states with entry/exit actions

      Events

      Events must be proto-enabled. To achieve this, they must inherit from a proto terminal (euml_event<event-name>). eUML also provides a macro to make this easier:

      BOOST_MSM_EUML_EVENT(play)

      @@ -126,7 +70,7 @@ fsm.process_event(play()); or do we have to write: fsm.process_event(play);

      The answer is you can do both. The second one is easier but unlike other front-ends, the second uses a defined operator(), which creates an - event on the fly.

      Actions

      Actions (returning void) and guards (returning a bool) are defined + event on the fly.

      Actions

      Actions (returning void) and guards (returning a bool) are defined like previous functors, with the difference that they also must be proto-enabled. This can be done by inheriting from euml_action< functor-name >. eUML also provides a macro:

      BOOST_MSM_EUML_ACTION(some_condition)
      @@ -144,7 +88,20 @@
       {
           template <class Evt,class Fsm,class State>
           void operator()(Evt const& ,Fsm& ,State& ) { ... }                           
      -}; 

      States

      There is also a macro for states. This macro has 2 arguments, first + };

      It is also possible to reuse the functors from the functor front-end. + The syntax is however slightly less comfortable as we need to pretend + creating one on the fly for typeof. For example:

      struct start_playback 
      +{
      +        template <class Fsm,class Evt,class SourceState,class TargetState>
      +        void operator()(Evt const& ,Fsm&,SourceState& ,TargetState& )
      +        {
      +         ...            
      +        }
      +};
      +BOOST_MSM_EUML_TRANSITION_TABLE((
      +Playing   == Stopped  + play        / start_playback() ,
      +...
      +),transition_table)

      States

      There is also a macro for states. This macro has 2 arguments, first the expression defining the state, then the state (instance) name:

      BOOST_MSM_EUML_STATE((),Paused)

      This defines a simple state without entry or exit action. You can provide in the expression parameter the state behaviors (entry and exit) @@ -185,7 +142,7 @@ Empty_impl const Empty;

      Notice also that we defined a method named activ could use with the functor front-end, the second is the state method name, the third is the eUML-generated function, the fourth and fifth the return value when used inside a transition or a state behavior. You can - now use this inside a transition:

      Empty == Open + open_close / (close_drawer,activate_empty_(target_))

      Defining a simple state machine

      You can reuse the state machine definition method from the standard + now use this inside a transition:

      Empty == Open + open_close / (close_drawer,activate_empty_(target_))

      Defining a simple state machine

      You can reuse the state machine definition method from the standard front-end and simply replace the transition table by this new one. You can also use eUML to define a state machine "on the fly" (if, for example, you need to provide an on_entry/on_exit for this state machine as a functor). @@ -209,22 +166,13 @@ Empty_impl const Empty;

      Notice also that we defined a method named activ capabilities (no message queue / no exception catching) are added and a non-default base state (see the back-end description) is defined.

    For example, a minimum state machine could be defined - as:

    -

    - - - - - - - -
    BOOST_MSM_EUML_TRANSITION_TABLE((
    ),transition_table)

    -

    BOOST_MSM_EUML_DECLARE_STATE_MACHINE((transition_table,init_ << Empty ),
    +                        as:

    BOOST_MSM_EUML_TRANSITION_TABLE(( 
    +),transition_table)                       
    BOOST_MSM_EUML_DECLARE_STATE_MACHINE((transition_table,init_ << Empty ),
                                          player_)

    Please have a look at the player tutorial written using eUML's first and second syntax. The BOOST_MSM_EUML_DECLARE_ATTRIBUTE macro, to which we will get back shortly, declares attributes given to an eUML type (state or event) using the attribute - syntax.

    Defining a submachine

    Defining a submachine (see tutorial) with + syntax.

    Defining a submachine

    Defining a submachine (see tutorial) with other front-ends simply means using a state which is a state machine in the transition table of another state machine. This is the same with eUML. One only needs define a second state machine and reference it in the transition @@ -235,7 +183,7 @@ Empty_impl const Empty;

    Notice also that we defined a method named activ machine, for example:

    BOOST_MSM_EUML_DECLARE_STATE_MACHINE(...,Playing_)
     typedef msm::back::state_machine<Playing_> Playing_type;
     Playing_type const Playing;

    We can now use this instance inside the transition table of the containing - state machine:

    Paused == Playing + pause / pause_playback

    + state machine:

    Paused == Playing + pause / pause_playback

    Attributes / Function call

    We now want to make our grammar more useful. Very often, one needs only very simple action methods, for example ++Counter or Counter > 5 where Counter is usually defined as some attribute of the class containing the @@ -289,7 +237,7 @@ BOOST_MSM_EUML_DECLARE_ATTRIBUTE(DiskTypeEnum,cd_type)

    This declares two This method could also have an (or several) argument(s), for example the event, we could then call activate_empty_(target_ , event_).

    More examples can be found in the terrible compiler stress test, the timer example or in the iPodSearch with eUML - (for String_ and more).

    Orthogonal regions, flags, event deferring

    Defining orthogonal regions really means providing more initial states. To + (for String_ and more).

    Orthogonal regions, flags, event deferring

    Defining orthogonal regions really means providing more initial states. To add more initial states, “shift left” some, for example, if we had another initial state named AllOk :

    BOOST_MSM_EUML_DECLARE_STATE_MACHINE((transition_table,
                                          init_ << Empty << AllOk ),
    @@ -341,7 +289,7 @@ BOOST_MSM_EUML_DECLARE_ATTRIBUTE(DiskTypeEnum,cd_type)

    This declares two attributes_ << no_attributes_, configure_<< deferred_events ), player_)

    A tutorial - illustrates this possibility.

    + illustrates this possibility.

    Customizing a state machine / Getting more speed

    We just saw how to use configure_ to define deferred events or flags. We can also use it to configure our state machine like we did with the other front-ends:

    • configure_ << no_exception: disables @@ -353,7 +301,7 @@ BOOST_MSM_EUML_DECLARE_ATTRIBUTE(DiskTypeEnum,cd_type)

      This declares two with eUML does this for the best performance.

      Important note: As exit pseudo states are using the message queue to forward events out of a submachine, the no_message_queue option cannot be used with state machines - containing an exit pseudo state.

    Completion / Anonymous transitions

    Anonymous transitions (See UML + containing an exit pseudo state.

    Completion / Anonymous transitions

    Anonymous transitions (See UML tutorial) are transitions without a named event, which are therefore triggered immediately when the source state becomes active, provided a guard allows it. As there is no event, to define such a @@ -361,7 +309,7 @@ BOOST_MSM_EUML_DECLARE_ATTRIBUTE(DiskTypeEnum,cd_type)

    This declares two example:

    State3 == State4 [always_true] / State3ToState4
     State4 [always_true] / State3ToState4 == State3

    Please have a look at this example, which implements the previously - defined state machine with eUML.

    Internal transitions

    Like both other front-ends, eUML supports two ways of defining internal transitions:

    • in the state machine's transition table. In this case, you + defined state machine with eUML.

    Internal transitions

    Like both other front-ends, eUML supports two ways of defining internal transitions:

    • in the state machine's transition table. In this case, you need to specify a source state, event, actions and guards but no target state, which eUML will interpret as an internal transition, for example this defines a transition internal to @@ -382,7 +330,7 @@ struct Open_impl : public Open_def 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).

    Other state types

    We saw the build_state + instead of O(number of regions).

    Other state types

    We saw the build_state function, which creates a simple state. Likewise, eUML provides other state-building macros for other types of states:

    • BOOST_MSM_EUML_TERMINATE_STATE takes the same arguments as BOOST_MSM_EUML_STATE and defines, well, a terminate @@ -422,7 +370,7 @@ struct Open_impl : public Open_def

      entry_pt_(SubFsm2,PseudoEntry1) == State1 + event4

      For exit points, it is again the same syntax except that exit points are used as source of the transition:

      State2 == exit_pt_(SubFsm2,PseudoExit1) + event6 

      The entry tutorial - is also available with eUML.

    Helper functions

    We saw a few helpers but there are more, so let us have a more complete description:

    • event_ : used inside any action, the event triggering the + is also available with eUML.

    Helper functions

    We saw a few helpers but there are more, so let us have a more complete description:

    • event_ : used inside any action, the event triggering the transition

    • state_: used inside entry and exit actions, the entered / exited state

    • source_: used inside a transition action, the source state

    • target_: used inside a transition action, the target @@ -459,7 +407,7 @@ struct Open_impl : public Open_def MSM_EUML_METHOD or MSM_EUML_FUNCTION will create a correct functor. Your own eUML functors written as described at the beginning of this section will also work well, except, for the - moment, with the while_, if_then_, if_then_else_ functions.

    Phoenix-like STL support

    eUML supports most C++ operators (except address-of). For example it is + moment, with the while_, if_then_, if_then_else_ functions.

    Phoenix-like STL support

    eUML supports most C++ operators (except address-of). For example it is possible to write event_(some_attribute)++ or [source_(some_bool) && fsm_(some_other_bool)]. But a programmer needs more than operators in his daily programming. The STL is clearly a must have. Therefore, eUML comes in diff --git a/doc/HTML/ch03s05.html b/doc/HTML/ch03s05.html index ce4d4ce..f795e1a 100644 --- a/doc/HTML/ch03s05.html +++ b/doc/HTML/ch03s05.html @@ -1,6 +1,6 @@ - Back-end

    Back-end

    There is, at the moment, one back-end. This back-end contains the library + Back-end

    Back-end

    There is, at the moment, one back-end. This back-end contains the library engine and defines the performance and functionality trade-offs. The currently available back-end implements most of the functionality defined by the UML 2.0 standard at very high runtime speed, in exchange for longer compile-time. The @@ -8,18 +8,18 @@ capabilities allowing the framework to adapt itself to the features used by a given concrete state machine. All unneeded features either disable themselves or can be manually disabled. See section 5.1 for a complete description of the - run-to-completion algorithm.

    Creation

    MSM being divided between front and back-end, one needs to first define a + run-to-completion algorithm.

    Creation

    MSM being divided between front and back-end, one needs to first define a front-end. Then, to create a real state machine, the back-end must be declared:

    typedef msm::back::state_machine<my_front_end> my_fsm;

    We now have a fully functional state machine type. The next sections will - describe what can be done with it.

    Starting a state machine

    The start method starts the state machine, meaning it will + describe what can be done with it.

    Starting a state machine

    The start method starts the state machine, meaning it will activate the initial state, which means in turn that the initial state's entry behavior will be called. We need the start method because you do not always want the entry behavior of the initial state to be called immediately but only when your state machine is ready to process events. A good example of this is when you use a state machine to write an algorithm and each loop back to the initial state is an algorithm call. Each call to start will make - the algorithm run once. The iPodSearch example uses this possibility.

    Event dispatching

    The main reason to exist for a state machine is to dispatch events. For + the algorithm run once. The iPodSearch example uses this possibility.

    Event dispatching

    The main reason to exist for a state machine is to dispatch events. For MSM, events are objects of a given event type. The object itself can contain data, but the event type is what decides of the transition to be taken. For MSM, if some_event is a given type (a simple struct for example) and e1 and @@ -30,14 +30,80 @@ an event of type some_event, you can simply create one on the fly or instantiate if before processing:

    my_fsm fsm; fsm.process_event(some_event());
     some_event e1; fsm.process_event(e1)

    Creating an event on the fly will be optimized by the compiler so the - performance will not degrade.

    Active state(s)

    The backend also offers a way to know which state is active, though you + performance will not degrade.

    Active state(s)

    The backend also offers a way to know which state is active, though you will normally only need this for debugging purposes. If what you need simply is doing something with the active state, internal transitions or visitors are a better alternative. If you need to know what state is active, const int* current_state() will return an array of state ids. Please refer to the internals section to - know how state ids are generated.

    Base state type

    Sometimes, one needs to customize states to avoid repetition and provide a + know how state ids are generated.

    Serialization

    A common need is the ability to save a state machine and restore it at a + different time. MSM supports this feature for the basic and functor + front-ends, and in a more limited manner for eUML. MSM supports + boost::serialization out of the box (by offering a serialize + function). Actually, for basic serialization, you need not do much, a MSM + state machine is serializable almost like any other type. Without any + special work, you can make a state machine remember its state, for + example:

    +

    MyFsm fsm;
    +// write to archive
    +std::ofstream ofs("fsm.txt");
    +// save fsm to archive
    +{
    +    boost::archive::text_oarchive oa(ofs);
    +    // write class instance to archive
    +    oa << fsm;
    +}                                                  

    +

    Loading back is very similar:

    +

    MyFsm fsm;
    +{
    +    // create and open an archive for input
    +    std::ifstream ifs("fsm.txt");
    +    boost::archive::text_iarchive ia(ifs);
    +    // read class state from archive
    +    ia >> fsm;
    +}                                          

    +

    This will (de)serialize the state machine itself but not the concrete + states' data. This can be done on a per-state basis to reduce the amount of + typing necessary. To allow serialization of a concrete state, provide a + do_serialize typedef and implement the serialize function:

    +

    struct Empty : public msm::front::state<> 
    +{
    +    // we want Empty to be serialized. First provide the typedef
    +    typedef int do_serialize;
    +    // then implement serialize
    +    template<class Archive>
    +    void serialize(Archive & ar, const unsigned int /* version */)
    +    {
    +        ar & some_dummy_data;
    +    }
    +    Empty():some_dummy_data(0){}           
    +    int some_dummy_data;
    +};                        

    +

    You can also serialize data contained in the front-end class. Again, you + need to provide the typedef and implement serialize:

    +

    struct player_ : public msm::front::state_machine_def<player_>
    +{
    +    //we might want to serialize some data contained by the front-end
    +    int front_end_data;
    +    player_():front_end_data(0){}
    +    // to achieve this, provide the typedef
    +    typedef int do_serialize;
    +    // and implement serialize
    +    template<class Archive>
    +    void serialize(Archive & ar, const unsigned int )
    +    {
    +        ar & front_end_data;
    +    }  
    +...
    +};                                               

    +

    The saving of the back-end data (the current state(s)) is valid for all + front-ends, so a front-end written using eUML can be serialized. However, to + serialize a concrete state, the macros like + BOOST_MSM_EUML_STATE cannot be used, so the state will have + to be implemented by directly inheriting from + front::euml::euml_state.

    This example shows a state machine which we serialize after processing an + event. The Empty state also has some data to serialize.

    Base state type

    Sometimes, one needs to customize states to avoid repetition and provide a common functionality, for example in the form of a virtual method. You might also want to make your states polymorphic so that you can call typeid on them for logging or debugging. It is also useful if you need a visitor, like @@ -60,7 +126,7 @@ some_event e1; fsm.process_event(e1)

    Creating an event on the fly will b

    struct player_ : public msm::front::state_machine<player_,my_base_state>             

    You can also ask for a state with a given id (which you might have gotten from current_state()) using const base_state* get_state_by_id(int id) const where base_state is the one you just defined. You can now - do something polymorphically.

    Visitor

    In some cases, having a pointer-to-base of the currently active states is + do something polymorphically.

    Visitor

    In some cases, having a pointer-to-base of the currently active states is not enough. You might want to call non-virtually a method of the currently active states. It will not be said that MSM forces the virtual keyword down your throat!

    To achieve this goal, MSM provides its own variation of a visitor pattern @@ -99,18 +165,18 @@ struct my_visitable_state the accept function is to contain a parameter passed by reference, pass this parameter with a boost:ref/cref to avoid undesired copies or slicing. So, for example, in the above case, call:

    SomeVisitor vis; sm.visit_current_states(boost::ref(vis));

    This example uses a - visiting function with 2 arguments.

    Flags

    Flags is a MSM-only concept, supported by all front-ends, which base + visiting function with 2 arguments.

    Flags

    Flags is a MSM-only concept, supported by all front-ends, which base themselves on the functions:

    template <class Flag> bool is_flag_active()
     template <class Flag,class BinaryOp> bool is_flag_active()

    These functions return true if the currently active state(s) support the Flag property. The first variant ORs the result if there are several orthogonal regions, the second one expects OR or AND, for example:

    my_fsm.is_flag_active<MyFlag>()
    -my_fsm.is_flag_active<MyFlag,my_fsm_type::Flag_OR>()

    Please refer to the front-ends sections for usage examples.

    Getting a state

    It is sometimes necessary to have the client code get access to the +my_fsm.is_flag_active<MyFlag,my_fsm_type::Flag_OR>()

    Please refer to the front-ends sections for usage examples.

    Getting a state

    It is sometimes necessary to have the client code get access to the states' data. After all, the states are created once for good and hang around as long as the state machine does so why not use it? You simply just need sometimes to get information about any state, even inactive ones. An example is if you want to write a coverage tool and know how many times a state was visited. To get a state, use the get_state method giving the state - name, for example:

    player::Stopped* tempstate = p.get_state<player::Stopped*>();

    or

    player::Stopped& tempstate2 = p.get_state<player::Stopped&>();

    depending on your personal taste.

    State machine constructor with arguments

    You might want to define a state machine with a non-default constructor. + name, for example:

    player::Stopped* tempstate = p.get_state<player::Stopped*>();

    or

    player::Stopped& tempstate2 = p.get_state<player::Stopped&>();

    depending on your personal taste.

    State machine constructor with arguments

    You might want to define a state machine with a non-default constructor. For example, you might want to write:

    struct player_ : public msm::front::state_machine_def<player_> 
     { 
         player_(int some_value){…} 
    @@ -126,7 +192,7 @@ my_fsm.is_flag_active<MyFlag,my_fsm_type::Flag_OR>()

    Please refer typedef msm::back::state_machine<player_ > player; SomeType data; player p(boost::ref(data),3); -

    Trading run-time speed for +

    Trading run-time speed for better compile-time / multi-TU compilation

    MSM is optimized for run-time speed at the cost of longer compile-time. This can become a problem with older compilers and big state machines, especially if you don't really care about run-time speed that much and would diff --git a/doc/HTML/ch04.html b/doc/HTML/ch04.html index 3ca0b64..0a5c49e 100644 --- a/doc/HTML/ch04.html +++ b/doc/HTML/ch04.html @@ -1,6 +1,6 @@ - Chapter 4.  Performance / Compilers

    Chapter 4.  Performance / Compilers

    Tests were made on different PCs running Windows XP and Vista and compiled with + Chapter 4.  Performance / Compilers

    Chapter 4.  Performance / Compilers

    Tests were made on different PCs running Windows XP and Vista and compiled with VC9 SP1 or Ubuntu and compiled with g++ 4.2 and 4.3. For these tests, the same player state machine was written using Boost.Statechart, as a state machine with only simple states and as a state machine with a composite @@ -9,5 +9,5 @@ the simple one also with functors and with eUML. As these simple machines need no terminate/interrupt states, no message queue and have no-throw guarantee on their actions, the MSM state machines are defined with minimum functionality. Test machine is a Q6600 2.4GHz, Vista - 64.

    Speed

    VC9:

    • The simple test completes 90 times faster with MSM than with + 64.

      Speed

      VC9:

      • The simple test completes 90 times faster with MSM than with Boost.Statechart

      • The composite test completes 25 times faster with MSM

      gcc 4.2.3 (Ubuntu 8.04 in VMWare, same PC):

      • The simple test completes 46 times faster with MSM

      • The composite test completes 19 times faster with Msm

    \ No newline at end of file diff --git a/doc/HTML/ch04s02.html b/doc/HTML/ch04s02.html index b1fa02a..6e55664 100644 --- a/doc/HTML/ch04s02.html +++ b/doc/HTML/ch04s02.html @@ -1,6 +1,6 @@ - Executable size

    Executable size

    There are some worries that MSM generates huge code. Is it true? The 2 + Executable size

    Executable size

    There are some worries that MSM generates huge code. Is it true? The 2 compilers I tested disagree with this claim. On VC9, the test state machines used in the performance section produce executables of 14kB (for simple and eUML) and 21kB (for the composite). This includes the test code and iostreams. diff --git a/doc/HTML/ch04s03.html b/doc/HTML/ch04s03.html index 2ca1f80..a6175f0 100644 --- a/doc/HTML/ch04s03.html +++ b/doc/HTML/ch04s03.html @@ -1,9 +1,7 @@ - Supported compilers

    Supported compilers

    MSM was successfully tested with:

    • VC8 (please read further), VC9SP1, VC10 Beta 1 and 2

    • g++ 4.1 and higher

    • Green Hills Software MULTI for ARM v5.0.5 patch 4416 (Simple and - Composite tutorials)

    eUML will only work with:

    • VC8 (partly). You cannot, however use any overloaded function - (like splice) and compile times and RAM consumption explode

    • VC9SP1, VC10 Beta1-2

    • g++ 4.3 and higher (previous versions lack native typeof - support)

    VC8 and to some lesser extent VC9 suffer from a bug. Enabling the option + Supported compilers

    Supported compilers

    For a current status, have a look at the regression tests.

    MSM was successfully tested with:

    • VC8 (partly), VC9, VC10

    • g++ 4.0.1 and higher

    • Intel 10.1 and higher

    • Clang 2.9

    • Green Hills Software MULTI for ARM v5.0.5 patch 4416 (Simple and + Composite tutorials)

    • Partial support for IBM compiler

    VC8 and to some lesser extent VC9 suffer from a bug. Enabling the option "Enable Minimal Rebuild" (/Gm) will cause much higher compile-time (up to three times with VC8!). This option being activated per default in Debug mode, this can be a big problem.

    \ No newline at end of file diff --git a/doc/HTML/ch04s04.html b/doc/HTML/ch04s04.html index 8eb48c4..823a489 100644 --- a/doc/HTML/ch04s04.html +++ b/doc/HTML/ch04s04.html @@ -1,15 +1,15 @@ - Limitations

    Limitations

    + Limitations

    Limitations

    • Compilation times of state machines with > 80 transitions that are going to make you storm the CFO's office and make sure you get a shiny octocore with 12GB RAM by next week, unless he's interested in paying you watch the compiler agonize for hours... (Make sure you ask for dual 24" as well, it doesn't hurt).

    • eUML allows very long constructs but will also quickly increase - your compile time on some compilers (VC9, VC10 Beta1) with buggy - decltype support (I suspect some at least quadratic algorithms - there). Even g++ 4.4 shows some regression compared to 4.3 and will - crash if the constructs become too big.

    • Need to overwrite the mpl::vector/list default-size-limit of 20 + your compile time on some compilers (VC9, VC10) with buggy decltype + support (I suspect some at least quadratic algorithms there). Even + g++ 4.4 shows some regression compared to 4.3 and will crash if the + constructs become too big.

    • Need to overwrite the mpl::vector/list default-size-limit of 20 and fusion default vector size of 10 if more than 10 states found in a state machine

    \ No newline at end of file diff --git a/doc/HTML/ch04s05.html b/doc/HTML/ch04s05.html index 232b9f8..551ddf8 100644 --- a/doc/HTML/ch04s05.html +++ b/doc/HTML/ch04s05.html @@ -1,6 +1,6 @@ - Compilers corner

    Compilers corner

    Compilers are sometimes full of surprises and such strange errors happened in + Compilers corner

    Compilers corner

    Compilers are sometimes full of surprises and such strange errors happened in the course of the development that I wanted to list the most fun for readers’ entertainment.

    VC8:

    template <class StateType>
     typename ::boost::enable_if<
    diff --git a/doc/HTML/ch05.html b/doc/HTML/ch05.html
    index 27986d7..dcff80f 100644
    --- a/doc/HTML/ch05.html
    +++ b/doc/HTML/ch05.html
    @@ -1,6 +1,6 @@
     
           
    -   Chapter 5. Questions & Answers

    Chapter 5. Questions & Answers

    Question: on_entry gets as argument, the + Chapter 5. Questions & Answers

    Chapter 5. Questions & Answers

    Question: on_entry gets as argument, the sent event. What event do I get when the state becomes default-activated (because it is an initial state)?

    Answer: To allow you to know that the state diff --git a/doc/HTML/ch06.html b/doc/HTML/ch06.html index 2698ee1..83d5b3c 100644 --- a/doc/HTML/ch06.html +++ b/doc/HTML/ch06.html @@ -1,9 +1,9 @@ - Chapter 6. Internals

    Chapter 6. Internals

    Table of Contents

    Backend: Run To Completion
    Frontend / Backend + Chapter 6. Internals

    Chapter 6. Internals

    This chapter describes the internal machinery of the back-end, which can be useful for UML experts but can be safely ignored for most users. For implementers, the - interface between front- and back- end is also described in detail.

    Backend: Run To Completion

    The back-end implements the following run-to completion algorithm:

    • Check if one region of the concrete state machine is in a + interface between front- and back- end is also described in detail.

      Backend: Run To Completion

      The back-end implements the following run-to completion algorithm:

      • Check if one region of the concrete state machine is in a terminate or interrupt state. If yes, event processing is disabled while the condition lasts (forever for a terminate pseudo-state, while active for an interrupt pseudo-state).

      • If the message queue feature is enabled and if the state machine diff --git a/doc/HTML/ch06s02.html b/doc/HTML/ch06s02.html index 8122a84..54e26c1 100644 --- a/doc/HTML/ch06s02.html +++ b/doc/HTML/ch06s02.html @@ -1,7 +1,7 @@ - Frontend / Backend interface

        Frontend / Backend + Frontend / Backend interface

        Frontend / Backend interface

        The design of MSM tries to make front-ends and back-ends (later) to be as interchangeable as possible. Of course, no back-end will ever implement every feature defined by any possible front-end and inversely, but the goal is to make diff --git a/doc/HTML/ch06s03.html b/doc/HTML/ch06s03.html index c4fa1a1..c0c394b 100644 --- a/doc/HTML/ch06s03.html +++ b/doc/HTML/ch06s03.html @@ -1,6 +1,6 @@ - Generated state ids

        Generated state ids

        Normally, one does not need to know the ids are generated for all the states + Generated state ids

        Generated state ids

        Normally, one does not need to know the ids are generated for all the states of a state machine, unless for debugging purposes, like the pstate function does in the tutorials in order to display the name of the current state. This section will show how to automatically display typeid-generated names, but these are not diff --git a/doc/HTML/ch06s04.html b/doc/HTML/ch06s04.html index a8dce88..1587ee6 100644 --- a/doc/HTML/ch06s04.html +++ b/doc/HTML/ch06s04.html @@ -1,6 +1,6 @@ - Metaprogramming tools

        Metaprogramming tools

        We can find for the transition table more uses than what we have seen so far. + Metaprogramming tools

        Metaprogramming tools

        We can find for the transition table more uses than what we have seen so far. Let's suppose you need to write a coverage tool. A state machine would be perfect for such a job, if only it could provide some information about its structure. Thanks to the transition table and Boost.MPL, it does.

        What is needed for a coverage tool? You need to know how many states are diff --git a/doc/HTML/ch07.html b/doc/HTML/ch07.html index 066b9f2..e87432c 100644 --- a/doc/HTML/ch07.html +++ b/doc/HTML/ch07.html @@ -1,6 +1,6 @@ - Chapter 7. Acknowledgements

        Chapter 7. Acknowledgements

        Table of Contents

        MSM v2
        MSM v1

        I am in debt to the following people who helped MSM along the way.

        MSM v2

        + Chapter 7. Acknowledgements

        Chapter 7. Acknowledgements

        Table of Contents

        MSM v2
        MSM v1

        I am in debt to the following people who helped MSM along the way.

        MSM v2

        • Thanks to Dave Abrahams for managing the review

        • Thanks to Eric Niebler for his patience correcting my grammar errors

        • Special thanks to Joel de Guzman who gave me very good ideas at the BoostCon09. These ideas were the starting point of the redesign. diff --git a/doc/HTML/ch07s02.html b/doc/HTML/ch07s02.html index cd76f12..cbaf5ff 100644 --- a/doc/HTML/ch07s02.html +++ b/doc/HTML/ch07s02.html @@ -1,6 +1,6 @@ - MSM v1

          MSM v1

          + MSM v1

          MSM v1

          • The original version of this framework is based on the brilliant work of David Abrahams and Aleksey Gurtovoy who laid down the base and the principles of the framework in their excellent book, “C++ diff --git a/doc/HTML/ch08.html b/doc/HTML/ch08.html index d90477a..149f355 100644 --- a/doc/HTML/ch08.html +++ b/doc/HTML/ch08.html @@ -1,9 +1,7 @@ - Chapter 8. Version history

            Chapter 8. Version history

            Table of Contents

            From V2.0 to V2.10

            From V2.0 to V2.10

            -

            • New documentation

            • Internal transitions. Either as part of the transition table or - using a state's internal transition table

            • increased dispatch and copy speed

            • new row types for the - basic front-end

            • new eUML syntax, better attribute support, macros to ease - developer's life. Even VC8 seems to like it better.

            • New policy for reduced compile-time at the cost of dispatch - speed

            • Support for base events

            • possibility to choose the initial event

            -

            \ No newline at end of file + Chapter 8. Version history

            Chapter 8. Version history

            From V2.10 to V2.12

            +

            +

            \ No newline at end of file diff --git a/doc/HTML/ch08s02.html b/doc/HTML/ch08s02.html new file mode 100644 index 0000000..a66d6ab --- /dev/null +++ b/doc/HTML/ch08s02.html @@ -0,0 +1,9 @@ + + + From V2.0 to V2.12

            From V2.0 to V2.12

            +

            • New documentation

            • Internal transitions. Either as part of the transition table or + using a state's internal transition table

            • increased dispatch and copy speed

            • new row types for the + basic front-end

            • new eUML syntax, better attribute support, macros to ease + developer's life. Even VC8 seems to like it better.

            • New policy for reduced compile-time at the cost of dispatch + speed

            • Support for base events

            • possibility to choose the initial event

            +

            \ No newline at end of file diff --git a/doc/HTML/ch09.html b/doc/HTML/ch09.html index 533c3f2..2fed11d 100644 --- a/doc/HTML/ch09.html +++ b/doc/HTML/ch09.html @@ -1,7 +1,7 @@ - Chapter 9. eUML operators and basic helpers

            Chapter 9. eUML operators and basic helpers

            The following table lists the supported operators:

            -

            Table 9.1. Operators and state machine helpers

            eUML function / operatorDescriptionFunctor
            &&Calls lazily Action1&& Action2And_
            ||Calls lazily Action1|| Action2Or_
            !Calls lazily !Action1Not_
            !=Calls lazily Action1 != Action2NotEqualTo_
            ==Calls lazily Action1 == Action2EqualTo_
            >Calls lazily Action1 > Action2Greater_
            >=Calls lazily Action1 >= Action2Greater_Equal_
            <Calls lazily Action1 < Action2Less_
            <=Calls lazily Action1 <= Action2Less_Equal_
            &Calls lazily Action1 & Action2Bitwise_And_
            |Calls lazily Action1 | Action2Bitwise_Or_
            ^Calls lazily Action1 ^ Action2Bitwise_Xor_
            --Calls lazily --Action1 / Action1--Pre_Dec_ / Post_Dec_
            ++Calls lazily ++Action1 / Action1++Pre_Inc_ / Post_Inc_
            /Calls lazily Action1 / Action2Divides_
            /=Calls lazily Action1 /= Action2Divides_Assign_
            *Calls lazily Action1 * Action2Multiplies_
            *=Calls lazily Action1 *= Action2Multiplies_Assign_
            + (binary)Calls lazily Action1 + Action2Plus_
            + (unary)Calls lazily +Action1Unary_Plus_
            +=Calls lazily Action1 += Action2Plus_Assign_
            - (binary)Calls lazily Action1 - Action2Minus_
            - (unary)Calls lazily -Action1Unary_Minus_
            -=Calls lazily Action1 -= Action2Minus_Assign_
            %Calls lazily Action1 % Action2Modulus_
            %=Calls lazily Action1 %= Action2Modulus_Assign_
            >>Calls lazily Action1 >> Action2ShiftRight_
            >>=Calls lazily Action1 >>= Action2ShiftRight_Assign_
            <<Calls lazily Action1 << Action2ShiftLeft_
            <<=Calls lazily Action1 <<= Action2ShiftLeft_Assign_
            [] (works on vector, map, arrays)Calls lazily Action1 [Action2]Subscript_
            if_then_else_(Condition,Action1,Action2)Returns either the result of calling Action1 or the result of + Chapter 9. eUML operators and basic helpers

            Chapter 9. eUML operators and basic helpers

            The following table lists the supported operators:

            +

            Table 9.1. Operators and state machine helpers

            eUML function / operatorDescriptionFunctor
            &&Calls lazily Action1&& Action2And_
            ||Calls lazily Action1|| Action2Or_
            !Calls lazily !Action1Not_
            !=Calls lazily Action1 != Action2NotEqualTo_
            ==Calls lazily Action1 == Action2EqualTo_
            >Calls lazily Action1 > Action2Greater_
            >=Calls lazily Action1 >= Action2Greater_Equal_
            <Calls lazily Action1 < Action2Less_
            <=Calls lazily Action1 <= Action2Less_Equal_
            &Calls lazily Action1 & Action2Bitwise_And_
            |Calls lazily Action1 | Action2Bitwise_Or_
            ^Calls lazily Action1 ^ Action2Bitwise_Xor_
            --Calls lazily --Action1 / Action1--Pre_Dec_ / Post_Dec_
            ++Calls lazily ++Action1 / Action1++Pre_Inc_ / Post_Inc_
            /Calls lazily Action1 / Action2Divides_
            /=Calls lazily Action1 /= Action2Divides_Assign_
            *Calls lazily Action1 * Action2Multiplies_
            *=Calls lazily Action1 *= Action2Multiplies_Assign_
            + (binary)Calls lazily Action1 + Action2Plus_
            + (unary)Calls lazily +Action1Unary_Plus_
            +=Calls lazily Action1 += Action2Plus_Assign_
            - (binary)Calls lazily Action1 - Action2Minus_
            - (unary)Calls lazily -Action1Unary_Minus_
            -=Calls lazily Action1 -= Action2Minus_Assign_
            %Calls lazily Action1 % Action2Modulus_
            %=Calls lazily Action1 %= Action2Modulus_Assign_
            >>Calls lazily Action1 >> Action2ShiftRight_
            >>=Calls lazily Action1 >>= Action2ShiftRight_Assign_
            <<Calls lazily Action1 << Action2ShiftLeft_
            <<=Calls lazily Action1 <<= Action2ShiftLeft_Assign_
            [] (works on vector, map, arrays)Calls lazily Action1 [Action2]Subscript_
            if_then_else_(Condition,Action1,Action2)Returns either the result of calling Action1 or the result of calling Action2If_Else_
            if_then_(Condition,Action)Returns the result of calling Action if ConditionIf_Then_
            while_(Condition, Body)While Condition(), calls Body(). Returns nothingWhile_Do_
            do_while_(Condition, Body)Calls Body() while Condition(). Returns nothingDo_While_
            for_(Begin,Stop,EndLoop,Body)Calls for(Begin;Stop;EndLoop){Body;}For_Loop_
            process_(Event [,fsm1] [,fsm2] [,fsm3] [,fsm4])Processes Event on the current state machine (if no fsm specified) or on up to 4 state machines returned by an appropriate functor.Process_
            process2_(Event, Data [,fsm1] [,fsm2] [,fsm3])Processes Event on the current state machine (if no fsm diff --git a/doc/HTML/ch10.html b/doc/HTML/ch10.html index 019616f..514d0e9 100644 --- a/doc/HTML/ch10.html +++ b/doc/HTML/ch10.html @@ -1,33 +1,33 @@ - Chapter 10.  Functional programming

            Chapter 10.  + Chapter 10.  Functional programming

            Chapter 10.  Functional programming

            To use these functions, you need to include:

            #include <msm/front/euml/stl.hpp>

            or the specified header in the following tables.

            The following tables list the supported STL algorithms:

            -

            Table 10.1. STL algorithms

            STL algorithms in querying.hppFunctor
            find_(first, last, value)Find_
            find_if_(first, last, value)FindIf_
            lower_bound_(first, last, value [,opᵃ])LowerBound_
            upper_bound_(first, last, value [,opᵃ])UpperBound_
            equal_range_(first, last, value [,opᵃ])EqualRange_
            binary_search_(first, last, value [,opᵃ])BinarySearch_
            min_element_(first, last[,opᵃ])MinElement_
            max_element_(first, last[,opᵃ])MaxElement_
            adjacent_find_(first, last[,opᵃ])AdjacentFind_
            find_end_( first1, last1, first2, last2 [,op ᵃ])FindEnd_
            find_first_of_( first1, last1, first2, last2 [,op ᵃ])FindFirstOf_
            equal_( first1, last1, first2 [,op ᵃ])Equal_
            search_( first1, last1, first2, last2 [,op ᵃ])Search_
            includes_( first1, last1, first2, last2 [,op ᵃ])Includes_
            lexicographical_compare_ ( first1, last1, first2, last2 [,op +

            Table 10.1. STL algorithms

            STL algorithms in querying.hppFunctor
            find_(first, last, value)Find_
            find_if_(first, last, value)FindIf_
            lower_bound_(first, last, value [,opᵃ])LowerBound_
            upper_bound_(first, last, value [,opᵃ])UpperBound_
            equal_range_(first, last, value [,opᵃ])EqualRange_
            binary_search_(first, last, value [,opᵃ])BinarySearch_
            min_element_(first, last[,opᵃ])MinElement_
            max_element_(first, last[,opᵃ])MaxElement_
            adjacent_find_(first, last[,opᵃ])AdjacentFind_
            find_end_( first1, last1, first2, last2 [,op ᵃ])FindEnd_
            find_first_of_( first1, last1, first2, last2 [,op ᵃ])FindFirstOf_
            equal_( first1, last1, first2 [,op ᵃ])Equal_
            search_( first1, last1, first2, last2 [,op ᵃ])Search_
            includes_( first1, last1, first2, last2 [,op ᵃ])Includes_
            lexicographical_compare_ ( first1, last1, first2, last2 [,op ᵃ]) LexicographicalCompare_
            count_(first, last, value [,size])Count_
            count_if_(first, last, op ᵃ [,size])CountIf_
            distance_(first, last)Distance_
            mismatch _( first1, last1, first2 [,op ᵃ])Mismatch_


            -

            Table 10.2. STL algorithms

            STL algorithms in iteration.hppFunctor
            for_each_(first,last, unary opᵃ)ForEach_
            accumulate_first, last, init [,opᵃ])Accumulate_


            +

            Table 10.2. STL algorithms

            STL algorithms in iteration.hppFunctor
            for_each_(first,last, unary opᵃ)ForEach_
            accumulate_first, last, init [,opᵃ])Accumulate_


            -

            Table 10.3. STL algorithms

            STL algorithms in transformation.hppFunctor
            copy_(first, last, result)Copy_
            copy_backward_(first, last, result)CopyBackward_
            reverse_(first, last)Reverse_
            reverse_copy_(first, last , result)ReverseCopy_
            remove_(first, last, value)Remove_
            remove_if_(first, last , opᵃ)RemoveIf_
            remove_copy_(first, last , output, value)RemoveCopy_
            remove_copy_if_(first, last, output, opᵃ)RemoveCopyIf_
            fill_(first, last, value)Fill_
            fill_n_(first, size, value)ᵇFillN_
            generate_(first, last, generatorᵃ)Generate_
            generate_(first, size, generatorᵃ)ᵇGenerateN_
            unique_(first, last [,opᵃ])Unique_
            unique_copy_(first, last, output [,opᵃ])UniqueCopy_
            random_shuffle_(first, last [,opᵃ])RandomShuffle_
            rotate_copy_(first, middle, last, output)RotateCopy_
            partition_ (first, last [,opᵃ])Partition_
            stable_partition_ (first, last [,opᵃ])StablePartition_
            stable_sort_(first, last [,opᵃ])StableSort_
            sort_(first, last [,opᵃ])Sort_
            partial_sort_(first, middle, last [,opᵃ])PartialSort_
            partial_sort_copy_ (first, last, res_first, res_last [,opᵃ]) PartialSortCopy_
            nth_element_(first, nth, last [,opᵃ])NthElement_
            merge_( first1, last1, first2, last2, output [,op ᵃ])Merge_
            inplace_merge_(first, middle, last [,opᵃ])InplaceMerge_
            set_union_(first1, last1, first2, last2, output [,op +

            Table 10.3. STL algorithms

            STL algorithms in transformation.hppFunctor
            copy_(first, last, result)Copy_
            copy_backward_(first, last, result)CopyBackward_
            reverse_(first, last)Reverse_
            reverse_copy_(first, last , result)ReverseCopy_
            remove_(first, last, value)Remove_
            remove_if_(first, last , opᵃ)RemoveIf_
            remove_copy_(first, last , output, value)RemoveCopy_
            remove_copy_if_(first, last, output, opᵃ)RemoveCopyIf_
            fill_(first, last, value)Fill_
            fill_n_(first, size, value)ᵇFillN_
            generate_(first, last, generatorᵃ)Generate_
            generate_(first, size, generatorᵃ)ᵇGenerateN_
            unique_(first, last [,opᵃ])Unique_
            unique_copy_(first, last, output [,opᵃ])UniqueCopy_
            random_shuffle_(first, last [,opᵃ])RandomShuffle_
            rotate_copy_(first, middle, last, output)RotateCopy_
            partition_ (first, last [,opᵃ])Partition_
            stable_partition_ (first, last [,opᵃ])StablePartition_
            stable_sort_(first, last [,opᵃ])StableSort_
            sort_(first, last [,opᵃ])Sort_
            partial_sort_(first, middle, last [,opᵃ])PartialSort_
            partial_sort_copy_ (first, last, res_first, res_last [,opᵃ]) PartialSortCopy_
            nth_element_(first, nth, last [,opᵃ])NthElement_
            merge_( first1, last1, first2, last2, output [,op ᵃ])Merge_
            inplace_merge_(first, middle, last [,opᵃ])InplaceMerge_
            set_union_(first1, last1, first2, last2, output [,op ᵃ])SetUnion_
            push_heap_(first, last [,op ᵃ])PushHeap_
            pop_heap_(first, last [,op ᵃ])PopHeap_
            make_heap_(first, last [,op ᵃ])MakeHeap_
            sort_heap_(first, last [,op ᵃ])SortHeap_
            next_permutation_(first, last [,op ᵃ])NextPermutation_
            prev_permutation_(first, last [,op ᵃ])PrevPermutation_
            inner_product_(first1, last1, first2, init [,op1ᵃ] [,op2ᵃ]) InnerProduct_
            partial_sum_(first, last, output [,opᵃ])PartialSum_
            adjacent_difference_(first, last, output [,opᵃ])AdjacentDifference_
            replace_(first, last, old_value, new_value)Replace_
            replace_if_(first, last, opᵃ, new_value)ReplaceIf_
            replace_copy_(first, last, result, old_value, new_value)ReplaceCopy_
            replace_copy_if_(first, last, result, opᵃ, new_value)ReplaceCopyIf_
            rotate_(first, middle, last)ᵇRotate_


            -

            Table 10.4. STL container methods

            STL container methods(common) in container.hppFunctor
            container::reference front_(container)Front_
            container::reference back_(container)Back_
            container::iterator begin_(container)Begin_
            container::iterator end_(container)End_
            container::reverse_iterator rbegin_(container)RBegin_
            container::reverse_iterator rend_(container)REnd_
            void push_back_(container, value)Push_Back_
            void pop_back_(container, value)Pop_Back_
            void push_front_(container, value)Push_Front_
            void pop_front_(container, value)Pop_Front_
            void clear_(container)Clear_
            size_type capacity_(container)Capacity_
            size_type size_(container)Size_
            size_type max_size_(container)Max_Size_
            void reserve_(container, value)Reserve _
            void resize_(container, value)Resize _
            iterator insert_(container, pos, value)Insert_
            void insert_( container , pos, first, last)Insert_
            void insert_( container , pos, number, value)Insert_
            void swap_( container , other_container)Swap_
            void erase_( container , pos)Erase_
            void erase_( container , first, last) Erase_
            bool empty_( container)Empty_


            +

            Table 10.4. STL container methods

            STL container methods(common) in container.hppFunctor
            container::reference front_(container)Front_
            container::reference back_(container)Back_
            container::iterator begin_(container)Begin_
            container::iterator end_(container)End_
            container::reverse_iterator rbegin_(container)RBegin_
            container::reverse_iterator rend_(container)REnd_
            void push_back_(container, value)Push_Back_
            void pop_back_(container, value)Pop_Back_
            void push_front_(container, value)Push_Front_
            void pop_front_(container, value)Pop_Front_
            void clear_(container)Clear_
            size_type capacity_(container)Capacity_
            size_type size_(container)Size_
            size_type max_size_(container)Max_Size_
            void reserve_(container, value)Reserve _
            void resize_(container, value)Resize _
            iterator insert_(container, pos, value)Insert_
            void insert_( container , pos, first, last)Insert_
            void insert_( container , pos, number, value)Insert_
            void swap_( container , other_container)Swap_
            void erase_( container , pos)Erase_
            void erase_( container , first, last) Erase_
            bool empty_( container)Empty_


            -

            Table 10.5. STL list methods

            std::list methods in container.hppFunctor
            void list_remove_(container, value)ListRemove_
            void list_remove_if_(container, opᵃ)ListRemove_If_
            void list_merge_(container, other_list)ListMerge_
            void list_merge_(container, other_list, opᵃ)ListMerge_
            void splice_(container, iterator, other_list)Splice_
            void splice_(container, iterator, other_list, +

            Table 10.5. STL list methods

            std::list methods in container.hppFunctor
            void list_remove_(container, value)ListRemove_
            void list_remove_if_(container, opᵃ)ListRemove_If_
            void list_merge_(container, other_list)ListMerge_
            void list_merge_(container, other_list, opᵃ)ListMerge_
            void splice_(container, iterator, other_list)Splice_
            void splice_(container, iterator, other_list, iterator)Splice_
            void splice_(container, iterator, other_list, first, last)Splice_
            void list_reverse_(container)ListReverse_
            void list_unique_(container)ListUnique_
            void list_unique_(container, opᵃ)ListUnique_
            void list_sort_(container)ListSort_
            void list_sort_(container, opᵃ)ListSort_


            -

            Table 10.6. STL associative container methods

            Associative container methods in container.hppFunctor
            iterator insert_(container, pos, value)Insert_
            void insert_( container , first, last)Insert_
            pair<iterator, bool> insert_( container , value)Insert_
            void associative_erase_( container , pos)Associative_Erase_
            void associative_erase_( container , first, last)Associative_Erase_
            size_type associative_erase_( container , key)Associative_Erase_
            iterator associative_find_( container , key)Associative_Find_
            size_type associative_count_( container , key)AssociativeCount_
            iterator associative_lower_bound_( container , key)Associative_Lower_Bound_
            iterator associative_upper_bound_( container , key)Associative_Upper_Bound_
            pair<iterator, iterator> associative_equal_range_( +

            Table 10.6. STL associative container methods

            Associative container methods in container.hppFunctor
            iterator insert_(container, pos, value)Insert_
            void insert_( container , first, last)Insert_
            pair<iterator, bool> insert_( container , value)Insert_
            void associative_erase_( container , pos)Associative_Erase_
            void associative_erase_( container , first, last)Associative_Erase_
            size_type associative_erase_( container , key)Associative_Erase_
            iterator associative_find_( container , key)Associative_Find_
            size_type associative_count_( container , key)AssociativeCount_
            iterator associative_lower_bound_( container , key)Associative_Lower_Bound_
            iterator associative_upper_bound_( container , key)Associative_Upper_Bound_
            pair<iterator, iterator> associative_equal_range_( container , key)Associative_Equal_Range_


            -

            Table 10.7. STL pair

            std::pair in container.hppFunctor
            first_type first_(pair<T1, T2>)First_
            second_type second_(pair<T1, T2>)Second_


            +

            Table 10.7. STL pair

            std::pair in container.hppFunctor
            first_type first_(pair<T1, T2>)First_
            second_type second_(pair<T1, T2>)Second_


            -

            Table 10.8. STL string

            STL string methodstd::string method in container.hppFunctor
            substr (size_type pos, size_type size)string substr_(container, pos, length)Substr_
            int compare(string)int string_compare_(container, another_string)StringCompare_
            int compare(char*)int string_compare_(container, another_string)StringCompare_
            int compare(size_type pos, size_type size, string)int string_compare_(container, pos, size, +

            Table 10.8. STL string

            STL string methodstd::string method in container.hppFunctor
            substr (size_type pos, size_type size)string substr_(container, pos, length)Substr_
            int compare(string)int string_compare_(container, another_string)StringCompare_
            int compare(char*)int string_compare_(container, another_string)StringCompare_
            int compare(size_type pos, size_type size, string)int string_compare_(container, pos, size, another_string)StringCompare_
            int compare (size_type pos, size_type size, string, size_type length)int string_compare_(container, pos, size, another_string, length)StringCompare_
            string& append(const string&)string& append_(container, another_string)Append_
            string& append (charT*)string& append_(container, another_string)Append_
            string& append (string , size_type pos, size_type diff --git a/doc/HTML/examples/Serialize.cpp b/doc/HTML/examples/Serialize.cpp new file mode 100644 index 0000000..dc72c59 --- /dev/null +++ b/doc/HTML/examples/Serialize.cpp @@ -0,0 +1,248 @@ +#include +// back-end +#include +//front-end +#include + +// include headers that implement a archive in simple text format +#include +#include +#include + +#include + + +namespace msm = boost::msm; +namespace mpl = boost::mpl; + + +namespace +{ + // events + struct play {}; + struct end_pause {}; + struct stop {}; + struct pause {}; + struct open_close {}; + + // A "complicated" event type that carries some data. + enum DiskTypeEnum + { + DISK_CD=0, + DISK_DVD=1 + }; + struct cd_detected + { + cd_detected(std::string name, DiskTypeEnum diskType) + : name(name), + disc_type(diskType) + {} + + std::string name; + DiskTypeEnum disc_type; + }; + + // front-end: define the FSM structure + struct player_ : public msm::front::state_machine_def + { + //we might want to serialize some data contained by the front-end + int front_end_data; + player_():front_end_data(0){} + // to achieve this, ask for it + typedef int do_serialize; + // and provide a serialize + template + void serialize(Archive & ar, const unsigned int ) + { + ar & front_end_data; + } + // The list of FSM states + struct Empty : public msm::front::state<> + { + // we want Empty to be serialized + typedef int do_serialize; + template + void serialize(Archive & ar, const unsigned int ) + { + ar & some_dummy_data; + } + Empty():some_dummy_data(0){} + // every (optional) entry/exit methods get the event passed. + template + void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "leaving: Empty" << std::endl;} + int some_dummy_data; + }; + struct Open : public msm::front::state<> + { + template + void on_entry(Event const& ,FSM&) {std::cout << "entering: Open" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "leaving: Open" << std::endl;} + }; + + // sm_ptr still supported but deprecated as functors are a much better way to do the same thing + struct Stopped : public msm::front::state + { + template + void on_entry(Event const& ,FSM&) {std::cout << "entering: Stopped" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "leaving: Stopped" << std::endl;} + void set_sm_ptr(player_* pl) + { + m_player=pl; + } + player_* m_player; + }; + + struct Playing : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {std::cout << "entering: Playing" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "leaving: Playing" << std::endl;} + }; + + // state not defining any entry or exit + struct Paused : public msm::front::state<> + { + }; + + // the initial state of the player SM. Must be defined + typedef Empty initial_state; + + // transition actions + void start_playback(play const&) { std::cout << "player::start_playback\n"; } + void open_drawer(open_close const&) { std::cout << "player::open_drawer\n"; } + void close_drawer(open_close const&) { std::cout << "player::close_drawer\n"; } + void store_cd_info(cd_detected const&) { std::cout << "player::store_cd_info\n"; } + void stop_playback(stop const&) { std::cout << "player::stop_playback\n"; } + void pause_playback(pause const&) { std::cout << "player::pause_playback\n"; } + void resume_playback(end_pause const&) { std::cout << "player::resume_playback\n"; } + void stop_and_open(open_close const&) { std::cout << "player::stop_and_open\n"; } + void stopped_again(stop const&) {std::cout << "player::stopped_again\n";} + // guard conditions + bool good_disk_format(cd_detected const& evt) + { + // to test a guard condition, let's say we understand only CDs, not DVD + if (evt.disc_type != DISK_CD) + { + std::cout << "wrong disk, sorry" << std::endl; + return false; + } + return true; + } + // used to show a transition conflict. This guard will simply deactivate one transition and thus + // solve the conflict + bool auto_start(cd_detected const&) + { + return false; + } + + typedef player_ p; // makes transition table cleaner + + // Transition table for player + struct transition_table : mpl::vector< + // Start Event Next Action Guard + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Stopped , play , Playing , &p::start_playback >, + a_row < Stopped , open_close , Open , &p::open_drawer >, + _row < Stopped , stop , Stopped >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Open , open_close , Empty , &p::close_drawer >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Empty , open_close , Open , &p::open_drawer >, + row < Empty , cd_detected , Stopped , &p::store_cd_info ,&p::good_disk_format >, + row < Empty , cd_detected , Playing , &p::store_cd_info ,&p::auto_start >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Playing , stop , Stopped , &p::stop_playback >, + a_row < Playing , pause , Paused , &p::pause_playback >, + a_row < Playing , open_close , Open , &p::stop_and_open >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Paused , end_pause , Playing , &p::resume_playback >, + a_row < Paused , stop , Stopped , &p::stop_playback >, + a_row < Paused , open_close , Open , &p::stop_and_open > + // +---------+-------------+---------+---------------------+----------------------+ + > {}; + // Replaces the default no-transition response. + template + void no_transition(Event const& e, FSM&,int state) + { + std::cout << "no transition from state " << state + << " on event " << typeid(e).name() << std::endl; + } + }; + // Pick a back-end + typedef msm::back::state_machine player; + + // + // Testing utilities. + // + static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" }; + void pstate(player const& p) + { + std::cout << " -> " << state_names[p.current_state()[0]] << std::endl; + } + + void test() + { + player p; + // needed to start the highest-level SM. This will call on_entry and mark the start of the SM + p.start(); + p.get_state().some_dummy_data=3; + p.front_end_data=4; + + // go to Open, call on_exit on Empty, then action, then on_entry on Open + p.process_event(open_close()); pstate(p); + + std::ofstream ofs("fsm.txt"); + // save fsm to archive (current state is Open) + { + boost::archive::text_oarchive oa(ofs); + // write class instance to archive + oa << p; + } + // reload fsm in state Open + player p2; + { + // create and open an archive for input + std::ifstream ifs("fsm.txt"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> p2; + } + // we now use p2 as it was loaded + // check that we kept Empty's data value + std::cout << "Empty's data should be 3:" << p2.get_state().some_dummy_data << std::endl; + std::cout << "front-end data should be 4:" << p2.front_end_data << std::endl; + + p2.process_event(open_close()); pstate(p2); + // will be rejected, wrong disk type + p2.process_event( + cd_detected("louie, louie",DISK_DVD)); pstate(p2); + p2.process_event( + cd_detected("louie, louie",DISK_CD)); pstate(p2); + p2.process_event(play()); + + // at this point, Play is active + p2.process_event(pause()); pstate(p2); + // go back to Playing + p2.process_event(end_pause()); pstate(p2); + p2.process_event(pause()); pstate(p2); + p2.process_event(stop()); pstate(p2); + // event leading to the same state + // no action method called as it is not present in the transition table + p2.process_event(stop()); pstate(p2); + } +} +// eliminate object tracking (even if serialized through a pointer) +// at the risk of a programming error creating duplicate objects. +// this is to get rid of warning because p is not const +BOOST_CLASS_TRACKING(player, boost::serialization::track_never) + +int main() +{ + test(); + return 0; +} diff --git a/doc/HTML/examples/SerializeCompositeAndHistory.cpp b/doc/HTML/examples/SerializeCompositeAndHistory.cpp new file mode 100644 index 0000000..9699ab1 --- /dev/null +++ b/doc/HTML/examples/SerializeCompositeAndHistory.cpp @@ -0,0 +1,266 @@ +// Copyright 2010 Christophe Henry +// henry UNDERSCORE christophe AT hotmail DOT com +// This is an extended version of the state machine available in the boost::mpl library +// Distributed under the same license as the original. +// Copyright for the original version: +// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed +// under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +// back-end +#include +//front-end +#include + +// include headers that implement a archive in simple text format +#include +#include +#include + +#include + +namespace msm = boost::msm; +namespace mpl = boost::mpl; + +namespace +{ + // events + struct play {}; + struct end_pause {}; + struct stop {}; + struct pause {}; + struct open_close {}; + struct NextSong {}; + struct PreviousSong {}; + + // A "complicated" event type that carries some data. + struct cd_detected + { + cd_detected(std::string name) + : name(name) + {} + + std::string name; + }; + + // front-end: define the FSM structure + struct player_ : public msm::front::state_machine_def + { + // The list of FSM states + struct Empty : public msm::front::state<> + { + // every (optional) entry/exit methods get the event passed + template + void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "leaving: Empty" << std::endl;} + }; + struct Open : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {std::cout << "entering: Open" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "leaving: Open" << std::endl;} + }; + + struct Stopped : public msm::front::state<> + { + // when stopped, the CD is loaded + template + void on_entry(Event const&,FSM& ) {std::cout << "entering: Stopped" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "leaving: Stopped" << std::endl;} + }; + + struct Playing_ : public msm::front::state_machine_def + { + // when playing, the CD is loaded and we are in either pause or playing (duh) + template + void on_entry(Event const&,FSM& ) {std::cout << "entering: Playing" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "leaving: Playing" << std::endl;} + + // The list of FSM states + struct Song1 : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {std::cout << "starting: First song" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "finishing: First Song" << std::endl;} + }; + struct Song2 : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {std::cout << "starting: Second song" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "finishing: Second Song" << std::endl;} + }; + struct Song3 : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {std::cout << "starting: Third song" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "finishing: Third Song" << std::endl;} + }; + // the initial state. Must be defined + typedef Song1 initial_state; + // transition actions + void start_next_song(NextSong const&) { std::cout << "Playing::start_next_song\n"; } + void start_prev_song(PreviousSong const&) { std::cout << "Playing::start_prev_song\n"; } + // guard conditions + + typedef Playing_ pl; // makes transition table cleaner + // Transition table for Playing + struct transition_table : mpl::vector4< + // Start Event Next Action Guard + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Song1 , NextSong , Song2 , &pl::start_next_song >, + a_row < Song2 , PreviousSong, Song1 , &pl::start_prev_song >, + a_row < Song2 , NextSong , Song3 , &pl::start_next_song >, + a_row < Song3 , PreviousSong, Song2 , &pl::start_prev_song > + // +---------+-------------+---------+---------------------+----------------------+ + > {}; + // Replaces the default no-transition response. + template + void no_transition(Event const& e, FSM&,int state) + { + std::cout << "no transition from state " << state + << " on event " << typeid(e).name() << std::endl; + } + + }; + // back-end + // demonstrates Shallow History: if the state gets activated with end_pause + // then it will remember the last active state and reactivate it + // also possible: AlwaysHistory, the last active state will always be reactivated + // or NoHistory, always restart from the initial state + typedef msm::back::state_machine > > Playing; + + // state not defining any entry or exit + struct Paused : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {std::cout << "entering: Paused" << std::endl;} + template + void on_exit(Event const&,FSM& ) {std::cout << "leaving: Paused" << std::endl;} + }; + + // the initial state of the player SM. Must be defined + typedef Empty initial_state; + + // transition actions + void start_playback(play const&) { std::cout << "player::start_playback\n"; } + void open_drawer(open_close const&) { std::cout << "player::open_drawer\n"; } + void close_drawer(open_close const&) { std::cout << "player::close_drawer\n"; } + void store_cd_info(cd_detected const& cd) {std::cout << "player::store_cd_info\n";} + void stop_playback(stop const&) { std::cout << "player::stop_playback\n"; } + void pause_playback(pause const&) { std::cout << "player::pause_playback\n"; } + void resume_playback(end_pause const&) { std::cout << "player::resume_playback\n"; } + void stop_and_open(open_close const&) { std::cout << "player::stop_and_open\n"; } + void stopped_again(stop const&){std::cout << "player::stopped_again\n";} + // guard conditions + + typedef player_ p; // makes transition table cleaner + + // Transition table for player + struct transition_table : mpl::vector< + // Start Event Next Action Guard + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Stopped , play , Playing , &p::start_playback >, + a_row < Stopped , open_close , Open , &p::open_drawer >, + a_row < Stopped , stop , Stopped , &p::stopped_again >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Open , open_close , Empty , &p::close_drawer >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Empty , open_close , Open , &p::open_drawer >, + a_row < Empty , cd_detected , Stopped , &p::store_cd_info >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Playing , stop , Stopped , &p::stop_playback >, + a_row < Playing , pause , Paused , &p::pause_playback >, + a_row < Playing , open_close , Open , &p::stop_and_open >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Paused , end_pause , Playing , &p::resume_playback >, + a_row < Paused , stop , Stopped , &p::stop_playback >, + a_row < Paused , open_close , Open , &p::stop_and_open > + // +---------+-------------+---------+---------------------+----------------------+ + > {}; + + // Replaces the default no-transition response. + template + void no_transition(Event const& e, FSM&,int state) + { + std::cout << "no transition from state " << state + << " on event " << typeid(e).name() << std::endl; + } + + }; + // Pick a back-end + typedef msm::back::state_machine player; + + // + // Testing utilities. + // + static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" }; + + void pstate(player const& p) + { + std::cout << " -> " << state_names[p.current_state()[0]] << std::endl; + } + + void test() + { + player p; + + // needed to start the highest-level SM. This will call on_entry and mark the start of the SM + p.start(); + // go to Open, call on_exit on Empty, then action, then on_entry on Open + p.process_event(open_close()); pstate(p); + p.process_event(open_close()); pstate(p); + p.process_event(cd_detected("louie, louie")); + p.process_event(play()); + + // at this point, Play is active + // make transition happen inside it. Player has no idea about this event but it's ok. + p.process_event(NextSong());pstate(p); //2nd song active + p.process_event(NextSong());pstate(p);//3rd song active + p.process_event(PreviousSong());pstate(p);//2nd song active + p.process_event(pause()); pstate(p); + std::ofstream ofs("fsm.txt"); + // save fsm to archive (current state is Pause, Playing is in Song2) + { + boost::archive::text_oarchive oa(ofs); + // write class instance to archive + oa << p; + } + // reload fsm in state Open + player p2; + { + // create and open an archive for input + std::ifstream ifs("fsm.txt"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> p2; + } + // go back to Playing + // as you see, remembers the original state as end_pause is an history trigger + p2.process_event(end_pause()); pstate(p2); + p2.process_event(pause()); pstate(p2); + p2.process_event(stop()); pstate(p2); + // event leading to the same state + p2.process_event(stop()); pstate(p2); + // play does not trigger shallow history => start back from 1st song + p2.process_event(play()); pstate(p2); + } +} +// eliminate object tracking (even if serialized through a pointer) +// at the risk of a programming error creating duplicate objects. +// this is to get rid of warning because p is not const +BOOST_CLASS_TRACKING(player, boost::serialization::track_never) + +int main() +{ + test(); + return 0; +} diff --git a/doc/HTML/index.html b/doc/HTML/index.html index bdffba3..6ff0301 100644 --- a/doc/HTML/index.html +++ b/doc/HTML/index.html @@ -1,16 +1,16 @@ - Meta State Machine (MSM) V2.10

            Meta State Machine (MSM) V2.10

            Meta State Machine (MSM) V2.12


            Table of Contents

            Preface
            I. User' guide
            1. Founding idea
            2. UML Short Guide
            What are state machines?
            Concepts
            State machine, state, transition, event
            Submachines, orthogonal regions, pseudostates
            History
            Completion transitions / anonymous transitions
            Internal transitions
            - Conflicting transitions
            State machine glossary
            3. Tutorial
            Design
            Basic front-end
            A simple example
            Transition table
            Defining states with entry/exit actions
            Defining a simple state machine
            Defining a submachine
            Orthogonal regions, terminate state, event deferring
            History
            Completion (anonymous) transitions
            Internal transitions
            more row types
            Explicit entry / entry and exit pseudo-state / fork
            Flags
            Event Hierarchy
            Customizing a state machine / Getting more speed
            Choosing the initial event
            Containing state machine (deprecated)
            Functor front-end
            Transition table
            Defining states with entry/exit actions
            Defining a simple state machine
            Anonymous transitions
            Internal - transitions
            eUML (experimental)
            Transition table
            Defining events, actions and states with entry/exit actions
            Defining a simple state machine
            Defining a submachine
            - Attributes / Function call
            Orthogonal regions, flags, event deferring
            + Conflicting transitions
            State machine glossary
            3. Tutorial
            Design
            Basic front-end
            A simple example
            Transition table
            Defining states with entry/exit actions
            Defining a simple state machine
            Defining a submachine
            Orthogonal regions, terminate state, event deferring
            History
            Completion (anonymous) transitions
            Internal transitions
            more row types
            Explicit entry / entry and exit pseudo-state / fork
            Flags
            Event Hierarchy
            Customizing a state machine / Getting more speed
            Choosing the initial event
            Containing state machine (deprecated)
            Functor front-end
            Transition table
            Defining states with entry/exit actions
            Defining a simple state machine
            Anonymous transitions
            Internal + transitions
            eUML (experimental)
            Transition table
            Defining events, actions and states with entry/exit actions
            Defining a simple state machine
            Defining a submachine
            + Attributes / Function call
            Orthogonal regions, flags, event deferring
            Customizing a state machine / Getting - more speed
            Completion / Anonymous transitions
            Internal transitions
            Other state types
            Helper functions
            Phoenix-like STL support
            Back-end
            Creation
            Starting a state machine
            Event dispatching
            Active state(s)
            Base state type
            Visitor
            Flags
            Getting a state
            State machine constructor with arguments
            Trading run-time speed for - better compile-time / multi-TU compilation
            4. Performance / Compilers
            Speed
            Executable size
            Supported compilers
            Limitations
            Compilers corner
            5. Questions & Answers
            6. Internals
            Backend: Run To Completion
            Frontend / Backend - interface
            Generated state ids
            Metaprogramming tools
            7. Acknowledgements
            MSM v2
            MSM v1
            8. Version history
            From V2.0 to V2.10
            II. Reference
            9. eUML operators and basic helpers
            10. - Functional programming
            Common headers — The common types used by front- and back-ends
            Back-end — The back-end headers
            Front-end — The front-end headers
            \ No newline at end of file + more speed
            Completion / Anonymous transitions
            Internal transitions
            Other state types
            Helper functions
            Phoenix-like STL support
            Back-end
            Creation
            Starting a state machine
            Event dispatching
            Active state(s)
            Serialization
            Base state type
            Visitor
            Flags
            Getting a state
            State machine constructor with arguments
            Trading run-time speed for + better compile-time / multi-TU compilation
            4. Performance / Compilers
            Speed
            Executable size
            Supported compilers
            Limitations
            Compilers corner
            5. Questions & Answers
            6. Internals
            Backend: Run To Completion
            Frontend / Backend + interface
            Generated state ids
            Metaprogramming tools
            7. Acknowledgements
            MSM v2
            MSM v1
            8. Version history
            From V2.10 to V2.12
            From V2.0 to V2.12
            II. Reference
            9. eUML operators and basic helpers
            10. + Functional programming
            Common headers — The common types used by front- and back-ends
            Back-end — The back-end headers
            Front-end — The front-end headers
            \ No newline at end of file diff --git a/doc/HTML/pr01.html b/doc/HTML/pr01.html index 48ccbd5..02d4568 100644 --- a/doc/HTML/pr01.html +++ b/doc/HTML/pr01.html @@ -1,6 +1,6 @@ - Preface

            Preface

            MSM is a library allowing you to easily and quickly define state machines of very high + Preface

            Preface

            MSM is a library allowing you to easily and quickly define state machines of very high performance. From this point, two main questions usually quickly arise, so please allow me to try answering them upfront.

            • When do I need a state machine?

              More often that you think. Very often, one defined a state machine @@ -58,4 +58,4 @@ standard which is not implemented. MSM offers a very large part of the standard, with more on the way.

            Let us not wait any longer, I hope you will enjoy MSM and have fun with it!

            -

            \ No newline at end of file +

            \ No newline at end of file diff --git a/doc/HTML/pt01.html b/doc/HTML/pt01.html index 34eccfd..c9f261c 100644 --- a/doc/HTML/pt01.html +++ b/doc/HTML/pt01.html @@ -1,12 +1,12 @@ - Part I. User' guide

            Part I. User' guide

            Table of Contents

            1. Founding idea
            2. UML Short Guide
            What are state machines?
            Concepts
            State machine, state, transition, event
            Submachines, orthogonal regions, pseudostates
            + Part I. User' guide

            Part I. User' guide

            Table of Contents

            1. Founding idea
            2. UML Short Guide
            What are state machines?
            Concepts
            State machine, state, transition, event
            Submachines, orthogonal regions, pseudostates
            History
            Completion transitions / anonymous transitions
            Internal transitions
            - Conflicting transitions
            State machine glossary
            3. Tutorial
            Design
            Basic front-end
            A simple example
            Transition table
            Defining states with entry/exit actions
            Defining a simple state machine
            Defining a submachine
            Orthogonal regions, terminate state, event deferring
            History
            Completion (anonymous) transitions
            Internal transitions
            more row types
            Explicit entry / entry and exit pseudo-state / fork
            Flags
            Event Hierarchy
            Customizing a state machine / Getting more speed
            Choosing the initial event
            Containing state machine (deprecated)
            Functor front-end
            Transition table
            Defining states with entry/exit actions
            Defining a simple state machine
            Anonymous transitions
            Internal - transitions
            eUML (experimental)
            Transition table
            Defining events, actions and states with entry/exit actions
            Defining a simple state machine
            Defining a submachine
            - Attributes / Function call
            Orthogonal regions, flags, event deferring
            + Conflicting transitions
            State machine glossary
            3. Tutorial
            Design
            Basic front-end
            A simple example
            Transition table
            Defining states with entry/exit actions
            Defining a simple state machine
            Defining a submachine
            Orthogonal regions, terminate state, event deferring
            History
            Completion (anonymous) transitions
            Internal transitions
            more row types
            Explicit entry / entry and exit pseudo-state / fork
            Flags
            Event Hierarchy
            Customizing a state machine / Getting more speed
            Choosing the initial event
            Containing state machine (deprecated)
            Functor front-end
            Transition table
            Defining states with entry/exit actions
            Defining a simple state machine
            Anonymous transitions
            Internal + transitions
            eUML (experimental)
            Transition table
            Defining events, actions and states with entry/exit actions
            Defining a simple state machine
            Defining a submachine
            + Attributes / Function call
            Orthogonal regions, flags, event deferring
            Customizing a state machine / Getting - more speed
            Completion / Anonymous transitions
            Internal transitions
            Other state types
            Helper functions
            Phoenix-like STL support
            Back-end
            Creation
            Starting a state machine
            Event dispatching
            Active state(s)
            Base state type
            Visitor
            Flags
            Getting a state
            State machine constructor with arguments
            Trading run-time speed for - better compile-time / multi-TU compilation
            4. Performance / Compilers
            Speed
            Executable size
            Supported compilers
            Limitations
            Compilers corner
            5. Questions & Answers
            6. Internals
            Backend: Run To Completion
            Frontend / Backend - interface
            Generated state ids
            Metaprogramming tools
            7. Acknowledgements
            MSM v2
            MSM v1
            8. Version history
            From V2.0 to V2.10
            \ No newline at end of file + more speed
            Completion / Anonymous transitions
            Internal transitions
            Other state types
            Helper functions
            Phoenix-like STL support
            Back-end
            Creation
            Starting a state machine
            Event dispatching
            Active state(s)
            Serialization
            Base state type
            Visitor
            Flags
            Getting a state
            State machine constructor with arguments
            Trading run-time speed for + better compile-time / multi-TU compilation
            4. Performance / Compilers
            Speed
            Executable size
            Supported compilers
            Limitations
            Compilers corner
            5. Questions & Answers
            6. Internals
            Backend: Run To Completion
            Frontend / Backend + interface
            Generated state ids
            Metaprogramming tools
            7. Acknowledgements
            MSM v2
            MSM v1
            8. Version history
            From V2.10 to V2.12
            From V2.0 to V2.12
            \ No newline at end of file diff --git a/doc/HTML/pt02.html b/doc/HTML/pt02.html index 7e4cd8d..e3d05c2 100644 --- a/doc/HTML/pt02.html +++ b/doc/HTML/pt02.html @@ -1,4 +1,4 @@ - Part II. Reference

            Part II. Reference

            Table of Contents

            9. eUML operators and basic helpers
            10. - Functional programming
            Common headers — The common types used by front- and back-ends
            Back-end — The back-end headers
            Front-end — The front-end headers
            \ No newline at end of file + Part II. Reference

            Part II. Reference

            Table of Contents

            9. eUML operators and basic helpers
            10. + Functional programming
            Common headers — The common types used by front- and back-ends
            Back-end — The back-end headers
            Front-end — The front-end headers
            \ No newline at end of file diff --git a/doc/HTML/re01.html b/doc/HTML/re01.html index 57797a5..800d2a4 100644 --- a/doc/HTML/re01.html +++ b/doc/HTML/re01.html @@ -1,8 +1,8 @@ - Common headers

            Name

            Common headers — The common types used by front- and back-ends

            msm/common.hpp

            This header provides one type, wrap, which is an empty type whose only reason + Common headers

            Name

            Common headers — The common types used by front- and back-ends

            msm/common.hpp

            This header provides one type, wrap, which is an empty type whose only reason to exist is to be cheap to construct, so that it can be used with mpl::for_each, - as shown in the Metaprogramming book, chapter 9.

             template <class Dummy> wrap{}; {
            }

            msm/row_tags.hpp

            This header contains the row type tags which front-ends can support partially + as shown in the Metaprogramming book, chapter 9.

             template <class Dummy> wrap{}; {
            }

            msm/row_tags.hpp

            This header contains the row type tags which front-ends can support partially or totally. Please see the Internals section for a description of the different types.

            \ No newline at end of file diff --git a/doc/HTML/re02.html b/doc/HTML/re02.html index c350be2..e1066ad 100644 --- a/doc/HTML/re02.html +++ b/doc/HTML/re02.html @@ -1,79 +1,79 @@ - Back-end

            Name

            Back-end — The back-end headers

            msm/back/state_machine.hpp

            This header provides one type, state_machine, MSM's state machine engine + Back-end

            Name

            Back-end — The back-end headers

            msm/back/state_machine.hpp

            This header provides one type, state_machine, MSM's state machine engine implementation.

             template <class Derived,class HistoryPolicy=NoHistory,class
            -                            CompilePolicy=favor_runtime_speed> state_machine {
            }

            Template arguments

            Derived

            The name of the front-end state machine definition. All three - front-ends are possible.

            HistoryPolicy

            The desired history. This can be: AlwaysHistory, NoHistory, - ShallowHistory. Default is NoHistory.

            CompilePolicy

            The trade-off performance / compile-time. There are two predefined + CompilePolicy=favor_runtime_speed> state_machine {
            }

            Template arguments

            Derived

            The name of the front-end state machine definition. All three + front-ends are possible.

            HistoryPolicy

            The desired history. This can be: AlwaysHistory, NoHistory, + ShallowHistory. Default is NoHistory.

            CompilePolicy

            The trade-off performance / compile-time. There are two predefined policies, favor_runtime_speed and favor_compile_time. Default is - favor_runtime_speed, best performance, longer compile-time. See the backend.

            methods

            start

            The start methods must be called before any call to process_event. It + favor_runtime_speed, best performance, longer compile-time. See the backend.

            methods

            start

            The start methods must be called before any call to process_event. It activates the entry action of the initial state(s). This allows you to - choose when a state machine can start. See backend.

            void start();

            process_event

            The event processing method implements the double-dispatch. Each call + choose when a state machine can start. See backend.

            void start();

            process_event

            The event processing method implements the double-dispatch. Each call to this function with a new event type instantiates a new dispatch algorithm and increases compile-time.

            template <class Event> HandledEnum - process_event(Event const&);

            current_state

            Returns the ids of currently active states. You will typically need it - only for debugging or logging purposes.

            const int* current_state const();

            get_state_by_id

            Returns the state whose id is given. As all states of a concrete state + process_event(Event const&);

            current_state

            Returns the ids of currently active states. You will typically need it + only for debugging or logging purposes.

            const int* current_state const();

            get_state_by_id

            Returns the state whose id is given. As all states of a concrete state machine share a common base state, the return value is a base state. If - the id corresponds to no state, a null pointer is returned.

            const BaseState* get_state_by_id const(int id);

            is_contained

            Helper returning true if the state machine is contained as a - submachine of another state machine.

            bool is_contained const();

            get_state

            Returns the required state of the state machine as a pointer. A + the id corresponds to no state, a null pointer is returned.

            const BaseState* get_state_by_id const(int id);

            is_contained

            Helper returning true if the state machine is contained as a + submachine of another state machine.

            bool is_contained const();

            get_state

            Returns the required state of the state machine as a pointer. A compile error will occur if the state is not to be found in the state - machine.

            template <class State> State* get_state();

            get_state

            Returns the required state of the state machine as a reference. A + machine.

            template <class State> State* get_state();

            get_state

            Returns the required state of the state machine as a reference. A compile error will occur if the state is not to be found in the state - machine.

            template <class State> State& get_state();

            is_flag_active

            Returns true if the given flag is currently active. A flag is active + machine.

            template <class State> State& get_state();

            is_flag_active

            Returns true if the given flag is currently active. A flag is active if the active state of one region is tagged with this flag (using OR as BinaryOp) or active states of all regions (using AND as BinaryOp)

            template <class Flag,class BinaryOp> bool - is_flag_active();

            is_flag_active

            Returns true if the given flag is currently active. A flag is active - if the active state of one region is tagged with this flag.

            template <class Flag> bool is_flag_active();

            visit_current_states

            Visits all active states and their substates. A state is visited using + is_flag_active();

            is_flag_active

            Returns true if the given flag is currently active. A flag is active + if the active state of one region is tagged with this flag.

            template <class Flag> bool is_flag_active();

            visit_current_states

            Visits all active states and their substates. A state is visited using the accept method without argument. The base class of all - states must provide an accept_sig type.

            void visit_current_states();

            visit_current_states

            Visits all active states and their substates. A state is visited using + states must provide an accept_sig type.

            void visit_current_states();

            visit_current_states

            Visits all active states and their substates. A state is visited using the accept method with arguments. The base class of all states must provide an accept_sig type defining the - signature and thus the number and type of the parameters.

            void visit_current_states(any-type param1, any-type param2,...);

            defer_event

            Defers the provided event. This method can be called only if at least + signature and thus the number and type of the parameters.

            void visit_current_states(any-type param1, any-type param2,...);

            defer_event

            Defers the provided event. This method can be called only if at least one state defers an event or if the state machine provides the activate_deferred_events(see example) type either directly or using the deferred_events configuration of eUML - (configure_ << deferred_events)

            template <class Event> void defer_event(Event const&);

            Types

            nr_regions

            The number of orthogonal regions contained in the state machine

            entry_pt

            This nested type provides the necessary typedef for entry point + (configure_ << deferred_events)

            template <class Event> void defer_event(Event const&);

            Types

            nr_regions

            The number of orthogonal regions contained in the state machine

            entry_pt

            This nested type provides the necessary typedef for entry point pseudostates. state_machine<...>::entry_pt<state_name> is a transition's valid target inside the containing state machine's - transition table.

             entry_pt {
            }

            exit_pt

            This nested type provides the necessary typedef for exit point + transition table.

             entry_pt {
            }

            exit_pt

            This nested type provides the necessary typedef for exit point pseudostates. state_machine<...>::exit_pt<state_name> is a transition's valid source inside the containing state machine's - transition table.

             exit_pt {
            }

            direct

            This nested type provides the necessary typedef for an explicit entry + transition table.

             exit_pt {
            }

            direct

            This nested type provides the necessary typedef for an explicit entry inside a submachine. state_machine<...>::direct<state_name> is a transition's valid target inside the containing state machine's - transition table.

             direct {
            }

            stt

            Calling state_machine<frontend>::stt returns a mpl::vector + transition table.

             direct {
            }

            stt

            Calling state_machine<frontend>::stt returns a mpl::vector containing the transition table of the state machine. This type can then - be used with generate_state_set or generate_event_set.

            args.hpp

            This header provides one type, args. which provides the necessary types for a - visitor implementation.

            msm/back/history_policies.hpp

            This header provides the out-of-the-box history policies supported by MSM. - There are 3 such policies.

            Every history policy must implement the following methods:

            set_initial_states

            This method is called by msm::back::state_machine when constructed. + be used with generate_state_set or generate_event_set.

            args.hpp

            This header provides one type, args. which provides the necessary types for a + visitor implementation.

            msm/back/history_policies.hpp

            This header provides the out-of-the-box history policies supported by MSM. + There are 3 such policies.

            Every history policy must implement the following methods:

            set_initial_states

            This method is called by msm::back::state_machine when constructed. It gives the policy a chance to save the ids of all initial states (passed as array).

            void set_initial_states(); 
            (int* const) - ;
             

            history_exit

            This method is called by msm::back::state_machine when the submachine + ;

             

            history_exit

            This method is called by msm::back::state_machine when the submachine is exited. It gives the policy a chance to remember the ids of the last active substates of this submachine (passed as array).

            void history_exit(); 
            (int* const) - ;
             

            history_entry

            This method is called by msm::back::state_machine when the submachine + ;

             

            history_entry

            This method is called by msm::back::state_machine when the submachine is entered. It gives the policy a chance to set the active states according to the policy's aim. The policy gets as parameter the event which activated the submachine and returns an array of active states ids.

            template <class Event> int* const history_exit(); 
            (Event const&) - ;
             

            Out-of-the-box policies:

            NoHistory

            This policy is the default used by state_machine. No active state of a + ;

             

            Out-of-the-box policies:

            NoHistory

            This policy is the default used by state_machine. No active state of a submachine is remembered and at every new activation of the submachine, - the initial state(s) are activated.

            AlwaysHistory

            This policy is a non-UML-standard extension. The active state(s) of a + the initial state(s) are activated.

            AlwaysHistory

            This policy is a non-UML-standard extension. The active state(s) of a submachine is (are) always remembered at every new activation of the - submachine.

            ShallowHistory

            This policy activates the active state(s) of a submachine if the event - is found in the policy's event list.

            msm/back/default_compile_policy.hpp

            This header contains the definition of favor_runtime_speed. This policy has + submachine.

            ShallowHistory

            This policy activates the active state(s) of a submachine if the event + is found in the policy's event list.

            msm/back/default_compile_policy.hpp

            This header contains the definition of favor_runtime_speed. This policy has two settings:

            • Submachines dispatch faster because their transitions are added into their containing machine's transition table instead of simply - forwarding events.

            • It solves transition conflicts at compile-time

            msm/back/favor_compile_time.hpp

            This header contains the definition of favor_compile_time. This policy has two settings:

            • Submachines dispatch is slower because all events, even those with + forwarding events.

            • It solves transition conflicts at compile-time

            msm/back/favor_compile_time.hpp

            This header contains the definition of favor_compile_time. This policy has two settings:

            • Submachines dispatch is slower because all events, even those with no dispatch chance, are forwarded to submachines. In exchange, no row is added into the containing machine's transition table, which - reduces compile-time.

            • It solves transition conflicts at run-time.

            msm/back/metafunctions.hpp

            This header contains metafunctions for use by the library. Three metafunctions + reduces compile-time.

          • It solves transition conflicts at run-time.

          • msm/back/metafunctions.hpp

            This header contains metafunctions for use by the library. Three metafunctions can be useful for the user:

            • generate_state_set< stt >: generates the list of all states referenced by the transition table stt. If stt is a recursive table (generated by @@ -86,10 +86,10 @@ finds recursively all events of the submachines. A non-recursive table can be obtained with some_backend_fsm::stt.

            • recursive_get_transition_table<fsm>: recursively extends the transition table of the state machine fsm with tables - from the submachines.

            msm/back/tools.hpp

            This header contains a few metaprogramming tools to get some information out - of a state machine.

            fill_state_names

            attributes

            fill_state_names has for attribute:

            • char const** m_names: an already allocated + from the submachines.

            msm/back/tools.hpp

            This header contains a few metaprogramming tools to get some information out + of a state machine.

            fill_state_names

            attributes

            fill_state_names has for attribute:

            • char const** m_names: an already allocated array of const char* where the typeid-generated names of a - state machine states will be witten.

            constructor

            char const** names_to_fill(char const** names_to_fill);

            usage

            fill_state_names is made for use in a mpl::for_each iterating on a + state machine states will be witten.

            constructor

            char const** names_to_fill(char const** names_to_fill);

            usage

            fill_state_names is made for use in a mpl::for_each iterating on a state list and writing inside a pre-allocated array the state names. Example:

            typedef some_fsm::stt Stt;
             typedef msm::back::generate_state_set<Stt>::type all_states; //states
            @@ -104,10 +104,10 @@ for (unsigned int i=0;i<some_fsm::nr_regions::value;++i)
                 std::cout << " -> " 
                           << state_names[my_fsm_instance.current_state()[i]] 
                           << std::endl;
            -}

            get_state_name

            attributes

            get_state_name has for attributes:

            • std::string& m_name: the return value of the - iteration

            • int m_state_id: the searched state's id

            constructor

            The constructor takes as argument a reference to the string to fill - with the state name and the id which must be searched.

            string& name_to_fill,int state_id(string& name_to_fill,int state_id);

            usage

            This type is made for the same search as in the previous example, +}

            get_state_name

            attributes

            get_state_name has for attributes:

            • std::string& m_name: the return value of the + iteration

            • int m_state_id: the searched state's id

            constructor

            The constructor takes as argument a reference to the string to fill + with the state name and the id which must be searched.

            string& name_to_fill,int state_id(string& name_to_fill,int state_id);

            usage

            This type is made for the same search as in the previous example, using a mpl::for_each to iterate on states. After the iteration, the - state name reference has been set.

            display_type

            attributes

            none

            usage

            Reusing the state list from the previous example, we can output all + state name reference has been set.

            display_type

            attributes

            none

            usage

            Reusing the state list from the previous example, we can output all state names:

            mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> >(msm::back::display_type ());

            \ No newline at end of file diff --git a/doc/HTML/re03.html b/doc/HTML/re03.html index 2f70800..1ca3879 100644 --- a/doc/HTML/re03.html +++ b/doc/HTML/re03.html @@ -1,11 +1,11 @@ - Front-end

            Name

            Front-end — The front-end headers

            msm/front/common_states.hpp

            This header contains the predefined types to serve as base for states or state machines:

            • default_base_state: non-polymorphic empty type.

            • polymorphic_state: type with a virtual destructor, which makes all - states polymorphic.

            msm/front/completion_event.hpp

            This header contains one type, none. This type has several + Front-end

            Name

            Front-end — The front-end headers

            msm/front/common_states.hpp

            This header contains the predefined types to serve as base for states or state machines:

            • default_base_state: non-polymorphic empty type.

            • polymorphic_state: type with a virtual destructor, which makes all + states polymorphic.

            msm/front/completion_event.hpp

            This header contains one type, none. This type has several meanings inside a transition table:

            • as action or guard: that there is no action or guard

            • as target state: that the transition is an internal transition

            • as event: the transition is an anonymous (completion) - transition

            msm/front/functor_row.hpp

            This header implements the functor front-end's transitions and helpers.

            Row

            definition

             template <class Source,class Event,class Target,class
            -                                    Action,class Guard> Row {
            }

            tags

            row_type_tag is defined differently for every specialization:

            • all 5 template parameters means a normal transition with + transition

            msm/front/functor_row.hpp

            This header implements the functor front-end's transitions and helpers.

            Row

            definition

             template <class Source,class Event,class Target,class
            +                                    Action,class Guard> Row {
            }

            tags

            row_type_tag is defined differently for every specialization:

            • all 5 template parameters means a normal transition with action and guard: typedef row_tag row_type_tag;

            • Row<Source,Event,Target,none,none> a normal transition without action or guard: typedef _row_tag @@ -21,7 +21,7 @@ transition with action and guard: typedef irow_tag row_type_tag;

            • Row<Source,Event,none,none,none> an internal transition without action or guard: typedef _irow_tag - row_type_tag;

            methods

            Like any other front-end, Row implements the two necessary static + row_type_tag;

            methods

            Like any other front-end, Row implements the two necessary static functions for action and guard call. Each function receives as parameter the (deepest-level) state machine processsing the event, the event itself, the source and target states and all the states contained in a @@ -33,8 +33,8 @@ class AllStates> static bool guard_call(

            ); 
            (Fsm& fsm,Event const& evt,SourceState&,TargetState,AllStates&) - ;
             

            Internal

            definition

             template <class Event,class Action,class Guard>
            -                                    Internal {
            }

            tags

            row_type_tag is defined differently for every specialization:

            • all 3 template parameters means an internal transition + ;

             

            Internal

            definition

             template <class Event,class Action,class Guard>
            +                                    Internal {
            }

            tags

            row_type_tag is defined differently for every specialization:

            • all 3 template parameters means an internal transition with action and guard: typedef sm_i_row_tag row_type_tag;

            • Internal<Event,none,none> an internal transition without action or guard: typedef sm__i_row_tag @@ -42,7 +42,7 @@ without guard: typedef sm_a_i_row_tag row_type_tag;

            • Internal<Event,none,Guard> an internal transition without action: typedef sm_g_i_row_tag - row_type_tag;

            methods

            Like any other front-end, Internal implements the two necessary static + row_type_tag;

            methods

            Like any other front-end, Internal implements the two necessary static functions for action and guard call. Each function receives as parameter the (deepest-level) state machine processsing the event, the event itself, the source and target states and all the states contained in a @@ -54,9 +54,9 @@ class AllStates> static bool guard_call(

            ); 
            (Fsm& fsm,Event const& evt,SourceState&,TargetState,AllStates&) - ;
             

            ActionSequence_

            This functor calls every element of the template Sequence (which are also + ;

             

            ActionSequence_

            This functor calls every element of the template Sequence (which are also callable functors) in turn. It is also the underlying implementation of the - eUML sequence grammar (action1,action2,...).

            definition

             template <class Sequence> ActionSequence_ {
            }

            methods

            This helper functor is made for use in a transition table and in a + eUML sequence grammar (action1,action2,...).

            definition

             template <class Sequence> ActionSequence_ {
            }

            methods

            This helper functor is made for use in a transition table and in a state behavior and therefore implements an operator() with 3 and with 4 arguments:

            template <class Evt,class Fsm,class @@ -65,13 +65,13 @@

            template <class Evt,class Fsm,class State> operator()(); 
            Evt const&, Fsm&, State&;
             

            -

            Defer

            definition

             Defer {
            }

            methods

            This helper functor is made for use in a transition table and +

            Defer

            definition

             Defer {
            }

            methods

            This helper functor is made for use in a transition table and therefore implements an operator() with 4 arguments:

            template <class Evt,class Fsm,class SourceState,class TargetState> operator()(); 
            Evt const&, Fsm& , SourceState&, - TargetState&;
             

            msm/front/internal_row.hpp

            This header implements the internal transition rows for use inside an + TargetState&;

             

            msm/front/internal_row.hpp

            This header implements the internal transition rows for use inside an internal_transition_table. All these row types have no source or target state, as the backend will recognize internal transitions from this - internal_transition_table.

            methods

            Like any other front-end, the following transition row types implements + internal_transition_table.

            methods

            Like any other front-end, the following transition row types implements the two necessary static functions for action and guard call. Each function receives as parameter the (deepest-level) state machine processsing the event, the event itself, the source and target states and all the states @@ -83,30 +83,30 @@ class AllStates> static bool guard_call(

            ); 
            (Fsm& fsm,Event const& evt,SourceState&,TargetState,AllStates&) - ;
             

            a_internal

            definition

            This is an internal transition with an action called during the + ;

             

            a_internal

            definition

            This is an internal transition with an action called during the transition.

             template< class Event, class CalledForAction, void
                                                 (CalledForAction::*action)(Event const&)>
            -                                    a_internal {
            }

            template parameters

            + a_internal {
            }

            template parameters

            • Event: the event triggering the internal transition.

            • CalledForAction: the type on which the action method will be called. It can be either a state of the containing state machine or the state machine itself.

            • action: a pointer to the method which CalledForAction provides.

            -

            g_internal

            This is an internal transition with a guard called before the transition - and allowing the transition if returning true.

            definition

             template< class Event, class CalledForGuard, bool
            +                        

            g_internal

            This is an internal transition with a guard called before the transition + and allowing the transition if returning true.

            definition

             template< class Event, class CalledForGuard, bool
                                                 (CalledForGuard::*guard)(Event const&)>
            -                                    g_internal {
            }

            template parameters

            + g_internal {
            }

            template parameters

            • Event: the event triggering the internal transition.

            • CalledForGuard: the type on which the guard method will be called. It can be either a state of the containing state machine or the state machine itself.

            • guard: a pointer to the method which CalledForGuard provides.

            -

            internal

            This is an internal transition with a guard called before the transition +

            internal

            This is an internal transition with a guard called before the transition and allowing the transition if returning true. It also calls an action - called during the transition.

            definition

             template< class Event, class CalledForAction, void
            +                        called during the transition.

            definition

             template< class Event, class CalledForAction, void
                                                 (CalledForAction::*action)(Event const&), class
                                                 CalledForGuard, bool (CalledForGuard::*guard)(Event const&)>
            -                                    internal {
            }

            template parameters

            + internal {
            }

            template parameters

            • Event: the event triggering the internal transition

            • CalledForAction: the type on which the action method will be called. It can be either a state of the containing state machine or the state machine itself.

            • action: a pointer to the method which CalledForAction @@ -114,15 +114,15 @@ called. It can be either a state of the containing state machine or the state machine itself.

            • guard: a pointer to the method which CalledForGuard provides.

            -

            _internal

            This is an internal transition without action or guard. This is equivalent - to an explicit "ignore event".

            definition

             template< class Event > _internal {
            }

            template parameters

            +

            _internal

            This is an internal transition without action or guard. This is equivalent + to an explicit "ignore event".

            definition

             template< class Event > _internal {
            }

            template parameters

            • Event: the event triggering the internal transition.

            -

            msm/front/row2.hpp

            This header contains the variants of row2, which are an extension of the +

            msm/front/row2.hpp

            This header contains the variants of row2, which are an extension of the standard row transitions for use in the transition table. They offer the possibility to define action and guard not only in the state machine, but in any state of the state machine. They can also be used in internal transition tables - through their irow2 variants.

            methods

            Like any other front-end, the following transition row types implements + through their irow2 variants.

            methods

            Like any other front-end, the following transition row types implements the two necessary static functions for action and guard call. Each function receives as parameter the (deepest-level) state machine processsing the event, the event itself, the source and target states and all the states @@ -134,28 +134,28 @@ class AllStates> static bool guard_call(

            ); 
            (Fsm& fsm,Event const& evt,SourceState&,TargetState,AllStates&) - ;
             

            _row2

            This is a transition without action or guard. The state machine only - changes active state.

            definition

             template< class Source, class Event, class Target >
            -                                    _row2 {
            }

            template parameters

            + ;

             

            _row2

            This is a transition without action or guard. The state machine only + changes active state.

            definition

             template< class Source, class Event, class Target >
            +                                    _row2 {
            }

            template parameters

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • Target: the target state of the transition.

            -

            a_row2

            This is a transition with action and without guard.

            definition

             template< class Source, class Event, class Target,
            +                        

            a_row2

            This is a transition with action and without guard.

            definition

             template< class Source, class Event, class Target,
                                              {
            }
             class CalledForAction, void
            -                                    (CalledForAction::*action)(Event const&) > _row2 {
            }

            template parameters

            + (CalledForAction::*action)(Event const&) > _row2 {
            }

            template parameters

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • Target: the target state of the transition.

            • CalledForAction: the type on which the action method will be called. It can be either a state of the containing state machine or the state machine itself.

            • action: a pointer to the method which CalledForAction provides.

            -

            g_row2

            This is a transition with guard and without action.

            definition

             template< class Source, class Event, class Target,
            +                        

            g_row2

            This is a transition with guard and without action.

            definition

             template< class Source, class Event, class Target,
                                              {
            }
             class CalledForGuard, bool (CalledForGuard::*guard)(Event
            -                                    const&) > _row2 {
            }

            template parameters

            + const&) > _row2 {
            }

            template parameters

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • Target: the target state of the transition.

            • CalledForGuard: the type on which the guard method will be called. It can be either a state of the containing state machine or the state machine itself.

            • guard: a pointer to the method which CalledForGuard provides.

            -

            row2

            This is a transition with guard and action.

            definition

             template< class Source, class Event, class Target,
            +                        

            row2

            This is a transition with guard and action.

            definition

             template< class Source, class Event, class Target,
                                              {
            }
             class CalledForAction, void
                                                 (CalledForAction::*action)(Event const&),  {
            }
             class CalledForGuard, bool (CalledForGuard::*guard)(Event
            -                                    const&) > _row2 {
            }

            template parameters

            + const&) > _row2 {
            }

            template parameters

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • Target: the target state of the transition.

            • CalledForAction: the type on which the action method will be called. It can be either a state of the containing state machine or the state machine itself.

            • action: a pointer to the method which CalledForAction @@ -163,24 +163,24 @@ called. It can be either a state of the containing state machine or the state machine itself.

            • guard: a pointer to the method which CalledForGuard provides.

            -

            a_irow2

            This is an internal transition for use inside a transition table, with - action and without guard.

            definition

             template< class Source, class Event,  {
            }
             class CalledForAction, void
            -                                    (CalledForAction::*action)(Event const&) > _row2 {
            }

            template parameters

            +

            a_irow2

            This is an internal transition for use inside a transition table, with + action and without guard.

            definition

             template< class Source, class Event,  {
            }
             class CalledForAction, void
            +                                    (CalledForAction::*action)(Event const&) > _row2 {
            }

            template parameters

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • CalledForAction: the type on which the action method will be called. It can be either a state of the containing state machine or the state machine itself.

            • action: a pointer to the method which CalledForAction provides.

            -

            g_irow2

            This is an internal transition for use inside a transition table, with - guard and without action.

            definition

             template< class Source, class Event,  {
            }
             class CalledForGuard, bool (CalledForGuard::*guard)(Event
            -                                    const&) > _row2 {
            }

            template parameters

            +

            g_irow2

            This is an internal transition for use inside a transition table, with + guard and without action.

            definition

             template< class Source, class Event,  {
            }
             class CalledForGuard, bool (CalledForGuard::*guard)(Event
            +                                    const&) > _row2 {
            }

            template parameters

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • CalledForGuard: the type on which the guard method will be called. It can be either a state of the containing state machine or the state machine itself.

            • guard: a pointer to the method which CalledForGuard provides.

            -

            irow2

            This is an internal transition for use inside a transition table, with - guard and action.

            definition

             template< class Source, class Event,  {
            }
             class CalledForAction, void
            +                        

            irow2

            This is an internal transition for use inside a transition table, with + guard and action.

            definition

             template< class Source, class Event,  {
            }
             class CalledForAction, void
                                                 (CalledForAction::*action)(Event const&),  {
            }
             class CalledForGuard, bool (CalledForGuard::*guard)(Event
            -                                    const&) > _row2 {
            }

            template parameters

            + const&) > _row2 {
            }

            template parameters

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • CalledForAction: the type on which the action method will be called. It can be either a state of the containing state machine or the state machine itself.

            • action: a pointer to the method which CalledForAction @@ -188,16 +188,16 @@ called. It can be either a state of the containing state machine or the state machine itself.

            • guard: a pointer to the method which CalledForGuard provides.

            -

            msm/front/state_machine_def.hpp

            This header provides the implementation of the basic front-end. It contains one - type, state_machine_def

            state_machine_def definition

            This type is the basic class for a basic (or possibly any other) +

            msm/front/state_machine_def.hpp

            This header provides the implementation of the basic front-end. It contains one + type, state_machine_def

            state_machine_def definition

            This type is the basic class for a basic (or possibly any other) front-end. It provides the standard row types (which includes internal transitions) and a default implementation of the required methods and typedefs.

             template <class Derived,class BaseState =
            -                                default_base_state> state_machine_def {
            }

            typedefs

            + default_base_state> state_machine_def {
            }

            typedefs

            • flag_list: by default, no flag is set in the state machine

            • deferred_events: by default, no event is deferred.

            • configuration: by default, no configuration customization is done.

            -

            row methods

            Like any other front-end, the following transition row types +

            row methods

            Like any other front-end, the following transition row types implements the two necessary static functions for action and guard call. Each function receives as parameter the (deepest-level) state machine processsing the event, the event itself, the source and target states @@ -209,30 +209,30 @@ class AllStates> static bool guard_call(

            ); 
            (Fsm& fsm,Event const& evt,SourceState&,TargetState,AllStates&) - ;
             

            a_row

            This is a transition with action and without guard.

            template< class Source, class Event, class Target, + ;

             

            a_row

            This is a transition with action and without guard.

            template< class Source, class Event, class Target, void (Derived::*action)(Event const&) > a_row

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • Target: the target state of the transition.

            • action: a pointer to the method provided by the concrete - front-end (represented by Derived).

            g_row

            This is a transition with guard and without action.

            template< class Source, class Event, class Target, + front-end (represented by Derived).

            g_row

            This is a transition with guard and without action.

            template< class Source, class Event, class Target, bool (Derived::*guard)(Event const&) > g_row

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • Target: the target state of the transition.

            • guard: a pointer to the method provided by the concrete - front-end (represented by Derived).

            row

            This is a transition with guard and action.

            template< class Source, class Event, class Target, + front-end (represented by Derived).

            row

            This is a transition with guard and action.

            template< class Source, class Event, class Target, void (Derived::*action)(Event const&), bool (Derived::*guard)(Event const&) > row

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • Target: the target state of the transition.

            • action: a pointer to the method provided by the concrete front-end (represented by Derived).

            • guard: a pointer to the method provided by the concrete - front-end (represented by Derived).

            _row

            This is a transition without action or guard. The state machine only + front-end (represented by Derived).

            _row

            This is a transition without action or guard. The state machine only changes active state.

            template< class Source, class Event, class Target > - _row

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • Target: the target state of the transition.

            a_irow

            This is an internal transition for use inside a transition table, with + _row

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • Target: the target state of the transition.

            a_irow

            This is an internal transition for use inside a transition table, with action and without guard.

            template< class Source, class Event, void (Derived::*action)(Event const&) > a_irow

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • action: a pointer to the method provided by the concrete - front-end (represented by Derived).

            g_irow

            This is an internal transition for use inside a transition table, with + front-end (represented by Derived).

            g_irow

            This is an internal transition for use inside a transition table, with guard and without action.

            template< class Source, class Event, bool (Derived::*guard)(Event const&) > g_irow

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • guard: a pointer to the method provided by the concrete - front-end (represented by Derived).

            irow

            This is an internal transition for use inside a transition table, with + front-end (represented by Derived).

            irow

            This is an internal transition for use inside a transition table, with guard and action.

            template< class Source, class Event, void (Derived::*action)(Event const&), bool (Derived::*guard)(Event const&) > irow

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            • action: a pointer to the method provided by the concrete front-end (represented by Derived).

            • guard: a pointer to the method provided by the concrete - front-end (represented by Derived).

            _irow

            This is an internal transition without action or guard. As it does + front-end (represented by Derived).

            _irow

            This is an internal transition without action or guard. As it does nothing, it means "ignore event".

            template< class Source, class Event > - _irow

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            methods

            state_machine_def provides a default implementation in + _irow

            • Event: the event triggering the transition.

            • Source: the source state of the transition.

            methods

            state_machine_def provides a default implementation in case of an event which cannot be processed by a state machine (no transition found). The implementation is using a BOOST_ASSERT so that the error will only be noticed in @@ -256,30 +256,30 @@ (Event const& ,Fsm&, std::exception&) ;

             

            -

            msm/front/states.hpp

            This header provides the different states (except state machines) for the - basic front-end (or mixed with other front-ends).

            types

            This header provides the following types:

            no_sm_ptr

            deprecated: default policy for states. It means that states do not - need to save a pointer to their containing state machine.

            sm_ptr

            deprecated: state policy. It means that states need to save a pointer +

            msm/front/states.hpp

            This header provides the different states (except state machines) for the + basic front-end (or mixed with other front-ends).

            types

            This header provides the following types:

            no_sm_ptr

            deprecated: default policy for states. It means that states do not + need to save a pointer to their containing state machine.

            sm_ptr

            deprecated: state policy. It means that states need to save a pointer to their containing state machine. When seeing this flag, the back-end - will call set_sm_ptr(fsm*) and give itself as argument.

            state

            Basic type for simple states. Inherit from this type to define a + will call set_sm_ptr(fsm*) and give itself as argument.

            state

            Basic type for simple states. Inherit from this type to define a simple state. The first argument is needed if you want your state (and all others used in a concrete state machine) to inherit a basic type for logging or providing a common behavior.

             template<class Base = default_base_state,class
            -                                    SMPtrPolicy = no_sm_ptr> state {
            }

            terminate_state

            Basic type for terminate states. Inherit from this type to define a + SMPtrPolicy = no_sm_ptr> state {
            }

            terminate_state

            Basic type for terminate states. Inherit from this type to define a terminate state. The first argument is needed if you want your state (and all others used in a concrete state machine) to inherit a basic type for logging or providing a common behavior.

             template<class Base = default_base_state,class
            -                                    SMPtrPolicy = no_sm_ptr> terminate_state {
            }

            interrupt_state

            Basic type for interrupt states. Interrupt states prevent any further + SMPtrPolicy = no_sm_ptr> terminate_state {
            }

            interrupt_state

            Basic type for interrupt states. Interrupt states prevent any further event handling until EndInterruptEvent is sent. Inherit from this type to define a terminate state. The first argument is the name of the event ending the interrupt. The second argument is needed if you want your state (and all others used in a concrete state machine) to inherit a basic type for logging or providing a common behavior.

             template<class EndInterruptEvent,class Base =
                                                 default_base_state, {
            }
             class SMPtrPolicy = no_sm_ptr>
            -                                    interrupt_state {
            }

            explicit_entry

            Inherit from this type in + interrupt_state {
            }

            explicit_entry

            Inherit from this type in addition to the desired state type to enable this state for direct entering. The template parameter gives the region id of the state (regions are numbered in the order of the - initial_state typedef).

             template <int ZoneIndex=-1> explicit_entry {
            }

            entry_pseudo_state

            Basic type for entry pseudo states. Entry pseudo states are an + initial_state typedef).

             template <int ZoneIndex=-1> explicit_entry {
            }

            entry_pseudo_state

            Basic type for entry pseudo states. Entry pseudo states are an predefined entry into a submachine and connect two transitions. The first argument is the id of the region entered by this state (regions are numbered in the order of the initial_state typedef). @@ -287,7 +287,7 @@ used in a concrete state machine) to inherit a basic type for logging or providing a common behavior.

             template<int RegionIndex=-1,class Base =
                                                 default_base_state, {
            }
             class SMPtrPolicy = no_sm_ptr>
            -                                    entry_pseudo_state {
            }

            exit_pseudo_state

            Basic type for exit pseudo states. Exit pseudo states are an + entry_pseudo_state {
            }

            exit_pseudo_state

            Basic type for exit pseudo states. Exit pseudo states are an predefined exit from a submachine and connect two transitions. The first argument is the name of the event which will be "thrown" out of the exit point. This event does not need to be the same as the one sent by the @@ -296,32 +296,32 @@ machine) to inherit a basic type for logging or providing a common behavior.

             template<class Event,class Base =
                                                 default_base_state, {
            }
             class SMPtrPolicy = no_sm_ptr>
            -                                    exit_pseudo_state {
            }

            msm/front/euml/euml.hpp

            This header includes all of eUML except the STL functors.

            msm/front/euml/stl.hpp

            This header includes all the functors for STL support in eUML. These tables show a full description.

            msm/front/euml/algorithm.hpp

            This header includes all the functors for STL algorithms support in eUML. + exit_pseudo_state {
            }

            msm/front/euml/euml.hpp

            This header includes all of eUML except the STL functors.

            msm/front/euml/stl.hpp

            This header includes all the functors for STL support in eUML. These tables show a full description.

            msm/front/euml/algorithm.hpp

            This header includes all the functors for STL algorithms support in eUML. These tables show a full - description.

            msm/front/euml/iteration.hpp

            This header includes iteration functors for STL support in eUML. This tables shows a full - description.

            msm/front/euml/querying.hpp

            This header includes querying functors for STL support in eUML. This tables shows a full - description.

            msm/front/euml/transformation.hpp

            This header includes transformation functors for STL support in eUML. This + description.

            msm/front/euml/iteration.hpp

            This header includes iteration functors for STL support in eUML. This tables shows a full + description.

            msm/front/euml/querying.hpp

            This header includes querying functors for STL support in eUML. This tables shows a full + description.

            msm/front/euml/transformation.hpp

            This header includes transformation functors for STL support in eUML. This tables shows a full - description.

            msm/front/euml/container.hpp

            This header includes container functors for STL support in eUML (functors + description.

            msm/front/euml/container.hpp

            This header includes container functors for STL support in eUML (functors calling container methods). This tables shows a full description. It also provides npos for - strings.

            Npos_<container type>

            Functor returning npos for transition or state behaviors. Like all + strings.

            Npos_<container type>

            Functor returning npos for transition or state behaviors. Like all constants, only the functor form exists, so parenthesis are necessary. Example:

            string_find_(event_(m_song),Char_<'S'>(),Size_t_<0>()) != Npos_<string>() // compare result of string::find with - npos

            msm/front/euml/stt_grammar.hpp

            This header provides the transition table grammars. This includes internal - transition tables.

            functions

            build_stt

            The function build_stt evaluates the grammar-conform expression as + npos

            msm/front/euml/stt_grammar.hpp

            This header provides the transition table grammars. This includes internal + transition tables.

            functions

            build_stt

            The function build_stt evaluates the grammar-conform expression as parameter. It returns a transition table, which is a mpl::vector of transitions (rows) or, if the expression is ill-formed (does not match the grammar), the type invalid_type, which will lead to a compile-time static assertion when this transition table is passed to a state machine.

            template<class Expr> [mpl::vector<...> / - msm::front::euml::invalid_type] build_stt(); 
            Expr const& expr;
             

            build_internal_stt

            The function build_internal_stt evaluates the grammar-conform + msm::front::euml::invalid_type] build_stt(

            ); 
            Expr const& expr;
             

            build_internal_stt

            The function build_internal_stt evaluates the grammar-conform expression as parameter. It returns a transition table, which is a mpl::vector of transitions (rows) or, if the expression is ill-formed (does not match the grammar), the type invalid_type, which will lead to a compile-time static assertion when this transition table is passed to a state machine.

            template<class Expr> [mpl::vector<...> / - msm::front::euml::invalid_type] build_internal_stt(); 
            Expr const& expr;
             

            grammars

            transition + msm::front::euml::invalid_type] build_internal_stt(

            ); 
            Expr const& expr;
             

            grammars

            transition table

            The transition table accepts the following grammar:

            Stt := Row | (Stt ',' Stt)
             Row := (Target '==' (SourcePlusEvent)) /* first syntax*/
                    | ( (SourcePlusEvent) '==' Target ) /* second syntax*/
            @@ -346,15 +346,15 @@ target == source + event / action,
             source + event /action == target,
             source / action == target, /*anonymous transition*/
             target == source / action, /*anonymous transition*/
            -source + event /action, /* internal transition*/

            internal transition table

            The internal transition table accepts the following grammar:

            IStt := BuildEvent | (IStt ',' IStt)

            BuildEvent being defined for both internal and standard transition - tables.

            msm/front/euml/guard_grammar.hpp

            This header contains the Guard grammar used in the previous +source + event /action, /* internal transition*/

            internal transition table

            The internal transition table accepts the following grammar:

            IStt := BuildEvent | (IStt ',' IStt)

            BuildEvent being defined for both internal and standard transition + tables.

            msm/front/euml/guard_grammar.hpp

            This header contains the Guard grammar used in the previous section. This grammar is long but pretty simple:

            Guard := action_tag | (Guard '&&' Guard) 
                     | (Guard '||' Guard) | ... /* operators*/
                     | (if_then_else_(Guard,Guard,Guard)) | (function (Action,...Action))

            Most C++ operators are supported (address-of is not). With function is meant any eUML predefined function or any self-made (using MSM_EUML_METHOD or MSM_EUML_FUNCTION). Action - is a grammar defined in state_grammar.hpp.

            msm/front/euml/state_grammar.hpp

            This header provides the grammar for actions and the different grammars and - functions to build states using eUML.

            action grammar

            Like the guard grammar, this grammar supports relevant C++ operators and + is a grammar defined in state_grammar.hpp.

            msm/front/euml/state_grammar.hpp

            This header provides the grammar for actions and the different grammars and + functions to build states using eUML.

            action grammar

            Like the guard grammar, this grammar supports relevant C++ operators and eUML functions:

            Action := action_tag | (Action '+' Action) 
                       | ('--' Action) | ... /* operators*/
                       | if_then_else_(Guard,Action,Action) | if_then_(Action) 
            @@ -363,10 +363,10 @@ source + event /action, /* internal transition*/

            attributes

            This grammar is used to add attributes to states (or state machines) or + ^(bitwise), +=, -=, *=, /=, %=, <<=, >>=, <<, >>, =, [].

            attributes

            This grammar is used to add attributes to states (or state machines) or events: It evaluates to a fusion::map. You can use two forms:

            • attributes_ << no_attributes_

            • attributes_ << attribute_1 << ... << attribute_n

            Attributes can be of any default-constructible type (fusion - requirement).

            configure

            This grammar also has two forms:

            • configure_ << no_configure_

            • configure_ << type_1 << ... << + requirement).

            configure

            This grammar also has two forms:

            • configure_ << no_configure_

            • configure_ << type_1 << ... << type_n

            This grammar is used to create inside one syntax:

            • flags: configure_ << some_flag where some_flag inherits from euml_flag<some_flag> or is defined using BOOST_MSM_EUML_FLAG.

            • deferred events: configure_ << some_event @@ -378,12 +378,12 @@ ActionSequence := Action | (Action ',' Action)

              Relevant operators are: + some_config inherits from euml_config<some_config>. At the moment, three predefined objects exist (in msm//front/euml/common.hpp):

              • no_exception: disable catching exceptions

              • no_msg_queue: disable message queue

              • deferred_events: manually enable handling of - deferred events

            initial states

            The grammar to define initial states for a state machine is: init_ + deferred events

            initial states

            The grammar to define initial states for a state machine is: init_ << state_1 << ... << state_n where state_1...state_n inherit from euml_state or is defined using BOOST_MSM_EUML_STATE, BOOST_MSM_EUML_INTERRUPT_STATE, BOOST_MSM_EUML_TERMINATE_STATE, BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE, - BOOST_MSM_EUML_ENTRY_STATE or BOOST_MSM_EUML_EXIT_STATE.

            functions

            build_sm

            This function has several overloads. The return type is not relevant + BOOST_MSM_EUML_ENTRY_STATE or BOOST_MSM_EUML_EXIT_STATE.

            functions

            build_sm

            This function has several overloads. The return type is not relevant to you as only decltype (return type) is what one needs.

            Defines a state machine without entry or exit:

            template <class StateNameTag,class Stt,class Init> func_state_machine<...> build_sm(); 
            Stt ,Init;
             

            Defines a state machine with entry behavior:

            template <class StateNameTag,class Stt,class Init,class Expr1> func_state_machine<...> build_sm(); 
            Stt ,Init,Expr1 const&;
             

            Defines a state machine with entry and exit behaviors:

            template <class StateNameTag,class Stt,class Init,class @@ -402,7 +402,7 @@ ActionSequence := Action | (Action ',' Action)

            Relevant operators are: + Base> func_state_machine<...> build_sm(

            ); 
            Stt ,Init,Expr1 const&, Expr2 const&, Attributes const&, Configure const&, Base;
             

            Notice that this function requires the extra parameter class StateNameTag to disambiguate state machines having the same parameters - but still being different.

            build_state

            This function has several overloads. The return type is not relevant + but still being different.

            build_state

            This function has several overloads. The return type is not relevant to you as only decltype (return type) is what one needs.

            Defines a simple state without entry or exit:

            func_state<class StateNameTag,...> build_state(); 
            ;
             

            Defines a simple state with entry behavior:

            template <class StateNameTag,class Expr1> func_state<...> build_state(); 
            Expr1 const&;
             

            Defines a simple state with entry and exit behaviors:

            template <class StateNameTag,class Expr1, class Expr2> func_state<...> build_state(); 
            Expr1 const&,Expr2 const&;
             

            Defines a simple state with entry, exit behaviors and @@ -418,7 +418,7 @@ ActionSequence := Action | (Action ',' Action)

            Relevant operators are: + func_state<...> build_state(

            ); 
            Expr1 const&, Expr2 const&, Attributes const&, Configure const&, Base;
             

            Notice that this function requires the extra parameter class StateNameTag to disambiguate states having the same parameters but still - being different.

            build_terminate_state

            This function has the same overloads as build_state.

            build_interrupt_state

            This function has several overloads. The return type is not relevant + being different.

            build_terminate_state

            This function has the same overloads as build_state.

            build_interrupt_state

            This function has several overloads. The return type is not relevant to you as only decltype (return type) is what one needs.

            Defines an interrupt state without entry or exit:

            template <class StateNameTag,class EndInterruptEvent> func_state<...> build_interrupt_state(); 
            EndInterruptEvent const&;
             

            Defines an interrupt state with entry behavior:

            - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +struct transition_table : mpl::vector< +// Start Event Target Action Guard +// +---------+------------+-----------+---------------------------+----------------------------+ +a_row< Stopped , play , Playing , &player_::start_playback >, +a_row< Stopped , open_close , Open , &player_::open_drawer >, + _row< Stopped , stop , Stopped >, +// +---------+------------+-----------+---------------------------+----------------------------+ +a_row< Open , open_close , Empty , &player_::close_drawer >, +// +---------+------------+-----------+---------------------------+----------------------------+ +a_row< Empty , open_close , Open , &player_::open_drawer >, + row< Empty , cd_detected, Stopped , &player_::store_cd_info , &player_::good_disk_format >, + row< Empty , cd_detected, Playing , &player_::store_cd_info , &player_::auto_start >, +// +---------+------------+-----------+---------------------------+----------------------------+ +a_row< Playing , stop , Stopped , &player_::stop_playback >, +a_row< Playing , pause , Paused , &player_::pause_playback >, +a_row< Playing , open_close , Open , &player_::stop_and_open >, +// +---------+------------+-----------+---------------------------+----------------------------+ +a_row< Paused , end_pause , Playing , &player_::resume_playback >, +a_row< Paused , stop , Stopped , &player_::stop_playback >, +a_row< Paused , open_close , Open , &player_::stop_and_open > +// +---------+------------+-----------+---------------------------+----------------------------+ +> {}; + You will notice that this is almost exactly our founding example. The only change in the transition table is the different types of transitions (rows). The founding example forces one to define an action method and offers no @@ -870,82 +698,19 @@ typedef msm::back::state_machine<Playing_> Playing; Like for any state machine, one also needs a transition table and an initial state: - struct transition_table : mpl::vector< - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +struct transition_table : mpl::vector< +// Start Event Target Action Guard +// +--------+---------+--------+---------------------------+------+ +a_row< Song1 , NextSong, Song2 , &Playing_::start_next_song >, +a_row< Song2 , NextSong, Song1 , &Playing_::start_prev_song >, +a_row< Song2 , NextSong, Song3 , &Playing_::start_next_song >, +a_row< Song3 , NextSong, Song2 , &Playing_::start_prev_song > +// +--------+---------+--------+---------------------------+------+ +> {}; + + typedef Song1 initial_state; @@ -1728,201 +1493,30 @@ typedef my_initial_event initial_event; Transition table We can change the definition of the simple tutorial's transition table to: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +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 > +// +---------+------------+-----------+---------------------------+----------------------------+ +> {}; + 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 @@ -2065,11 +1659,8 @@ struct Empty : public msm::front::euml::func_state<Empty_Entry,Empty_Exit>{}; <command xml:id="eUML-front-end"/>eUML (experimental) Important note: eUML requires a compiler - supporting the C++0x decltype/typeof feature (for example VC >= 9, g++ >= 4.3. - VC8 supports eUML but will crash with middle-size state machines). More - generally, eUML has experimental status because most compilers will start - crashing when a state machine becomes too big. Only g++ 4.3 (unfortunately not - 4.4 which shows a serious regression) seems perfectly resilient. + supporting Boost.Typeof. More generally, eUML has experimental status because + most compilers will start crashing when a state machine becomes too big.The previous front-ends are simple to write but still force an amount of noise, mostly MPL types, so it would be nice to write code looking like C++ (with a C++ action language) directly inside the transition table, like UML @@ -2108,100 +1699,25 @@ struct Empty : public msm::front::euml::func_state<Empty_Entry,Empty_Exit>{}; The first version looks like a drawn transition in a diagram, the second one seems natural to a C++ developer. The simple transition table written with the previous front-end can now be + xlink:href="#functor-front-end">functor front-end can now be written as: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + BOOST_MSM_EUML_TRANSITION_TABLE(( +Stopped + play [some_guard] / (some_action , start_playback) == Playing , +Stopped + open_close/ open_drawer == Open , +Stopped + stop == Stopped , +Open + open_close / close_drawer == Empty , +Empty + open_close / open_drawer == Open , +Empty + cd_detected [good_disk_format] / store_cd_info == Stopped +),transition_table) Or, using the alternative notation, it can be: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + BOOST_MSM_EUML_TRANSITION_TABLE(( +Playing == Stopped + play [some_guard] / (some_action , start_playback) , +Open == Stopped + open_close/ open_drawer , +Stopped == Stopped + stop , +Empty == Open + open_close / close_drawer , +Open == Empty + open_close / open_drawer , +Stopped == Empty + cd_detected [good_disk_format] / store_cd_info +),transition_table) The transition table now looks like a list of (readable) rules with little noise.UML defines guards between “[ ]” and actions after a “/”, so the chosen @@ -2274,7 +1790,22 @@ struct Empty : public msm::front::euml::func_state<Empty_Entry,Empty_Exit>{}; { template <class Evt,class Fsm,class State> void operator()(Evt const& ,Fsm& ,State& ) { ... } -}; + }; + It is also possible to reuse the functors from the functor front-end. + The syntax is however slightly less comfortable as we need to pretend + creating one on the fly for typeof. For example: + struct start_playback +{ + template <class Fsm,class Evt,class SourceState,class TargetState> + void operator()(Evt const& ,Fsm&,SourceState& ,TargetState& ) + { + ... + } +}; +BOOST_MSM_EUML_TRANSITION_TABLE(( +Playing == Stopped + play / start_playback() , +... +),transition_table) States @@ -2403,22 +1934,8 @@ Empty_impl const Empty; For example, a minimum state machine could be defined as: - - - - - - - - - - - - - - - - + BOOST_MSM_EUML_TRANSITION_TABLE(( +),transition_table) BOOST_MSM_EUML_DECLARE_STATE_MACHINE((transition_table,init_ << Empty ), player_)Please have a look at the player tutorial written using eUML's internals section to know how state ids are generated. + + <command xml:id="back-end-serialization"/>Serialization + A common need is the ability to save a state machine and restore it at a + different time. MSM supports this feature for the basic and functor + front-ends, and in a more limited manner for eUML. MSM supports + boost::serialization out of the box (by offering a serialize + function). Actually, for basic serialization, you need not do much, a MSM + state machine is serializable almost like any other type. Without any + special work, you can make a state machine remember its state, for + example: + + MyFsm fsm; +// write to archive +std::ofstream ofs("fsm.txt"); +// save fsm to archive +{ + boost::archive::text_oarchive oa(ofs); + // write class instance to archive + oa << fsm; +} + + Loading back is very similar: + + MyFsm fsm; +{ + // create and open an archive for input + std::ifstream ifs("fsm.txt"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> fsm; +} + + This will (de)serialize the state machine itself but not the concrete + states' data. This can be done on a per-state basis to reduce the amount of + typing necessary. To allow serialization of a concrete state, provide a + do_serialize typedef and implement the serialize function: + + struct Empty : public msm::front::state<> +{ + // we want Empty to be serialized. First provide the typedef + typedef int do_serialize; + // then implement serialize + template<class Archive> + void serialize(Archive & ar, const unsigned int /* version */) + { + ar & some_dummy_data; + } + Empty():some_dummy_data(0){} + int some_dummy_data; +}; + + You can also serialize data contained in the front-end class. Again, you + need to provide the typedef and implement serialize: + + struct player_ : public msm::front::state_machine_def<player_> +{ + //we might want to serialize some data contained by the front-end + int front_end_data; + player_():front_end_data(0){} + // to achieve this, provide the typedef + typedef int do_serialize; + // and implement serialize + template<class Archive> + void serialize(Archive & ar, const unsigned int ) + { + ar & front_end_data; + } +... +}; + + The saving of the back-end data (the current state(s)) is valid for all + front-ends, so a front-end written using eUML can be serialized. However, to + serialize a concrete state, the macros like + BOOST_MSM_EUML_STATE cannot be used, so the state will have + to be implemented by directly inheriting from + front::euml::euml_state. + This example shows a state machine which we serialize after processing an + event. The Empty state also has some data to serialize. + <command xml:id="backend-base-state"/>Base state type Sometimes, one needs to customize states to avoid repetition and provide a @@ -3323,29 +2920,28 @@ BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(mysubmachine) Supported compilers - MSM was successfully tested with: + For a current status, have a look at the regression tests. + MSM was successfully tested with: - VC8 (please read further), VC9SP1, VC10 Beta 1 and 2 + VC8 (partly), VC9, VC10 - g++ 4.1 and higher + g++ 4.0.1 and higher + + + Intel 10.1 and higher + + + Clang 2.9 Green Hills Software MULTI for ARM v5.0.5 patch 4416 (Simple and Composite tutorials) - - eUML will only work with: - VC8 (partly). You cannot, however use any overloaded function - (like splice) and compile times and RAM consumption explode - - - VC9SP1, VC10 Beta1-2 - - - g++ 4.3 and higher (previous versions lack native typeof - support) + Partial support for IBM compiler VC8 and to some lesser extent VC9 suffer from a bug. Enabling the option @@ -3366,10 +2962,10 @@ BOOST_MSM_BACK_GENERATE_PROCESS_EVENT(mysubmachine) eUML allows very long constructs but will also quickly increase - your compile time on some compilers (VC9, VC10 Beta1) with buggy - decltype support (I suspect some at least quadratic algorithms - there). Even g++ 4.4 shows some regression compared to 4.3 and will - crash if the constructs become too big. + your compile time on some compilers (VC9, VC10) with buggy decltype + support (I suspect some at least quadratic algorithms there). Even + g++ 4.4 shows some regression compared to 4.3 and will crash if the + constructs become too big. Need to overwrite the mpl::vector/list default-size-limit of 20 @@ -3895,7 +3491,25 @@ typename ::boost::enable_if< Version history - From V2.0 to V2.10 + From V2.10 to V2.12 + + + + Support for serialization + + + Possibility to use + normal functors (from functor front-end) in + eUML. + + + Bugfixes + + + + + + From V2.0 to V2.12 diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 54ccbe1..5fb1cbe 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -19,6 +19,7 @@ project msm darwin:off intel:off /boost/test//boost_unit_test_framework/static + /boost/serialization//boost_serialization/static ; test-suite msm-unit-tests @@ -40,5 +41,8 @@ test-suite msm-unit-tests [ run SimpleInternalFunctors.cpp ] [ run SimpleMachine.cpp ] [ run SimpleWithFunctors.cpp ] + [ run Serialize.cpp ] + [ run SerializeWithHistory.cpp ] + [ run SerializeSimpleEuml.cpp ] ; diff --git a/test/Serialize.cpp b/test/Serialize.cpp new file mode 100644 index 0000000..3a1a636 --- /dev/null +++ b/test/Serialize.cpp @@ -0,0 +1,309 @@ +// Copyright 2010 Christophe Henry +// henry UNDERSCORE christophe AT hotmail DOT com +// This is an extended version of the state machine available in the boost::mpl library +// Distributed under the same license as the original. +// Copyright for the original version: +// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed +// under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +// back-end +#include +//front-end +#include +#define BOOST_TEST_MODULE MyTest +#include +// include headers that implement a archive in simple text format +#include +#include +#include + +#include + +namespace msm = boost::msm; +namespace mpl = boost::mpl; + +namespace +{ + // events + struct play {}; + struct end_pause {}; + struct stop {}; + struct pause {}; + struct open_close {}; + + // A "complicated" event type that carries some data. + enum DiskTypeEnum + { + DISK_CD=0, + DISK_DVD=1 + }; + struct cd_detected + { + cd_detected(std::string name, DiskTypeEnum diskType) + : name(name), + disc_type(diskType) + {} + + std::string name; + DiskTypeEnum disc_type; + }; + + // front-end: define the FSM structure + struct player_ : public msm::front::state_machine_def + { + unsigned int start_playback_counter; + unsigned int can_close_drawer_counter; + int front_end_data; + + player_(): + start_playback_counter(0), + can_close_drawer_counter(0), + front_end_data(4) + {} + + //we want to serialize some data contained by the front-end + // to achieve this, ask for it + typedef int do_serialize; + // and provide a serialize + template + void serialize(Archive & ar, const unsigned int ) + { + ar & front_end_data; + } + + // The list of FSM states + struct Empty : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + int some_dummy_data; + // we want Empty to be serialized + typedef int do_serialize; + template + void serialize(Archive & ar, const unsigned int ) + { + ar & some_dummy_data; + } + + }; + struct Open : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + + // sm_ptr still supported but deprecated as functors are a much better way to do the same thing + struct Stopped : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + + struct Playing : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + + // state not defining any entry or exit + struct Paused : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + + // the initial state of the player SM. Must be defined + typedef Empty initial_state; + + // transition actions + void start_playback(play const&) {++start_playback_counter; } + void open_drawer(open_close const&) { } + void store_cd_info(cd_detected const&) { } + void stop_playback(stop const&) { } + void pause_playback(pause const&) { } + void resume_playback(end_pause const&) { } + void stop_and_open(open_close const&) { } + void stopped_again(stop const&){} + // guard conditions + bool good_disk_format(cd_detected const& evt) + { + // to test a guard condition, let's say we understand only CDs, not DVD + if (evt.disc_type != DISK_CD) + { + return false; + } + return true; + } + bool can_close_drawer(open_close const&) + { + ++can_close_drawer_counter; + return true; + } + + typedef player_ p; // makes transition table cleaner + + // Transition table for player + struct transition_table : mpl::vector< + // Start Event Next Action Guard + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Stopped , play , Playing , &p::start_playback >, + a_row < Stopped , open_close , Open , &p::open_drawer >, + _row < Stopped , stop , Stopped >, + // +---------+-------------+---------+---------------------+----------------------+ + g_row < Open , open_close , Empty , &p::can_close_drawer >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Empty , open_close , Open , &p::open_drawer >, + row < Empty , cd_detected , Stopped , &p::store_cd_info ,&p::good_disk_format >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Playing , stop , Stopped , &p::stop_playback >, + a_row < Playing , pause , Paused , &p::pause_playback >, + a_row < Playing , open_close , Open , &p::stop_and_open >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Paused , end_pause , Playing , &p::resume_playback >, + a_row < Paused , stop , Stopped , &p::stop_playback >, + a_row < Paused , open_close , Open , &p::stop_and_open > + // +---------+-------------+---------+---------------------+----------------------+ + > {}; + // Replaces the default no-transition response. + template + void no_transition(Event const& , FSM&,int) + { + BOOST_FAIL("no_transition called!"); + } + // init counters + template + void on_entry(Event const&,FSM& fsm) + { + fsm.template get_state().entry_counter=0; + fsm.template get_state().exit_counter=0; + fsm.template get_state().entry_counter=0; + fsm.template get_state().exit_counter=0; + fsm.template get_state().entry_counter=0; + fsm.template get_state().exit_counter=0; + fsm.template get_state().some_dummy_data=3; + fsm.template get_state().entry_counter=0; + fsm.template get_state().exit_counter=0; + fsm.template get_state().entry_counter=0; + fsm.template get_state().exit_counter=0; + } + + }; + // Pick a back-end + typedef msm::back::state_machine player; + +// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" }; + + + BOOST_AUTO_TEST_CASE( my_test ) + { + player p; + + p.start(); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 1,"Empty entry not called correctly"); + + p.process_event(open_close()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 1,"Empty exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 1,"Open entry not called correctly"); + + // test the serialization + std::ofstream ofs("fsm.txt"); + // save fsm to archive (current state is Open) + { + boost::archive::text_oarchive oa(ofs); + // write class instance to archive + oa << p; + } + // reload fsm in state Open + player p2; + { + // create and open an archive for input + std::ifstream ifs("fsm.txt"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> p2; + } + // we now use p2 as it was loaded + // check that we kept Empty's data value + BOOST_CHECK_MESSAGE(p2.get_state().some_dummy_data == 3,"Empty not deserialized correctly"); + BOOST_CHECK_MESSAGE(p2.front_end_data == 4,"Front-end not deserialized correctly"); + + p.process_event(open_close()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 1,"Open exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 2,"Empty entry not called correctly"); + BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly"); + + p.process_event( + cd_detected("louie, louie",DISK_DVD)); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 1,"Open exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 2,"Empty entry not called correctly"); + + p.process_event( + cd_detected("louie, louie",DISK_CD)); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 2,"Empty exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 1,"Stopped entry not called correctly"); + + p.process_event(play()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 1,"Stopped exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 1,"Playing entry not called correctly"); + BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly"); + + p.process_event(pause()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 1,"Playing exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 1,"Paused entry not called correctly"); + + // go back to Playing + p.process_event(end_pause()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 1,"Paused exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 2,"Playing entry not called correctly"); + + p.process_event(pause()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 2,"Playing exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 2,"Paused entry not called correctly"); + + p.process_event(stop()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 2,"Paused exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 2,"Stopped entry not called correctly"); + + p.process_event(stop()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 2,"Stopped exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 3,"Stopped entry not called correctly"); + } +} +// eliminate object tracking (even if serialized through a pointer) +// at the risk of a programming error creating duplicate objects. +// this is to get rid of warning because p is not const +BOOST_CLASS_TRACKING(player, boost::serialization::track_never) + diff --git a/test/SerializeSimpleEuml.cpp b/test/SerializeSimpleEuml.cpp new file mode 100644 index 0000000..d605f7b --- /dev/null +++ b/test/SerializeSimpleEuml.cpp @@ -0,0 +1,214 @@ +// Copyright 2010 Christophe Henry +// henry UNDERSCORE christophe AT hotmail DOT com +// This is an extended version of the state machine available in the boost::mpl library +// Distributed under the same license as the original. +// Copyright for the original version: +// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed +// under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +#define BOOST_TEST_MODULE MyTest +#include +// include headers that implement a archive in simple text format +#include +#include +#include + +#include + +using namespace std; +using namespace boost::msm::front::euml; +namespace msm = boost::msm; + +namespace +{ + // A "complicated" event type that carries some data. + enum DiskTypeEnum + { + DISK_CD=0, + DISK_DVD=1 + }; + // events + BOOST_MSM_EUML_EVENT(play) + BOOST_MSM_EUML_EVENT(end_pause) + BOOST_MSM_EUML_EVENT(stop) + BOOST_MSM_EUML_EVENT(pause) + BOOST_MSM_EUML_EVENT(open_close) + // A "complicated" event type that carries some data. + BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,cd_name) + BOOST_MSM_EUML_DECLARE_ATTRIBUTE(DiskTypeEnum,cd_type) + BOOST_MSM_EUML_ATTRIBUTES((attributes_ << cd_name << cd_type ), cd_detected_attributes) + BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(cd_detected,cd_detected_attributes) + + //states + BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,entry_counter) + BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,exit_counter) + + BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Empty) + BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Open) + BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Stopped) + BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Playing) + BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),Paused) + + //fsm + BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,start_playback_counter) + BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,can_close_drawer_counter) + BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,test_fct_counter) + BOOST_MSM_EUML_ACTION(No_Transition) + { + template + void operator()(Event const&,FSM&,int) + { + BOOST_FAIL("no_transition called!"); + } + }; + BOOST_MSM_EUML_ACTION(good_disk_format) + { + template + bool operator()(EVT const& evt,FSM&,SourceState& ,TargetState& ) + { + if (evt.get_attribute(cd_type)!=DISK_CD) + { + return false; + } + return true; + } + }; + BOOST_MSM_EUML_TRANSITION_TABLE(( + Playing == Stopped + play / (++fsm_(start_playback_counter),++fsm_(test_fct_counter) ), + Playing == Paused + end_pause , + // +------------------------------------------------------------------------------+ + Empty == Open + open_close / ++fsm_(can_close_drawer_counter), + // +------------------------------------------------------------------------------+ + Open == Empty + open_close , + Open == Paused + open_close , + Open == Stopped + open_close , + Open == Playing + open_close , + // +------------------------------------------------------------------------------+ + Paused == Playing + pause , + // +------------------------------------------------------------------------------+ + Stopped == Playing + stop , + Stopped == Paused + stop , + Stopped == Empty + cd_detected [good_disk_format || + (event_(cd_type)==Int_())] / process_(play) , + Stopped == Stopped + stop + // +------------------------------------------------------------------------------+ + ),transition_table) + + BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT + init_ << Empty, // Init State + no_action, // Entry + no_action, // Exit + attributes_ << start_playback_counter + << can_close_drawer_counter << test_fct_counter, // Attributes + configure_ << no_configure_, // configuration + No_Transition // no_transition handler + ), + player_) //fsm name + + typedef msm::back::state_machine player; + +// static char const* const state_names[] = { "Stopped", "Paused", "Open", "Empty", "Playing" }; + + + BOOST_AUTO_TEST_CASE( my_test ) + { + player p2; + + p2.start(); + BOOST_CHECK_MESSAGE(p2.get_state().get_attribute(entry_counter) == 1, + "Empty entry not called correctly"); + + p2.process_event(open_close()); + BOOST_CHECK_MESSAGE(p2.current_state()[0] == 2,"Open should be active"); //Open + BOOST_CHECK_MESSAGE(p2.get_state().get_attribute(exit_counter) == 1, + "Empty exit not called correctly"); + BOOST_CHECK_MESSAGE(p2.get_state().get_attribute(entry_counter) == 1, + "Open entry not called correctly"); + + // test the serialization + std::ofstream ofs("fsm.txt"); + // save fsm to archive (current state is Open) + { + boost::archive::text_oarchive oa(ofs); + // write class instance to archive + oa << p2; + } + // reload fsm in state Open + player p; + { + // create and open an archive for input + std::ifstream ifs("fsm.txt"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> p; + } + + p.process_event(open_close()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty + + p.process_event( + cd_detected("louie, louie",DISK_DVD)); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Empty should be active"); //Empty + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(exit_counter) == 1, + "Open exit not called correctly"); + + p.process_event( + cd_detected("louie, louie",DISK_CD)); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(entry_counter) == 1, + "Stopped entry not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(exit_counter) == 1, + "Stopped exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(entry_counter) == 1, + "Playing entry not called correctly"); + BOOST_CHECK_MESSAGE(p.get_attribute(start_playback_counter) == 1,"action not called correctly"); + BOOST_CHECK_MESSAGE(p.get_attribute(test_fct_counter) == 1,"action not called correctly"); + + p.process_event(pause()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(exit_counter) == 1, + "Playing exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(entry_counter) == 1, + "Paused entry not called correctly"); + + // go back to Playing + p.process_event(end_pause()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Playing should be active"); //Playing + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(exit_counter) == 1, + "Paused exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(entry_counter) == 2, + "Playing entry not called correctly"); + + p.process_event(pause()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Paused should be active"); //Paused + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(exit_counter) == 2, + "Playing exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(entry_counter) == 2, + "Paused entry not called correctly"); + + p.process_event(stop()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(exit_counter) == 2, + "Paused exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(entry_counter) == 2, + "Stopped entry not called correctly"); + + p.process_event(stop()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(exit_counter) == 2, + "Stopped exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().get_attribute(entry_counter) == 3, + "Stopped entry not called correctly"); + } +} + +// eliminate object tracking (even if serialized through a pointer) +// at the risk of a programming error creating duplicate objects. +// this is to get rid of warning because p is not const +BOOST_CLASS_TRACKING(player, boost::serialization::track_never) diff --git a/test/SerializeWithHistory.cpp b/test/SerializeWithHistory.cpp new file mode 100644 index 0000000..743102e --- /dev/null +++ b/test/SerializeWithHistory.cpp @@ -0,0 +1,365 @@ +// Copyright 2010 Christophe Henry +// henry UNDERSCORE christophe AT hotmail DOT com +// This is an extended version of the state machine available in the boost::mpl library +// Distributed under the same license as the original. +// Copyright for the original version: +// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed +// under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +// back-end +#include +//front-end +#include +#define BOOST_TEST_MODULE MyTest +#include +// include headers that implement a archive in simple text format +#include +#include +#include + +#include + +namespace msm = boost::msm; +namespace mpl = boost::mpl; + +namespace +{ + // events + struct play {}; + struct end_pause {}; + struct stop {}; + struct pause {}; + struct open_close {}; + struct NextSong {}; + struct PreviousSong {}; + struct cd_detected + { + cd_detected(std::string name) + : name(name) + {} + std::string name; + }; + + // front-end: define the FSM structure + struct player_ : public msm::front::state_machine_def + { + unsigned int start_playback_counter; + unsigned int can_close_drawer_counter; + + player_(): + start_playback_counter(0), + can_close_drawer_counter(0) + {} + // The list of FSM states + struct Empty : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + struct Open : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + + // sm_ptr still supported but deprecated as functors are a much better way to do the same thing + struct Stopped : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + + struct Playing_ : public msm::front::state_machine_def + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + unsigned int start_next_song_counter; + unsigned int start_prev_song_guard_counter; + + Playing_(): + start_next_song_counter(0), + start_prev_song_guard_counter(0) + {} + + // The list of FSM states + struct Song1 : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + struct Song2 : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + struct Song3 : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + // the initial state. Must be defined + typedef Song1 initial_state; + // transition actions + void start_next_song(NextSong const&) {++start_next_song_counter; } + void start_prev_song(PreviousSong const&) { } + // guard conditions + bool start_prev_song_guard(PreviousSong const&) {++start_prev_song_guard_counter;return true; } + + typedef Playing_ pl; // makes transition table cleaner + // Transition table for Playing + struct transition_table : mpl::vector4< + // Start Event Next Action Guard + // +---------+-------------+---------+---------------------+----------------------+ + _row < Song1 , NextSong , Song2 >, + row < Song2 , PreviousSong, Song1 , &pl::start_prev_song,&pl::start_prev_song_guard>, + a_row < Song2 , NextSong , Song3 , &pl::start_next_song >, + g_row < Song3 , PreviousSong, Song2 ,&pl::start_prev_song_guard> + // +---------+-------------+---------+---------------------+----------------------+ + > {}; + // Replaces the default no-transition response. + template + void no_transition(Event const&, FSM&,int) + { + BOOST_FAIL("no_transition called!"); + } + }; + // back-end + typedef msm::back::state_machine > > Playing; + + // state not defining any entry or exit + struct Paused : public msm::front::state<> + { + template + void on_entry(Event const&,FSM& ) {++entry_counter;} + template + void on_exit(Event const&,FSM& ) {++exit_counter;} + int entry_counter; + int exit_counter; + }; + + // the initial state of the player SM. Must be defined + typedef Empty initial_state; + + // transition actions + void start_playback(play const&) {++start_playback_counter; } + void open_drawer(open_close const&) { } + void store_cd_info(cd_detected const&) { } + void stop_playback(stop const&) { } + void pause_playback(pause const&) { } + void resume_playback(end_pause const&) { } + void stop_and_open(open_close const&) { } + void stopped_again(stop const&) {} + //guards + bool can_close_drawer(open_close const&) + { + ++can_close_drawer_counter; + return true; + } + + + typedef player_ p; // makes transition table cleaner + + // Transition table for player + struct transition_table : mpl::vector< + // Start Event Next Action Guard + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Stopped , play , Playing , &p::start_playback >, + a_row < Stopped , open_close , Open , &p::open_drawer >, + _row < Stopped , stop , Stopped >, + // +---------+-------------+---------+---------------------+----------------------+ + g_row < Open , open_close , Empty , &p::can_close_drawer >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Empty , open_close , Open , &p::open_drawer >, + a_row < Empty , cd_detected , Stopped , &p::store_cd_info >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Playing , stop , Stopped , &p::stop_playback >, + a_row < Playing , pause , Paused , &p::pause_playback >, + a_row < Playing , open_close , Open , &p::stop_and_open >, + // +---------+-------------+---------+---------------------+----------------------+ + a_row < Paused , end_pause , Playing , &p::resume_playback >, + a_row < Paused , stop , Stopped , &p::stop_playback >, + a_row < Paused , open_close , Open , &p::stop_and_open > + // +---------+-------------+---------+---------------------+----------------------+ + > {}; + // Replaces the default no-transition response. + template + void no_transition(Event const& e, FSM&,int state) + { + BOOST_FAIL("no_transition called!"); + } + // init counters + template + void on_entry(Event const&,FSM& fsm) + { + fsm.template get_state().entry_counter=0; + fsm.template get_state().exit_counter=0; + fsm.template get_state().entry_counter=0; + fsm.template get_state().exit_counter=0; + fsm.template get_state().entry_counter=0; + fsm.template get_state().exit_counter=0; + fsm.template get_state().entry_counter=0; + fsm.template get_state().exit_counter=0; + fsm.template get_state().template get_state().entry_counter=0; + fsm.template get_state().template get_state().exit_counter=0; + fsm.template get_state().template get_state().entry_counter=0; + fsm.template get_state().template get_state().exit_counter=0; + fsm.template get_state().template get_state().entry_counter=0; + fsm.template get_state().template get_state().exit_counter=0; + fsm.template get_state().entry_counter=0; + fsm.template get_state().exit_counter=0; + } + + }; + // Pick a back-end + typedef msm::back::state_machine player; + +// static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" }; + + + BOOST_AUTO_TEST_CASE( my_test ) + { + player p; + + p.start(); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 1,"Empty entry not called correctly"); + + p.process_event(open_close()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 1,"Empty exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 1,"Open entry not called correctly"); + + p.process_event(open_close()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 1,"Open exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 2,"Empty entry not called correctly"); + BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly"); + + p.process_event(cd_detected("louie, louie")); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 2,"Empty exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 1,"Stopped entry not called correctly"); + + p.process_event(play()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 1,"Stopped exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 1,"Playing entry not called correctly"); + BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().current_state()[0] == 0,"Song1 should be active"); + BOOST_CHECK_MESSAGE( + p.get_state().get_state().entry_counter == 1, + "Song1 entry not called correctly"); + + p.process_event(NextSong()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing + BOOST_CHECK_MESSAGE(p.get_state().current_state()[0] == 1,"Song2 should be active"); + BOOST_CHECK_MESSAGE( + p.get_state().get_state().entry_counter == 1, + "Song2 entry not called correctly"); + BOOST_CHECK_MESSAGE( + p.get_state().get_state().exit_counter == 1, + "Song1 exit not called correctly"); + BOOST_CHECK_MESSAGE( + p.get_state().start_next_song_counter == 0, + "submachine action not called correctly"); + + p.process_event(NextSong()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing + BOOST_CHECK_MESSAGE(p.get_state().current_state()[0] == 2,"Song3 should be active"); + BOOST_CHECK_MESSAGE( + p.get_state().get_state().entry_counter == 1, + "Song3 entry not called correctly"); + BOOST_CHECK_MESSAGE( + p.get_state().get_state().exit_counter == 1, + "Song2 exit not called correctly"); + BOOST_CHECK_MESSAGE( + p.get_state().start_next_song_counter == 1, + "submachine action not called correctly"); + + p.process_event(PreviousSong()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing + BOOST_CHECK_MESSAGE(p.get_state().current_state()[0] == 1,"Song2 should be active"); + BOOST_CHECK_MESSAGE( + p.get_state().get_state().entry_counter == 2, + "Song2 entry not called correctly"); + BOOST_CHECK_MESSAGE( + p.get_state().get_state().exit_counter == 1, + "Song3 exit not called correctly"); + BOOST_CHECK_MESSAGE( + p.get_state().start_prev_song_guard_counter == 1, + "submachine guard not called correctly"); + + p.process_event(pause()); + BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused + BOOST_CHECK_MESSAGE(p.get_state().exit_counter == 1,"Playing exit not called correctly"); + BOOST_CHECK_MESSAGE(p.get_state().entry_counter == 1,"Paused entry not called correctly"); + + std::ofstream ofs("fsm.txt"); + // save fsm to archive (current state is Pause, Playing is in Song2) + { + boost::archive::text_oarchive oa(ofs); + // write class instance to archive + oa << p; + } + // reload fsm in state Open + player p2; + { + // create and open an archive for input + std::ifstream ifs("fsm.txt"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> p2; + } + // go back to Playing + p2.process_event(end_pause()); + BOOST_CHECK_MESSAGE(p2.current_state()[0] == 3,"Playing should be active"); //Playing + BOOST_CHECK_MESSAGE(p2.get_state().current_state()[0] == 1,"Song2 should be active"); + + p2.process_event(pause()); + BOOST_CHECK_MESSAGE(p2.current_state()[0] == 4,"Paused should be active"); //Paused + + p2.process_event(stop()); + BOOST_CHECK_MESSAGE(p2.current_state()[0] == 0,"Stopped should be active"); //Stopped + + p2.process_event(stop()); + BOOST_CHECK_MESSAGE(p2.current_state()[0] == 0,"Stopped should be active"); //Stopped + + p2.process_event(play()); + BOOST_CHECK_MESSAGE(p2.get_state().current_state()[0] == 0,"Song1 should be active"); + } +} +// eliminate object tracking (even if serialized through a pointer) +// at the risk of a programming error creating duplicate objects. +// this is to get rid of warning because p is not const +BOOST_CLASS_TRACKING(player, boost::serialization::track_never) +
            template <class StateNameTag,class EndInterruptEvent,class Expr1> func_state<...> @@ -443,7 +443,7 @@ ActionSequence := Action | (Action ',' Action)

            Relevant operators are: + const&, Attributes const&, Configure const&, Base;

             

            Notice that this function requires the extra parameter class StateNameTag to disambiguate states having the same parameters but still - being different.

            build_entry_state

            This function has several overloads. The return type is not relevant + being different.

            build_entry_state

            This function has several overloads. The return type is not relevant to you as only decltype (return type) is what one needs.

            Defines an entry pseudo state without entry or exit:

            template <class StateNameTag,int RegionIndex> entry_func_state<...> build_entry_state(); 
            ;
             

            Defines an entry pseudo state with entry behavior:

            template <class StateNameTag,int RegionIndex,class Expr1> entry_func_state<...> build_entry_state(); 
            Expr1 const&;
             

            Defines an entry pseudo state with entry and exit behaviors:

            template <class StateNameTag,int RegionIndex,class @@ -462,7 +462,7 @@ ActionSequence := Action | (Action ',' Action)

            Relevant operators are: + Base> entry_func_state<...> build_entry_state(

            ); 
            Expr1 const&, Expr2 const&, Attributes const&, Configure const&, Base;
             

            Notice that this function requires the extra parameter class StateNameTag to disambiguate states having the same parameters but still - being different.

            build_exit_state

            This function has several overloads. The return type is not relevant + being different.

            build_exit_state

            This function has several overloads. The return type is not relevant to you as only decltype (return type) is what one needs.

            Defines an exit pseudo state without entry or exit:

            template <class StateNameTag,class Event> exit_func_state<...> build_exit_state(); 
            Event const&;
             

            Defines an exit pseudo state with entry behavior:

            template <class StateNameTag,class Event,class Expr1> exit_func_state<...> build_exit_state(); 
            Event const&,Expr1 const&;
             

            Defines an exit pseudo state with entry and exit behaviors:

            template <class StateNameTag,class Event,class Expr1, @@ -481,8 +481,8 @@ ActionSequence := Action | (Action ',' Action)

            Relevant operators are: + exit_func_state<...> build_exit_state(

            ); 
            Event const&,Expr1 const&, Expr2 const&, Attributes const&, Configure const&, Base;
             

            Notice that this function requires the extra parameter class StateNameTag to disambiguate states having the same parameters but still - being different.

            build_explicit_entry_state

            This function has the same overloads as build_entry_state and - explicit_entry_func_state as return type.

            msm/front/euml/common.hpp

            types

            euml_event

            The basic type for events with eUML.

             template <class EventName> euml_event; {
            }
            struct play : euml_event<play>{};

            euml_state

            The basic type for states with eUML. You will usually not use this + being different.

            build_explicit_entry_state

            This function has the same overloads as build_entry_state and + explicit_entry_func_state as return type.

            msm/front/euml/common.hpp

            types

            euml_event

            The basic type for events with eUML.

             template <class EventName> euml_event; {
            }
            struct play : euml_event<play>{};

            euml_state

            The basic type for states with eUML. You will usually not use this type directly as it is easier to use BOOST_MSM_EUML_STATE, BOOST_MSM_EUML_INTERRUPT_STATE, BOOST_MSM_EUML_TERMINATE_STATE, BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE, BOOST_MSM_EUML_ENTRY_STATE or @@ -493,7 +493,7 @@ ActionSequence := Action | (Action ',' Action)

            Relevant operators are: + void foo() {...} template <class Event,class Fsm> void on_entry(Event const& evt,Fsm& fsm){...} -};

            euml_flag

            The basic type for flags with eUML.

             template <class FlagName> euml_flag; {
            }
            struct PlayingPaused: euml_flag<PlayingPaused>{};

            euml_action

            The basic type for state or transition behaviors and guards with +};

            euml_flag

            The basic type for flags with eUML.

             template <class FlagName> euml_flag; {
            }
            struct PlayingPaused: euml_flag<PlayingPaused>{};

            euml_action

            The basic type for state or transition behaviors and guards with eUML.

             template <class AcionName> euml_action; {
            }
            struct close_drawer : euml_action<close_drawer>
             {
                 template <class Fsm,class Evt,class SourceState,class TargetState>
            @@ -502,41 +502,41 @@ ActionSequence := Action | (Action ',' Action)

            Relevant operators are: + { template <class Event,class Fsm,class State> void operator()(Event const&,Fsm& fsm,State& ){...} -};

            euml_config

            The basic type for configuration possibilities with eUML.

             template <class ConfigName> euml_config; {
            }

            You normally do not use this type directly but instead the instances +};

            euml_config

            The basic type for configuration possibilities with eUML.

             template <class ConfigName> euml_config; {
            }

            You normally do not use this type directly but instead the instances of predefined configuration:

            • no_exception: disable catching exceptions

            • no_msg_queue: disable message queue. The message queue allows you to send an event for procesing while in an event processing.

            • deferred_events: manually enable handling of deferred - events

            invalid_type

            Type returned by grammar parsers if the grammar is invalid. Seeing - this type will result in a static assertion.

            no_action

            Placeholder type for use in entry/exit or transition behaviors, which - does absolutely nothing.

            source_

            Generic object or function for the source state of a given transition:

            • as object: returns by reference the source state of a + events

            invalid_type

            Type returned by grammar parsers if the grammar is invalid. Seeing + this type will result in a static assertion.

            no_action

            Placeholder type for use in entry/exit or transition behaviors, which + does absolutely nothing.

            source_

            Generic object or function for the source state of a given transition:

            • as object: returns by reference the source state of a transition, usually to be used by another function (usually one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION).

              Example:

              some_user_function_(source_)
            • as function: returns by reference the attribute passed as parameter.

              Example: -

              source_(m_counter)++

            target_

            Generic object or function for the target state of a given transition:

            • as object: returns by reference the target state of a +

              source_(m_counter)++

            target_

            Generic object or function for the target state of a given transition:

            • as object: returns by reference the target state of a transition, usually to be used by another function (usually one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION).

              Example:

              some_user_function_(target_)
            • as function: returns by reference the attribute passed as parameter.

              Example: -

              target_(m_counter)++

            state_

            Generic object or function for the state of a given entry / exit +

            target_(m_counter)++

            state_

            Generic object or function for the state of a given entry / exit behavior. state_ means source_ while in the context of an exit behavior and target_ in the context of an entry behavior:

            • as object: returns by reference the current state, usually to be used by another function (usually one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION).

              Example:

              some_user_function_(state_) // calls some_user_function on the current state
            • as function: returns by reference the attribute passed as parameter.

              Example: -

              state_(m_counter)++

            event_

            Generic object or function for the event triggering a given transition +

            state_(m_counter)++

            event_

            Generic object or function for the event triggering a given transition (valid in a transition behavior, as well as in state entry/exit behaviors):

            • as object: returns by reference the event of a transition, usually to be used by another function (usually one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION).

              Example:

              some_user_function_(event_)
            • as function: returns by reference the attribute passed as parameter.

              Example: -

              event_(m_counter)++

            fsm_

            Generic object or function for the state machine containing a given transition:

            • as object: returns by reference the event of a transition, +

              event_(m_counter)++

            fsm_

            Generic object or function for the state machine containing a given transition:

            • as object: returns by reference the event of a transition, usually to be used by another function (usually one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION).

              Example:

              some_user_function_(fsm_)
            • as function: returns by reference the attribute passed as parameter.

              Example: -

              fsm_(m_counter)++

            substate_

            Generic object or function returning a state of a given state machine:

            • with 1 parameter: returns by reference the state passed as +

              fsm_(m_counter)++

            substate_

            Generic object or function returning a state of a given state machine:

            • with 1 parameter: returns by reference the state passed as parameter, usually to be used by another function (usually one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION).

              Example:

              some_user_function_(substate_(my_state))
            • with 2 parameters: returns by reference the state passed @@ -544,46 +544,46 @@ ActionSequence := Action | (Action ',' Action)

              Relevant operators are: + parameter, usually to be used by another function (usually one created by MSM_EUML_METHOD or MSM_EUML_FUNCTION). This makes sense when used in combination with attribute_.

              Example (equivalent to the previous example): -

              some_user_function_(substate_(my_state,fsm_))

            attribute_

            Generic object or function returning the attribute passed (by name) as +

            some_user_function_(substate_(my_state,fsm_))

            attribute_

            Generic object or function returning the attribute passed (by name) as second parameter of the thing passed as first (a state, event or state machine). Example:

            attribute_(substate_(my_state),cd_name_attribute)++

            -

            True_

            Functor returning true for transition or state behaviors. Like all +

            True_

            Functor returning true for transition or state behaviors. Like all constants, only the functor form exists, so parenthesis are necessary. Example:

            if_then_(True_(),/* some action always called*/)

            -

            False_

            Functor returning false for transition or state behaviors. Like all +

            False_

            Functor returning false for transition or state behaviors. Like all constants, only the functor form exists, so parenthesis are necessary. Example:

            if_then_(False_(),/* some action never called */)

            -

            Int_<int value>

            Functor returning an integer value for transition or state behaviors. +

            Int_<int value>

            Functor returning an integer value for transition or state behaviors. Like all constants, only the functor form exists, so parenthesis are necessary. Example:

            target_(m_ringing_cpt) = Int_<RINGING_TIME>() // RINGING_TIME is a constant

            -

            Char_<char value>

            Functor returning a char value for transition or state behaviors. Like +

            Char_<char value>

            Functor returning a char value for transition or state behaviors. Like all constants, only the functor form exists, so parenthesis are necessary. Example:

            // look for 'S' in event.m_song
             [string_find_(event_(m_song),Char_<'S'>(),Size_t_<0>()) != Npos_<string>()]

            -

            Size_t_<size_t value>

            Functor returning a size_t value for transition or state behaviors. +

            Size_t_<size_t value>

            Functor returning a size_t value for transition or state behaviors. Like all constants, only the functor form exists, so parenthesis are necessary. Example:

            substr_(event_(m_song),Size_t_<1>()) // returns a substring of event.m_song

            -

            String_ < mpl::string >

            Functor returning a string for transition or state behaviors. Like all +

            String_ < mpl::string >

            Functor returning a string for transition or state behaviors. Like all constants, only the functor form exists, so parenthesis are necessary. Requires boost >= 1.40 for mpl::string.

            Example:

            // adds "Let it be" to fsm.m_src_container
             push_back_(fsm_(m_src_container), String_<mpl::string<'Let','it ','be'> >())

            -

            Predicate_ < some_stl_compatible_functor >

            This functor eUML-enables a STL functor (for use in an algorithm). +

            Predicate_ < some_stl_compatible_functor >

            This functor eUML-enables a STL functor (for use in an algorithm). This is necessary because all what is in the transition table must be a eUML terminal.

            Example:

            //equivalent to: 
             //std::accumulate(fsm.m_vec.begin(),fsm.m_vec.end(),1,std::plus<int>())== 1
             accumulate_(begin_(fsm_(m_vec)),end_(fsm_(m_vec)),Int_<1>(),
            -            Predicate_<std::plus<int> >()) == Int_<1>())

            process_

            This function sends an event to up to 4 state machines by calling + Predicate_<std::plus<int> >()) == Int_<1>())

            process_

            This function sends an event to up to 4 state machines by calling process_event on them:

            • process_(some_event) : processes an event in the current (containing) state machine.

            • process_(some_event [,fsm1...fsm4] ) : processes the same event in the 1-4 state machines passed as - argument.

            process2_

            This function sends an event to up to 3 state machines by calling + argument.

            process2_

            This function sends an event to up to 3 state machines by calling process_event on them and copy-constructing the event from the data passed as second parameter:

            • process2_(some_event, some_data) : processes an event in the current (containing) state machine.

            • process2_(some_event, some_data [,fsm1...fsm3] @@ -593,24 +593,24 @@ accumulate_(begin_(fsm_(m_vec)),end_(fsm_(m_vec)),Int_<1>(), // copy-constructed with event.m_song process2_(NotFound,event_(m_song))

              With the following definitions:

              BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_song)//declaration of m_song
              -NotFound (const string& data) // copy-constructor of NotFound

            is_flag_

            This function tells if a flag is active by calling +NotFound (const string& data) // copy-constructor of NotFound

            is_flag_

            This function tells if a flag is active by calling is_flag_active on the current state machine or one passed as parameter:

            • is_flag_(some_flag) : calls is_flag_active on the current (containing) state machine.

            • is_flag_(some_flag, some_fsm) :calls is_flag_active on the state machine.passed - as argument.

            defer_

            This object defers the current event by calling + as argument.

            defer_

            This object defers the current event by calling defer_event on the current state machine. - Example:

            Empty() + play() / defer_

            explicit_(submachine-name,state-name)

            Used as transition's target, causes an explicit entry into the given + Example:

            Empty() + play() / defer_

            explicit_(submachine-name,state-name)

            Used as transition's target, causes an explicit entry into the given state from the given submachine. Several explicit_ as targets, separated by commas, means a fork. The state must have been declared as such using - BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE.

            entry_pt_(submachine-name,state-name)

            Used as transition's target from a containing state machine, causes + BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE.

            entry_pt_(submachine-name,state-name)

            Used as transition's target from a containing state machine, causes submachine-name to be entered using the given entry pseudo-state. This state must have been declared as pseudo entry using - BOOST_MSM_EUML_ENTRY_STATE.

            exit_pt_(submachine-name,state-name)

            Used as transition's source from a containing state machine, causes + BOOST_MSM_EUML_ENTRY_STATE.

            exit_pt_(submachine-name,state-name)

            Used as transition's source from a containing state machine, causes submachine-name to be left using the given exit pseudo-state. This state must have been declared as pseudo exit using - BOOST_MSM_EUML_EXIT_STATE.

            MSM_EUML_FUNCTION

            This macro creates a eUML function and a functor for use with the + BOOST_MSM_EUML_EXIT_STATE.

            MSM_EUML_FUNCTION

            This macro creates a eUML function and a functor for use with the functor front-end, based on a free function:

            • first parameter: the name of the functor

            • second parameter: the underlying function

            • third parameter: the eUML function name

            • fourth parameter: the return type if used in a transition behavior

            • fifth parameter: the return type if used in a state behavior (entry/exit)

            Note that the function itself can take up to 5 @@ -618,7 +618,7 @@ NotFound (const string& data) // copy-constructor of NotFound

            MSM_EUML_FUNCTION(BinarySearch_,std::binary_search,binary_search_,bool,bool)

            Can be used like:

            binary_search_(begin_(fsm_(m_var)),end_(fsm_(m_var)),Int_<9>())

            -

            MSM_EUML_METHOD

            This macro creates a eUML function and a functor for use with the +

            MSM_EUML_METHOD

            This macro creates a eUML function and a functor for use with the functor front-end, based on a method:

            • first parameter: the name of the functor

            • second parameter: the underlying function

            • third parameter: the eUML function name

            • fourth parameter: the return type if used in a transition behavior

            • fifth parameter: the return type if used in a state behavior (entry/exit)

            Note that the method itself can take up to 4 arguments @@ -630,40 +630,40 @@ NotFound (const string& data) // copy-constructor of NotFound

            Can be used like:

            Empty == Open + open_close / (close_drawer , activate_empty_(target_))

            -

            BOOST_MSM_EUML_ACTION(action-instance-name)

            This macro declares a behavior type and a const instance for use in +

            BOOST_MSM_EUML_ACTION(action-instance-name)

            This macro declares a behavior type and a const instance for use in state or transition behaviors. The action implementation itself follows the macro declaration, for example:

            BOOST_MSM_EUML_ACTION(good_disk_format)
             {
                  template <class Fsm,class Evt,class SourceState,class TargetState>
                  void/bool operator()(Evt const& evt,Fsm&,SourceState& ,TargetState& ){...}
            -};

            BOOST_MSM_EUML_FLAG(flag-instance-name)

            This macro declares a flag type and a const instance for use in - behaviors.

            BOOST_MSM_EUML_FLAG_NAME(flag-instance-name)

            This macro returns the name of the flag type generated by +};

            BOOST_MSM_EUML_FLAG(flag-instance-name)

            This macro declares a flag type and a const instance for use in + behaviors.

            BOOST_MSM_EUML_FLAG_NAME(flag-instance-name)

            This macro returns the name of the flag type generated by BOOST_MSM_EUML_FLAG. You need this where the type is required (usually - with the back-end method is_flag_active). For example:

            fsm.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>()

            BOOST_MSM_EUML_DECLARE_ATTRIBUTE(event-type,event-name)

            This macro declares an attribute called event-name of type event-type. + with the back-end method is_flag_active). For example:

            fsm.is_flag_active<BOOST_MSM_EUML_FLAG_NAME(CDLoaded)>()

            BOOST_MSM_EUML_DECLARE_ATTRIBUTE(event-type,event-name)

            This macro declares an attribute called event-name of type event-type. This attribute can then be made part of an attribute list using - BOOST_MSM_EUML_ATTRIBUTES.

            BOOST_MSM_EUML_ATTRIBUTES(attributes-expression,attributes-name)

            This macro declares an attribute list called attributes-name based on + BOOST_MSM_EUML_ATTRIBUTES.

            BOOST_MSM_EUML_ATTRIBUTES(attributes-expression,attributes-name)

            This macro declares an attribute list called attributes-name based on the expression as first argument. These attributes can then be made part of an event using BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES, of a state as 3rd parameter of BOOST_MSM_EUML_STATE or of a state machine as 5th parameter of BOOST_MSM_EUML_DECLARE_STATE_MACHINE.

            Attributes are added using left-shift, for example:

            // m_song is of type std::string
             BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_song)
             // contains one attribute, m_song
            -BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), FoundDef)

            BOOST_MSM_EUML_EVENT(event-instance name)

            This macro defines an event type (event-instance-name_helper) and +BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), FoundDef)

            BOOST_MSM_EUML_EVENT(event-instance name)

            This macro defines an event type (event-instance-name_helper) and declares a const instance of this event type called event-instance-name - for use in a transition table or state behaviors.

            BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(event-instance-name,attributes)

            This macro defines an event type (event-instance-name_helper) and + for use in a transition table or state behaviors.

            BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(event-instance-name,attributes)

            This macro defines an event type (event-instance-name_helper) and declares a const instance of this event type called event-instance-name for use in a transition table or state behaviors. The event will have as attributes the ones passed by the second argument:

            BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(Found,FoundDef)

            The created event instance supports operator()(attributes) so that

            my_back_end.process_event(Found(some_string))

            - is possible.

            BOOST_MSM_EUML_EVENT_NAME(event-instance-name)

            This macro returns the name of the event type generated by + is possible.

            BOOST_MSM_EUML_EVENT_NAME(event-instance-name)

            This macro returns the name of the event type generated by BOOST_MSM_EUML_EVENT or BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES. You need this where the type is required (usually inside a back-end definition). For example:

            typedef msm::back::state_machine<Playing_,
             msm::back::ShallowHistory<mpl::vector<BOOST_MSM_EUML_EVENT_NAME(end_pause)
             > > > Playing_type;

            -

            BOOST_MSM_EUML_STATE(build-expression,state-instance-name)

            This macro defines a state type (state-instance-name_helper) and +

            BOOST_MSM_EUML_STATE(build-expression,state-instance-name)

            This macro defines a state type (state-instance-name_helper) and declares a const instance of this state type called state-instance-name for use in a transition table or state behaviors.

            There are several possibilitites for the expression syntax:

            • (): state without entry or exit action.

            • (Expr1): state with entry but no exit action.

            • (Expr1,Expr2): state with entry and exit action.

            • (Expr1,Expr2,Attributes): state with entry and exit action, defining some attributes.

            • (Expr1,Expr2,Attributes,Configure): state with entry and @@ -672,7 +672,7 @@ msm::back::ShallowHistory<mpl::vector<BOOST_MSM_EUML_EVENT_NAME(end_pause) events).

            • (Expr1,Expr2,Attributes,Configure,Base): state with entry and exit action, defining some attributes, flags and deferred events (plain msm deferred events) and a - non-default base state (as defined in standard MSM).

            BOOST_MSM_EUML_INTERRUPT_STATE(build-expression,state-instance-name)

            This macro defines an interrupt state type + non-default base state (as defined in standard MSM).

            BOOST_MSM_EUML_INTERRUPT_STATE(build-expression,state-instance-name)

            This macro defines an interrupt state type (state-instance-name_helper) and declares a const instance of this state type called state-instance-name for use in a transition table or state behaviors.

            There are several possibilitites for the expression syntax. In all of @@ -689,7 +689,7 @@ msm::back::ShallowHistory<mpl::vector<BOOST_MSM_EUML_EVENT_NAME(end_pause) interrupt state with entry and exit action, defining some attributes, flags and deferred events (plain msm deferred events) and a non-default base state (as defined in standard - MSM).

            BOOST_MSM_EUML_TERMINATE_STATE(build-expression,state-instance-name)

            This macro defines a terminate pseudo-state type + MSM).

            BOOST_MSM_EUML_TERMINATE_STATE(build-expression,state-instance-name)

            This macro defines a terminate pseudo-state type (state-instance-name_helper) and declares a const instance of this state type called state-instance-name for use in a transition table or state behaviors.

            There are several possibilitites for the expression syntax:

            • (): terminate pseudo-state without entry or exit @@ -703,7 +703,7 @@ msm::back::ShallowHistory<mpl::vector<BOOST_MSM_EUML_EVENT_NAME(end_pause) pseudo-state with entry and exit action, defining some attributes, flags and deferred events (plain msm deferred events) and a non-default base state (as defined in standard - MSM).

            BOOST_MSM_EUML_EXIT_STATE(build-expression,state-instance-name)

            This macro defines an exit pseudo-state type + MSM).

            BOOST_MSM_EUML_EXIT_STATE(build-expression,state-instance-name)

            This macro defines an exit pseudo-state type (state-instance-name_helper) and declares a const instance of this state type called state-instance-name for use in a transition table or state behaviors.

            There are several possibilitites for the expression syntax:

            • (forwarded_event):exit pseudo-state without entry or exit @@ -719,7 +719,7 @@ msm::back::ShallowHistory<mpl::vector<BOOST_MSM_EUML_EVENT_NAME(end_pause) attributes, flags and deferred events (plain msm deferred events) and a non-default base state (as defined in standard MSM).

            Note that the forwarded_event must be constructible from the event - sent by the submachine containing the exit point.

            BOOST_MSM_EUML_ENTRY_STATE(int + sent by the submachine containing the exit point.

            BOOST_MSM_EUML_ENTRY_STATE(int region-index,build-expression,state-instance-name)

            This macro defines an entry pseudo-state type (state-instance-name_helper) and declares a const instance of this state type called state-instance-name for use in a transition table or state @@ -734,7 +734,7 @@ msm::back::ShallowHistory<mpl::vector<BOOST_MSM_EUML_EVENT_NAME(end_pause) pseudo-state with entry and exit action, defining some attributes, flags and deferred events (plain msm deferred events) and a non-default base state (as defined in standard - MSM).

            BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE(int + MSM).

            BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE(int region-index,build-expression,state-instance-name)

            This macro defines a submachine's substate type (state-instance-name_helper), which can be explicitly entered and also declares a const instance of this state type called state-instance-name @@ -745,28 +745,28 @@ msm::back::ShallowHistory<mpl::vector<BOOST_MSM_EUML_EVENT_NAME(end_pause) events).

          • (Expr1,Expr2,Attributes,Configure,Base): state with entry and exit action, defining some attributes, flags and deferred events (plain msm deferred events) and a - non-default base state (as defined in standard MSM).

          • BOOST_MSM_EUML_STATE_NAME(state-instance-name)

            This macro returns the name of the state type generated by + non-default base state (as defined in standard MSM).

            BOOST_MSM_EUML_STATE_NAME(state-instance-name)

            This macro returns the name of the state type generated by BOOST_MSM_EUML_STATE or other state macros. You need this where the type is required (usually using a backend function). For example:

            fsm.get_state<BOOST_MSM_EUML_STATE_NAME(StringFind)&>().some_state_function();

            -

            BOOST_MSM_EUML_DECLARE_STATE(build-expression,state-instance-name)

            Like BOOST_MSM_EUML_STATE but does not provide an instance, simply a - type declaration.

            BOOST_MSM_EUML_DECLARE_INTERRUPT_STATE(build-expression,state-instance-name)

            Like BOOST_MSM_EUML_INTERRUPT_STATE but does not provide an instance, - simply a type declaration.

            BOOST_MSM_EUML_DECLARE_TERMINATE_STATE(build-expression,state-instance-name)

            Like BOOST_MSM_EUML_TERMINATE_STATE but does not provide an instance, - simply a type declaration.

            BOOST_MSM_EUML_DECLARE_EXIT_STATE(build-expression,state-instance-name)

            Like BOOST_MSM_EUML_EXIT_STATE but does not provide an instance, - simply a type declaration.

            BOOST_MSM_EUML_DECLARE_ENTRY_STATE(int +

            BOOST_MSM_EUML_DECLARE_STATE(build-expression,state-instance-name)

            Like BOOST_MSM_EUML_STATE but does not provide an instance, simply a + type declaration.

            BOOST_MSM_EUML_DECLARE_INTERRUPT_STATE(build-expression,state-instance-name)

            Like BOOST_MSM_EUML_INTERRUPT_STATE but does not provide an instance, + simply a type declaration.

            BOOST_MSM_EUML_DECLARE_TERMINATE_STATE(build-expression,state-instance-name)

            Like BOOST_MSM_EUML_TERMINATE_STATE but does not provide an instance, + simply a type declaration.

            BOOST_MSM_EUML_DECLARE_EXIT_STATE(build-expression,state-instance-name)

            Like BOOST_MSM_EUML_EXIT_STATE but does not provide an instance, + simply a type declaration.

            BOOST_MSM_EUML_DECLARE_ENTRY_STATE(int region-index,build-expression,state-instance-name)

            Like BOOST_MSM_EUML_ENTRY_STATE but does not provide an instance, - simply a type declaration.

            BOOST_MSM_EUML_DECLARE_EXPLICIT_ENTRY_STATE(int + simply a type declaration.

            BOOST_MSM_EUML_DECLARE_EXPLICIT_ENTRY_STATE(int region-index,build-expression,state-instance-name)

            Like BOOST_MSM_EUML_EXPLICIT_ENTRY_STATE but does not provide an - instance, simply a type declaration.

            BOOST_MSM_EUML_TRANSITION_TABLE(expression, + instance, simply a type declaration.

            BOOST_MSM_EUML_TRANSITION_TABLE(expression, table-instance-name)

            This macro declares a transition table type and also declares a const instance of the table which can then be used in a state machine declaration (see BOOST_MSM_EUML_DECLARE_STATE_MACHINE).The expression must follow the transition - table grammar.

            BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE(iexpression,table-instance-name)

            Like BOOST_MSM_EUML_TRANSITION_TABLE but does not provide an instance, - simply a type declaration.

            BOOST_MSM_EUML_INTERNAL_TRANSITION_TABLE(expression, + table grammar.

            BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE(iexpression,table-instance-name)

            Like BOOST_MSM_EUML_TRANSITION_TABLE but does not provide an instance, + simply a type declaration.

            BOOST_MSM_EUML_INTERNAL_TRANSITION_TABLE(expression, table-instance-name)

            This macro declares a transition table type and also declares a const instance of the table.The expression must follow the transition table - grammar. For the moment, this macro is not used.

            BOOST_MSM_EUML_DECLARE_INTERNAL_TRANSITION_TABLE(iexpression,table-instance-name)

            Like BOOST_MSM_EUML_TRANSITION_TABLE but does not provide an instance, + grammar. For the moment, this macro is not used.

            BOOST_MSM_EUML_DECLARE_INTERNAL_TRANSITION_TABLE(iexpression,table-instance-name)

            Like BOOST_MSM_EUML_TRANSITION_TABLE but does not provide an instance, simply a type declaration. This is currently the only way to declare an internal transition table with eUML. For example:

            BOOST_MSM_EUML_DECLARE_STATE((Open_Entry,Open_Exit),Open_def)
             struct Open_impl : public Open_def
            diff --git a/doc/PDF/examples/Serialize.cpp b/doc/PDF/examples/Serialize.cpp
            new file mode 100644
            index 0000000..dc72c59
            --- /dev/null
            +++ b/doc/PDF/examples/Serialize.cpp
            @@ -0,0 +1,248 @@
            +#include 
            +// back-end
            +#include 
            +//front-end
            +#include 
            +
            +// include headers that implement a archive in simple text format
            +#include 
            +#include 
            +#include 
            +
            +#include 
            +
            +
            +namespace msm = boost::msm;
            +namespace mpl = boost::mpl;
            +
            +
            +namespace
            +{
            +    // events
            +    struct play {};
            +    struct end_pause {};
            +    struct stop {};
            +    struct pause {};
            +    struct open_close {};
            +
            +    // A "complicated" event type that carries some data.
            +	enum DiskTypeEnum
            +    {
            +        DISK_CD=0,
            +        DISK_DVD=1
            +    };
            +    struct cd_detected
            +    {
            +        cd_detected(std::string name, DiskTypeEnum diskType)
            +            : name(name),
            +            disc_type(diskType)
            +        {}
            +
            +        std::string name;
            +        DiskTypeEnum disc_type;
            +    };
            +
            +    // front-end: define the FSM structure 
            +    struct player_ : public msm::front::state_machine_def
            +    {
            +        //we might want to serialize some data contained by the front-end
            +        int front_end_data;
            +        player_():front_end_data(0){}
            +        // to achieve this, ask for it
            +        typedef int do_serialize;
            +        // and provide a serialize
            +        template
            +        void serialize(Archive & ar, const unsigned int )
            +        {
            +            ar & front_end_data;
            +        }
            +        // The list of FSM states
            +        struct Empty : public msm::front::state<> 
            +        {
            +            // we want Empty to be serialized
            +            typedef int do_serialize;
            +            template
            +            void serialize(Archive & ar, const unsigned int )
            +            {
            +                ar & some_dummy_data;
            +            }
            +            Empty():some_dummy_data(0){}
            +            // every (optional) entry/exit methods get the event passed.
            +            template 
            +            void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;}
            +            template 
            +            void on_exit(Event const&,FSM& ) {std::cout << "leaving: Empty" << std::endl;}
            +            int some_dummy_data;
            +        };
            +        struct Open : public msm::front::state<> 
            +        {	 
            +            template 
            +            void on_entry(Event const& ,FSM&) {std::cout << "entering: Open" << std::endl;}
            +            template 
            +            void on_exit(Event const&,FSM& ) {std::cout << "leaving: Open" << std::endl;}
            +        };
            +
            +        // sm_ptr still supported but deprecated as functors are a much better way to do the same thing
            +        struct Stopped : public msm::front::state 
            +        {	 
            +            template 
            +            void on_entry(Event const& ,FSM&) {std::cout << "entering: Stopped" << std::endl;}
            +            template 
            +            void on_exit(Event const&,FSM& ) {std::cout << "leaving: Stopped" << std::endl;}
            +            void set_sm_ptr(player_* pl)
            +            {
            +                m_player=pl;
            +            }
            +            player_* m_player;
            +        };
            +
            +        struct Playing : public msm::front::state<>
            +        {
            +            template 
            +            void on_entry(Event const&,FSM& ) {std::cout << "entering: Playing" << std::endl;}
            +            template 
            +            void on_exit(Event const&,FSM& ) {std::cout << "leaving: Playing" << std::endl;}
            +        };
            +
            +        // state not defining any entry or exit
            +        struct Paused : public msm::front::state<>
            +        {
            +        };
            +
            +        // the initial state of the player SM. Must be defined
            +        typedef Empty initial_state;
            +
            +        // transition actions
            +        void start_playback(play const&)       { std::cout << "player::start_playback\n"; }
            +        void open_drawer(open_close const&)    { std::cout << "player::open_drawer\n"; }
            +        void close_drawer(open_close const&)   { std::cout << "player::close_drawer\n"; }
            +        void store_cd_info(cd_detected const&) { std::cout << "player::store_cd_info\n"; }
            +        void stop_playback(stop const&)        { std::cout << "player::stop_playback\n"; }
            +        void pause_playback(pause const&)      { std::cout << "player::pause_playback\n"; }
            +        void resume_playback(end_pause const&)      { std::cout << "player::resume_playback\n"; }
            +        void stop_and_open(open_close const&)  { std::cout << "player::stop_and_open\n"; }
            +        void stopped_again(stop const&)	{std::cout << "player::stopped_again\n";}
            +        // guard conditions
            +        bool good_disk_format(cd_detected const& evt)
            +        {
            +            // to test a guard condition, let's say we understand only CDs, not DVD
            +            if (evt.disc_type != DISK_CD)
            +            {
            +                std::cout << "wrong disk, sorry" << std::endl;
            +                return false;
            +            }
            +            return true;
            +        }
            +        // used to show a transition conflict. This guard will simply deactivate one transition and thus
            +        // solve the conflict
            +        bool auto_start(cd_detected const&)
            +        {
            +            return false;
            +        }
            +
            +        typedef player_ p; // makes transition table cleaner
            +
            +        // Transition table for player
            +        struct transition_table : mpl::vector<
            +            //    Start     Event         Next      Action				 Guard
            +            //  +---------+-------------+---------+---------------------+----------------------+
            +          a_row < Stopped , play        , Playing , &p::start_playback                         >,
            +          a_row < Stopped , open_close  , Open    , &p::open_drawer                            >,
            +           _row < Stopped , stop        , Stopped                                              >,
            +            //  +---------+-------------+---------+---------------------+----------------------+
            +          a_row < Open    , open_close  , Empty   , &p::close_drawer                           >,
            +            //  +---------+-------------+---------+---------------------+----------------------+
            +          a_row < Empty   , open_close  , Open    , &p::open_drawer                            >,
            +            row < Empty   , cd_detected , Stopped , &p::store_cd_info   ,&p::good_disk_format  >,
            +            row < Empty   , cd_detected , Playing , &p::store_cd_info   ,&p::auto_start        >,
            +            //  +---------+-------------+---------+---------------------+----------------------+
            +          a_row < Playing , stop        , Stopped , &p::stop_playback                          >,
            +          a_row < Playing , pause       , Paused  , &p::pause_playback                         >,
            +          a_row < Playing , open_close  , Open    , &p::stop_and_open                          >,
            +            //  +---------+-------------+---------+---------------------+----------------------+
            +          a_row < Paused  , end_pause   , Playing , &p::resume_playback                        >,
            +          a_row < Paused  , stop        , Stopped , &p::stop_playback                          >,
            +          a_row < Paused  , open_close  , Open    , &p::stop_and_open                          >
            +            //  +---------+-------------+---------+---------------------+----------------------+
            +        > {};
            +        // Replaces the default no-transition response.
            +        template 
            +        void no_transition(Event const& e, FSM&,int state)
            +        {
            +            std::cout << "no transition from state " << state
            +                << " on event " << typeid(e).name() << std::endl;
            +        }
            +    };
            +    // Pick a back-end
            +    typedef msm::back::state_machine player;
            +
            +    //
            +    // Testing utilities.
            +    //
            +    static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
            +    void pstate(player const& p)
            +    {
            +        std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
            +    }
            +
            +    void test()
            +    {        
            +		player p;
            +        // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
            +        p.start(); 
            +        p.get_state().some_dummy_data=3;
            +        p.front_end_data=4;
            +
            +        // go to Open, call on_exit on Empty, then action, then on_entry on Open
            +        p.process_event(open_close()); pstate(p);
            +
            +        std::ofstream ofs("fsm.txt");
            +        // save fsm to archive (current state is Open)
            +        {
            +            boost::archive::text_oarchive oa(ofs);
            +            // write class instance to archive
            +            oa << p;
            +        }
            +        // reload fsm in state Open
            +        player p2;
            +        {
            +            // create and open an archive for input
            +            std::ifstream ifs("fsm.txt");
            +            boost::archive::text_iarchive ia(ifs);
            +            // read class state from archive
            +            ia >> p2;
            +        }
            +        // we now use p2 as it was loaded
            +        // check that we kept Empty's data value
            +        std::cout << "Empty's data should be 3:" << p2.get_state().some_dummy_data << std::endl;
            +        std::cout << "front-end data should be 4:" << p2.front_end_data << std::endl;
            +
            +        p2.process_event(open_close()); pstate(p2);
            +        // will be rejected, wrong disk type
            +        p2.process_event(
            +            cd_detected("louie, louie",DISK_DVD)); pstate(p2);
            +        p2.process_event(
            +            cd_detected("louie, louie",DISK_CD)); pstate(p2);
            +		p2.process_event(play());
            +
            +        // at this point, Play is active      
            +        p2.process_event(pause()); pstate(p2);
            +        // go back to Playing
            +        p2.process_event(end_pause());  pstate(p2);
            +        p2.process_event(pause()); pstate(p2);
            +        p2.process_event(stop());  pstate(p2);
            +        // event leading to the same state
            +        // no action method called as it is not present in the transition table
            +        p2.process_event(stop());  pstate(p2);
            +    }
            +}
            +// eliminate object tracking (even if serialized through a pointer)
            +// at the risk of a programming error creating duplicate objects.
            +// this is to get rid of warning because p is not const
            +BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
            +
            +int main()
            +{
            +    test();
            +    return 0;
            +}
            diff --git a/doc/PDF/examples/SerializeCompositeAndHistory.cpp b/doc/PDF/examples/SerializeCompositeAndHistory.cpp
            new file mode 100644
            index 0000000..9699ab1
            --- /dev/null
            +++ b/doc/PDF/examples/SerializeCompositeAndHistory.cpp
            @@ -0,0 +1,266 @@
            +// Copyright 2010 Christophe Henry
            +// henry UNDERSCORE christophe AT hotmail DOT com
            +// This is an extended version of the state machine available in the boost::mpl library
            +// Distributed under the same license as the original.
            +// Copyright for the original version:
            +// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
            +// under the Boost Software License, Version 1.0. (See accompanying
            +// file LICENSE_1_0.txt or copy at
            +// http://www.boost.org/LICENSE_1_0.txt)
            +
            +#include 
            +// back-end
            +#include 
            +//front-end
            +#include 
            +
            +// include headers that implement a archive in simple text format
            +#include 
            +#include 
            +#include 
            +
            +#include 
            +
            +namespace msm = boost::msm;
            +namespace mpl = boost::mpl;
            +
            +namespace  
            +{
            +    // events
            +    struct play {};
            +    struct end_pause {};
            +    struct stop {};
            +    struct pause {};
            +    struct open_close {};
            +    struct NextSong {};
            +    struct PreviousSong {};
            +
            +    // A "complicated" event type that carries some data.
            +    struct cd_detected
            +    {
            +        cd_detected(std::string name)
            +            : name(name)
            +        {}
            +
            +        std::string name;
            +    };
            +
            +    // front-end: define the FSM structure 
            +    struct player_ : public msm::front::state_machine_def
            +    {
            +        // The list of FSM states
            +        struct Empty : public msm::front::state<> 
            +        {
            +            // every (optional) entry/exit methods get the event passed
            +            template 
            +            void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;}
            +            template 
            +            void on_exit(Event const&,FSM& ) {std::cout << "leaving: Empty" << std::endl;}
            +        };
            +        struct Open : public msm::front::state<> 
            +        { 
            +            template 
            +            void on_entry(Event const&,FSM& ) {std::cout << "entering: Open" << std::endl;}
            +            template 
            +            void on_exit(Event const&,FSM& ) {std::cout << "leaving: Open" << std::endl;}
            +        };
            +
            +        struct Stopped : public msm::front::state<> 
            +        { 
            +            // when stopped, the CD is loaded
            +            template 
            +            void on_entry(Event const&,FSM& ) {std::cout << "entering: Stopped" << std::endl;}
            +            template 
            +            void on_exit(Event const&,FSM& ) {std::cout << "leaving: Stopped" << std::endl;}
            +        };
            +
            +        struct Playing_ : public msm::front::state_machine_def
            +        {
            +            // when playing, the CD is loaded and we are in either pause or playing (duh)
            +            template 
            +            void on_entry(Event const&,FSM& ) {std::cout << "entering: Playing" << std::endl;}
            +            template 
            +            void on_exit(Event const&,FSM& ) {std::cout << "leaving: Playing" << std::endl;}
            +
            +            // The list of FSM states
            +            struct Song1 : public msm::front::state<>
            +            {
            +                template 
            +                void on_entry(Event const&,FSM& ) {std::cout << "starting: First song" << std::endl;}
            +                template 
            +                void on_exit(Event const&,FSM& ) {std::cout << "finishing: First Song" << std::endl;}
            +            };
            +            struct Song2 : public msm::front::state<>
            +            { 
            +                template 
            +                void on_entry(Event const&,FSM& ) {std::cout << "starting: Second song" << std::endl;}
            +                template 
            +                void on_exit(Event const&,FSM& ) {std::cout << "finishing: Second Song" << std::endl;}
            +            };
            +            struct Song3 : public msm::front::state<>
            +            { 
            +                template 
            +                void on_entry(Event const&,FSM& ) {std::cout << "starting: Third song" << std::endl;}
            +                template 
            +                void on_exit(Event const&,FSM& ) {std::cout << "finishing: Third Song" << std::endl;}
            +            };
            +            // the initial state. Must be defined
            +            typedef Song1 initial_state;
            +            // transition actions
            +            void start_next_song(NextSong const&)       { std::cout << "Playing::start_next_song\n"; }
            +            void start_prev_song(PreviousSong const&)       { std::cout << "Playing::start_prev_song\n"; }
            +            // guard conditions
            +
            +            typedef Playing_ pl; // makes transition table cleaner
            +            // Transition table for Playing
            +            struct transition_table : mpl::vector4<
            +                //      Start     Event         Next      Action               Guard
            +                //    +---------+-------------+---------+---------------------+----------------------+
            +                a_row < Song1   , NextSong    , Song2   , &pl::start_next_song                       >,
            +                a_row < Song2   , PreviousSong, Song1   , &pl::start_prev_song                       >,
            +                a_row < Song2   , NextSong    , Song3   , &pl::start_next_song                       >,
            +                a_row < Song3   , PreviousSong, Song2   , &pl::start_prev_song                       >
            +                //    +---------+-------------+---------+---------------------+----------------------+
            +            > {};
            +            // Replaces the default no-transition response.
            +            template 
            +            void no_transition(Event const& e, FSM&,int state)
            +            {
            +                std::cout << "no transition from state " << state
            +                    << " on event " << typeid(e).name() << std::endl;
            +            }
            +
            +        };
            +        // back-end
            +        // demonstrates Shallow History: if the state gets activated with end_pause
            +        // then it will remember the last active state and reactivate it
            +        // also possible: AlwaysHistory, the last active state will always be reactivated
            +        // or NoHistory, always restart from the initial state
            +        typedef msm::back::state_machine > > Playing;
            +
            +        // state not defining any entry or exit
            +        struct Paused : public msm::front::state<>
            +        {
            +            template 
            +            void on_entry(Event const&,FSM& ) {std::cout << "entering: Paused" << std::endl;}
            +            template 
            +            void on_exit(Event const&,FSM& ) {std::cout << "leaving: Paused" << std::endl;}
            +        };
            +
            +        // the initial state of the player SM. Must be defined
            +        typedef Empty initial_state;
            +
            +        // transition actions
            +        void start_playback(play const&)       { std::cout << "player::start_playback\n"; }
            +        void open_drawer(open_close const&)    { std::cout << "player::open_drawer\n"; }
            +        void close_drawer(open_close const&)   { std::cout << "player::close_drawer\n"; }
            +        void store_cd_info(cd_detected const& cd) {std::cout << "player::store_cd_info\n";}
            +        void stop_playback(stop const&)        { std::cout << "player::stop_playback\n"; }
            +        void pause_playback(pause const&)      { std::cout << "player::pause_playback\n"; }
            +        void resume_playback(end_pause const&)      { std::cout << "player::resume_playback\n"; }
            +        void stop_and_open(open_close const&)  { std::cout << "player::stop_and_open\n"; }
            +        void stopped_again(stop const&){std::cout << "player::stopped_again\n";}
            +        // guard conditions
            +
            +        typedef player_ p; // makes transition table cleaner
            +
            +        // Transition table for player
            +        struct transition_table : mpl::vector<
            +            //      Start     Event         Next      Action               Guard
            +            //    +---------+-------------+---------+---------------------+----------------------+
            +            a_row < Stopped , play        , Playing , &p::start_playback                         >,
            +            a_row < Stopped , open_close  , Open    , &p::open_drawer                            >,
            +            a_row < Stopped , stop        , Stopped , &p::stopped_again                          >,
            +            //    +---------+-------------+---------+---------------------+----------------------+
            +            a_row < Open    , open_close  , Empty   , &p::close_drawer                           >,
            +            //    +---------+-------------+---------+---------------------+----------------------+
            +            a_row < Empty   , open_close  , Open    , &p::open_drawer                            >,
            +            a_row < Empty   , cd_detected , Stopped , &p::store_cd_info                          >,
            +            //    +---------+-------------+---------+---------------------+----------------------+
            +            a_row < Playing , stop        , Stopped , &p::stop_playback                          >,
            +            a_row < Playing , pause       , Paused  , &p::pause_playback                         >,
            +            a_row < Playing , open_close  , Open    , &p::stop_and_open                          >,
            +            //    +---------+-------------+---------+---------------------+----------------------+
            +            a_row < Paused  , end_pause   , Playing , &p::resume_playback                        >,
            +            a_row < Paused  , stop        , Stopped , &p::stop_playback                          >,
            +            a_row < Paused  , open_close  , Open    , &p::stop_and_open                          >
            +            //    +---------+-------------+---------+---------------------+----------------------+
            +        > {};
            +
            +        // Replaces the default no-transition response.
            +        template 
            +        void no_transition(Event const& e, FSM&,int state)
            +        {
            +            std::cout << "no transition from state " << state
            +                << " on event " << typeid(e).name() << std::endl;
            +        }
            +
            +    };
            +    // Pick a back-end
            +    typedef msm::back::state_machine player;
            +
            +    //
            +    // Testing utilities.
            +    //
            +    static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
            +
            +    void pstate(player const& p)
            +    {
            +        std::cout << " -> " << state_names[p.current_state()[0]] << std::endl;
            +    }
            +
            +    void test()
            +    {
            +        player p;
            +
            +        // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
            +        p.start(); 
            +        // go to Open, call on_exit on Empty, then action, then on_entry on Open
            +        p.process_event(open_close()); pstate(p);
            +        p.process_event(open_close()); pstate(p);
            +        p.process_event(cd_detected("louie, louie"));
            +        p.process_event(play());
            +
            +        // at this point, Play is active 
            +        // make transition happen inside it. Player has no idea about this event but it's ok.
            +        p.process_event(NextSong());pstate(p); //2nd song active
            +        p.process_event(NextSong());pstate(p);//3rd song active
            +        p.process_event(PreviousSong());pstate(p);//2nd song active
            +        p.process_event(pause()); pstate(p);
            +        std::ofstream ofs("fsm.txt");
            +        // save fsm to archive (current state is Pause, Playing is in Song2)
            +        {
            +            boost::archive::text_oarchive oa(ofs);
            +            // write class instance to archive
            +            oa << p;
            +        }
            +        // reload fsm in state Open
            +        player p2;
            +        {
            +            // create and open an archive for input
            +            std::ifstream ifs("fsm.txt");
            +            boost::archive::text_iarchive ia(ifs);
            +            // read class state from archive
            +            ia >> p2;
            +        }
            +        // go back to Playing
            +        // as you see, remembers the original state as end_pause is an history trigger
            +        p2.process_event(end_pause());  pstate(p2);
            +        p2.process_event(pause()); pstate(p2);
            +        p2.process_event(stop());  pstate(p2);
            +        // event leading to the same state
            +        p2.process_event(stop());  pstate(p2);
            +        // play does not trigger shallow history => start back from 1st song
            +        p2.process_event(play());  pstate(p2);
            +    }
            +}
            +// eliminate object tracking (even if serialized through a pointer)
            +// at the risk of a programming error creating duplicate objects.
            +// this is to get rid of warning because p is not const
            +BOOST_CLASS_TRACKING(player, boost::serialization::track_never)
            +
            +int main()
            +{
            +    test();
            +    return 0;
            +}
            diff --git a/doc/PDF/msm.pdf b/doc/PDF/msm.pdf
            index 959bc25..f3496fa 100644
            Binary files a/doc/PDF/msm.pdf and b/doc/PDF/msm.pdf differ
            diff --git a/doc/src/msm.xml b/doc/src/msm.xml
            index fe2de93..e877df4 100644
            --- a/doc/src/msm.xml
            +++ b/doc/src/msm.xml
            @@ -2,7 +2,7 @@
             
             
                 
            -        Meta State Machine (MSM) V2.10
            +        Meta State Machine (MSM) V2.12
                     
                         Christophe Henry
                         christophe.j.henry@googlemail.com
            @@ -535,202 +535,30 @@
                                 Transition table
                                 As previously stated, MSM is based on the transition table, so let us
                                     define one:
            -                    struct transition_table : mpl::vector<
            -                    
            -                        
            -                            
            //StartEventNextActionGuard
            //+---------+-------------+---------+---------------------+----------------------+
            a_row <Stopped ,play,Playing,&player_::start_playback >,
            a_row <Stopped ,open_close,Open,&player_::open_drawer >,
            _row <Stopped ,stop,Stopped >,
            //+----------------------+---------+---------------------+----------------------+
            a_row <Open ,open_close ,Empty ,&player_::close_drawer >,
            //+---------+-------------+---------+---------------------+----------------------+
            a_row <Empty ,open_close ,Open ,&player_::open_drawer >,
            row <Empty ,cd_detected ,Stopped ,&player_::store_cd_info ,&player_::good_disk_format>,
            row <Empty ,cd_detected ,Playing ,&player_::store_cd_info ,&player_::auto_start>,
            //+---------+-------------+---------+---------------------+----------------------+
            a_row <Playing ,stop ,Stopped ,&player_::stop_playback >,
            a_row <Playing ,pause ,Paused ,&player_::pause_playback >,
            a_row <Playing ,open_close ,Open ,&player_::stop_and_open >,
            //+---------+-------------+---------+---------------------+----------------------+
            a_row < Paused ,end_pause ,Playing ,&player_::resume_playback >,
            a_row < Paused ,stop ,Stopped ,&player_::stop_playback >,
            a_row < Paused ,open_close ,Open ,&player_::stop_and_open >
            //+---------+-------------+---------+---------------------+----------------------+
            > {};
            //StartEventNextActionGuard
            //+---------+-------------+---------+------------------------------+----------------------+
            a_row <Song1 ,NextSong,Song2,&Playing_::start_next_song >,
            a_row <Song2 ,PreviousSong,Song1,&Playing_::start_prev_song >,
            a_row <Song2 ,NextSong,Song3,&Playing_::start_next_song >,
            a_row <Song3 ,PreviousSong ,Song2 ,&Playing_::start_prev_song >
            //+---------+-------------+---------+------------------------------+----------------------+
            > {};
            //StartEventNextActionGuard
            //+---------+-------------+---------+---------------------+----------------------+
            Row <Stopped ,play,Playing,start_playback >,
            Row <Stopped ,open_close,Open,open_drawer, none>,
            Row <Stopped ,stop,Stopped, none>,
            //+----------------------+---------+---------------------+----------------------+
            Row <Open ,open_close ,Empty ,close_drawer, none>,
            //+---------+-------------+---------+---------------------+----------------------+
            Row <Empty ,open_close ,Open ,open_drawer >,
            Row <Empty ,cd_detected ,Stopped ,store_cd_info ,good_disk_format>,
            g_row <Empty ,cd_detected ,Playing ,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>
            //+---------+-------------+---------+---------------------+----------------------+
            > {};
            BOOST_MSM_EUML_TRANSITION_TABLE((
            Stopped +play [DummyGuard] / (TestFct,start_playback)== Playing
            Stopped +open_close/ open_drawer== Open
            Stopped +stop== Stopped
            Open +open_close / close_drawer== Empty
            Empty +open_close / open_drawer == Open
            Empty +cd_detected [good_disk_format] / store_cd_info == Stopped
            ),transition_table)
            BOOST_MSM_EUML_TRANSITION_TABLE((
            Playing == Stopped +play [DummyGuard] / (TestFct,start_playback)
            Open ==Stopped +open_close/ open_drawer
            Stopped ==Stopped +stop
            Empty ==Open +open_close / close_drawer
            Open ==Empty +open_close / open_drawer
            Stopped ==Empty +cd_detected [good_disk_format] / store_cd_info
            ),transition_table)
            BOOST_MSM_EUML_TRANSITION_TABLE((
            ),transition_table)