The Boost Statechart library is a framework that allows you to quickly
transform a UML statechart into executable C++ code, without needing
to use a code generator. Thanks to support for almost all UML features the
transformation is straight-forward and the resulting C++ code is a nearly
redundancy-free textual description of the statechart.

Finally, users wanting to create even more complex machines and
project architects evaluating Boost.Statechart should also read the
Advanced topics section at the end.
Moreover, reading the Limitations section in the Rationale is
strongly suggested

We will use the simplest possible program to make our first steps. The
statechart ...

... is implemented with the following code:

#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <iostream>
namespace sc = boost::statechart;
// We are declaring all types as structs only to avoid having to
// type public. If you don't mind doing so, you can just as well
// use class.
// We need to forward-declare the initial state because it can
// only be defined at a point where the state machine is
// defined.
struct Greeting;
// Boost.Statechart makes heavy use of the curiously recurring
// template pattern. The deriving class must always be passed as
// the first parameter to all base class templates.
//
// The state machine must be informed which state it has to
// enter when the machine is initiated. That's why Greeting is
// passed as the second template parameter.
struct Machine : sc::state_machine< Machine, Greeting > {};
// For each state we need to define which state machine it
// belongs to and where it is located in the statechart. Both is
// specified with Context argument that is passed to
// simple_state<>. For a flat state machine as we have it here,
// the context is always the state machine. Consequently,
// Machine must be passed as the second template parameter to
// Greeting's base (the Context parameter is explained in more
// detail in the next example).
struct Greeting : sc::simple_state< Greeting, Machine >
{
// Whenever the state machine enters a state, it creates an
// object of the corresponding state class. The object is then
// kept alive as long as the machine remains in the state.
// Finally, the object is destroyed when the state machine
// exits the state. Therefore, a state entry action can be
// defined by adding a constructor and a state exit action can
// be defined by adding a destructor.
Greeting() { std::cout << "Hello World!\n"; } // entry
~Greeting() { std::cout << "Bye Bye World!\n"; } // exit
};
int main()
{
Machine myMachine;
// The machine is not yet running after construction. We start
// it by calling initiate(). This triggers the construction of
// the initial state Greeting
myMachine.initiate();
// When we leave main(), myMachine is destructed what leads to
// the destruction of all currently active states.
return 0;
}

The two buttons are modeled by two events. Moreover, we also define the
necessary states and the initial state. The following code is our
starting point, subsequent code snippets must be inserted:

#include <boost/statechart/event.hpp>
#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
namespace sc = boost::statechart;
struct EvStartStop : sc::event< EvStartStop > {};
struct EvReset : sc::event< EvReset > {};
struct Active;
struct StopWatch : sc::state_machine< StopWatch, Active > {};
struct Stopped;
// The simple_state class template accepts up to four parameters:
// - The third parameter specifies the inner initial state, if
// there is one. Here, only Active has inner states, which is
// why it needs to pass its inner initial state Stopped to its
// base
// - The fourth parameter specifies whether and what kind of
// history is kept
// Active is the outermost state and therefore needs to pass the
// state machine class it belongs to
struct Active : sc::simple_state<
Active, StopWatch, Stopped > {};
// Stopped and Running both specify Active as their Context,
// which makes them nested inside Active
struct Running : sc::simple_state< Running, Active > {};
struct Stopped : sc::simple_state< Stopped, Active > {};
// Because the context of a state must be a complete type (i.e.
// not forward declared), a machine must be defined from
// "outside to inside". That is, we always start with the state
// machine, followed by outermost states, followed by the direct
// inner states of outermost states and so on. We can do so in a
// breadth-first or depth-first way or employ a mixture of the
// two.
int main()
{
StopWatch myWatch;
myWatch.initiate();
return 0;
}

Now we have all the states and all the transitions in place and a number
of events are also sent to the stop watch. The machine dutifully makes the
transitions we would expect, but no actions are executed yet.

Next we'll make the stop watch actually measure time. Depending on the
state the stop watch is in, we need different variables:

Stopped: One variable holding the elapsed time

Running: One variable holding the elapsed time and one
variable storing the point in time at which the watch was last
started.

We observe that the elapsed time variable is needed no matter what state
the machine is in. Moreover, this variable should be reset to 0 when we
send an EvReset event to the machine. The other variable is
only needed while the machine is in the Running state. It should be set to
the current time of the system clock whenever we enter the Running state.
Upon exit we simply subtract the start time from the current system clock
time and add the result to the elapsed time.

The machine now measures the time, but we cannot yet retrieve it from
the main program.

At this point, the advantages of state-local storage (which is still a
relatively little-known feature) may not yet have become apparent. The FAQ
item "What's so cool about state-local
storage?" tries to explain them in more detail by comparing this
StopWatch with one that does not make use of state-local storage.

To retrieve the measured time, we need a mechanism to get state
information out of the machine. With our current machine design there are
two ways to do that. For the sake of simplicity we use the less efficient
one: state_cast<>() (StopWatch2.cpp shows the slightly
more complex alternative). As the name suggests, the semantics are very
similar to the ones of dynamic_cast. For example, when we call
myWatch.state_cast< const Stopped & >()and
the machine is currently in the Stopped state, we get a reference to the
Stopped state. Otherwise std::bad_cast is thrown.
We can use this functionality to implement a StopWatch member
function that returns the elapsed time. However, rather than ask the
machine in which state it is and then switch to different calculations for
the elapsed time, we put the calculation into the Stopped and Running
states and use an interface to retrieve the elapsed time:

So far so good. However, the approach presented above has a few
limitations:

Bad scalability: As soon as the compiler reaches the point where
state_machine::initiate() is called, a number of template
instantiations take place, which can only succeed if the full declaration
of each and every state of the machine is known. That is, the whole
layout of a state machine must be implemented in one single translation
unit (actions can be compiled separately, but this is of no importance
here). For bigger (and more real-world) state machines, this leads to the
following limitations:

At some point compilers reach their internal template
instantiation limits and give up. This can happen even for
moderately-sized machines. For example, in debug mode one popular
compiler refused to compile earlier versions of the BitMachine
example for anything above 3 bits. This means that the compiler
reached its limits somewhere between 8 states, 24 transitions and 16
states, 64 transitions

Multiple programmers can hardly work on the same state machine
simultaneously because every layout change will inevitably lead to a
recompilation of the whole state machine

Maximum one reaction per event: According to UML a state can have
multiple reactions triggered by the same event. This makes sense when all
reactions have mutually exclusive guards. The interface we used above
only allows for at most one unguarded reaction for each event. Moreover,
the UML concepts junction and choice point are not directly
supported

All these limitations can be overcome with custom reactions. Warning:
It is easy to abuse custom reactions up to the point of invoking undefined
behavior. Please study the documentation before employing them!

Let's say your company would like to develop a digital camera. The
camera has the following controls:

Shutter button, which can be half-pressed and fully-pressed. The
associated events are EvShutterHalf,
EvShutterFull and EvShutterReleased

Config button, represented by the EvConfig event

A number of other buttons that are not of interest here

One use case for the camera says that the photographer can half-press
the shutter anywhere in the configuration mode and the camera will
immediately go into shooting mode. The following statechart is one way to
achieve this behavior:

The Configuring and Shooting states will contain numerous nested states
while the Idle state is relatively simple. It was therefore decided to
build two teams. One will implement the shooting mode while the other will
implement the configuration mode. The two teams have already agreed on the
interface that the shooting team will use to retrieve the configuration
settings. We would like to ensure that the two teams can work with the
least possible interference. So, we put the two states in their own
translation units so that machine layout changes within the Configuring
state will never lead to a recompilation of the inner workings of the
Shooting state and vice versa.

Unlike in the previous example, the excerpts presented here often
outline different options to achieve the same effect. That's why the code
is often not equal to the Camera example code. Comments mark the parts
where this is the case.

#include "Camera.hpp"
// The following includes are only made here but not in
// Camera.hpp
// The Shooting and Configuring states can themselves apply the
// same pattern to hide their inner implementation, which
// ensures that the two teams working on the Camera state
// machine will never need to disturb each other.
#include "Configuring.hpp"
#include "Shooting.hpp"
// ...
// not part of the Camera example
sc::result NotShooting::react( const EvShutterHalf & )
{
return transit< Shooting >();
}
sc::result Idle::react( const EvConfig & )
{
return transit< Configuring >();
}

Caution: Any call to
simple_state<>::transit<>() or
simple_state<>::terminate() (see reference) will inevitably destruct the state
object (similar to delete this;)! That is, code executed after
any of these calls may invoke undefined behavior! That's why
these functions should only be called as part of a return statement.

When the user half-presses the shutter, Shooting and its inner initial
state Focusing are entered. In the Focusing entry action the camera
instructs the focusing circuit to bring the subject into focus. The
focusing circuit then moves the lenses accordingly and sends the EvInFocus
event as soon as it is done. Of course, the user can fully-press the
shutter while the lenses are still in motion. Without any precautions, the
resulting EvShutterFull event would simply be lost because the Focusing
state does not define a reaction for this event. As a result, the user
would have to fully-press the shutter again after the camera has finished
focusing. To prevent this, the EvShutterFull event is deferred inside the
Focusing state. This means that all events of this type are stored in a
separate queue, which is emptied into the main queue when the Focusing
state is exited.

Starting from the innermost common context, all entry actions down to
the target state followed by the entry actions of the initial states

Example:

Here the order is as follows: ~D(), ~C(), ~B(), ~A(), t(), X(), Y(),
Z(). The transition action t() is therefore executed in the context of the
InnermostCommonOuter state because the source state has already been left
(destructed) and the target state has not yet been entered
(constructed).

With Boost.Statechart, a transition action can be a member of any
common outer context. That is, the transition between Focusing and Focused
could be implemented as follows:

Non-trivial state machines often need to post internal events. Here's an
example of how to do this:

Pumping::~Pumping()
{
post_event( EvPumpingFinished() );
}

The event is pushed into the main queue. The events in the queue are
processed as soon as the current reaction is completed. Events can be
posted from inside react functions, entry-, exit- and
transition actions. However, posting from inside entry actions is a bit
more complicated (see e.g. Focusing::Focusing() in
Shooting.cpp in the Camera example):

As soon as an entry action of a state needs to contact the "outside
world" (here: the event queue in the state machine), the state must derive
from state<> rather than from
simple_state<> and must implement a forwarding
constructor as outlined above (apart from the constructor,
state<> offers the same interface as
simple_state<>). Hence, this must be done whenever an
entry action makes one or more calls to the following functions:

simple_state<>::post_event()

simple_state<>::clear_shallow_history<>()

simple_state<>::clear_deep_history<>()

simple_state<>::outermost_context()

simple_state<>::context<>()

simple_state<>::state_cast<>()

simple_state<>::state_downcast<>()

simple_state<>::state_begin()

simple_state<>::state_end()

In my experience, these functions are needed only rarely in entry
actions so this workaround should not uglify user code too much.

Photographers testing beta versions of our digital camera
said that they really liked that half-pressing the shutter anytime (even
while the camera is being configured) immediately readies the camera for
picture-taking. However, most of them found it unintuitive that the camera
always goes into the idle mode after releasing the shutter. They would
rather see the camera go back into the state it had before half-pressing
the shutter. This way they can easily test the influence of a configuration
setting by modifying it, half- and then fully-pressing the shutter to take
a picture. Finally, releasing the shutter will bring them back to the
screen where they have modified the setting. To implement this behavior
we'd change the state chart as follows:

As mentioned earlier, the Configuring state contains a fairly complex
and deeply nested inner machine. Naturally, we'd like to restore the
previous state down to the innermost state(s) in Configuring,
that's why we use a deep history pseudo state. The associated code looks as
follows:

History has two phases: Firstly, when the state containing the history
pseudo state is exited, information about the previously active inner state
hierarchy must be saved. Secondly, when a transition to the history pseudo
state is made later, the saved state hierarchy information must be
retrieved and the appropriate states entered. The former is expressed by
passing either has_shallow_history,
has_deep_history or has_full_history (which
combines shallow and deep history) as the last parameter to the
simple_state and state class templates. The
latter is expressed by specifying either
shallow_history<> or deep_history<>
as a transition destination or, as we'll see in an instant, as an inner
initial state. Because it is possible that a state containing a history
pseudo state has never been entered before a transition to history is made,
both class templates demand a parameter specifying the default state to
enter in such situations.

The redundancy necessary for using history is checked for consistency at
compile time. That is, the state machine wouldn't have compiled had we
forgotten to pass has_deep_history to the base of
NotShooting.

Another change request filed by a few beta testers says that they would
like to see the camera go back into the state it had before turning it off
when they turn it back on. Here's the implementation:

Unfortunately, there is a small inconvenience due to some
template-related implementation details. When the inner initial state is a
class template instantiation we always have to put it into an
mpl::list<>, although there is only one inner initial
state. Moreover, the current deep history implementation has some limitations.

orthogonal< 0 > is the default, so
NumLockOn and NumLockOff could just as well pass
Active instead of Active::orthogonal< 0 >
to specify their context. The numbers passed to the orthogonal
member template must correspond to the list position in the outer state.
Moreover, the orthogonal position of the source state of a transition must
correspond to the orthogonal position of the target state. Any violations
of these rules lead to compile time errors. Examples:

Often reactions in a state machine depend on the active state in one or
more orthogonal regions. This is because orthogonal regions are not
completely orthogonal or a certain reaction in an outer state can only take
place if the inner orthogonal regions are in particular states. For this
purpose, the state_cast<> function introduced under
Getting state information
out of the machine is also available within states.

As a somewhat far-fetched example, let's assume that our keyboard also accepts
EvRequestShutdown events, the reception of which makes the
keyboard terminate only if all lock keys are in the off state. We would
then modify the Keyboard state machine as follows:

Passing a pointer type instead of reference type results in 0 pointers
being returned instead of std::bad_cast being thrown when the
cast fails. Note also the use of state_downcast<>()
instead of state_cast<>(). Similar to the differences
between boost::polymorphic_downcast<>() and
dynamic_cast, state_downcast<>() is a much
faster variant of state_cast<>() and can only be used
when the passed type is a most-derived type.
state_cast<>() should only be used if you want to query
an additional base.

Custom state queries

It is often desirable to find out exactly which state(s) a machine
currently resides in. To some extent this is already possible with
state_cast<>() and state_downcast<>()
but their utility is rather limited because both only return a yes/no
answer to the question "Are you in state X?". It is possible to ask more
sophisticated questions when you pass an additional base class rather than
a state class to state_cast<>() but this involves more
work (all states need to derive from and implement the additional base), is
slow (under the hood state_cast<>() uses
dynamic_cast), forces projects to compile with C++ RTTI turned
on and has a negative impact on state entry/exit speed.

Especially for debugging it would be so much more useful being able to
ask "In which state(s) are you?". For this purpose it is possible to
iterate over all active innermost states with
state_machine<>::state_begin() and
state_machine<>::state_end(). Dereferencing the returned
iterator returns a reference to const
state_machine<>::state_base_type, the common base of all
states. We can thus print the currently active state configuration as
follows (see the Keyboard example for the complete code):

If necessary, the outer states can be accessed with
state_machine<>::state_base_type::outer_state_ptr(),
which returns a pointer to const
state_machine<>::state_base_type. When called on an outermost
state this function simply returns 0.

To cut down on executable size some applications must be compiled with
C++ RTTI turned off. This would render the ability to iterate over all
active states pretty much useless if it weren't for the following two
functions:

Both return a value that is comparable via operator==() and
std::less<>. This alone would be enough to implement the
DisplayStateConfiguration function above without the help of
typeid but it is still somewhat cumbersome as a map must be
used to associate the type information values with the state names.

Exceptions can be propagated from all user code except from state
destructors. Out of the box, the state machine framework is configured for
simple exception handling and does not catch any of these exceptions, so
they are immediately propagated to the state machine client. A scope guard
inside the state_machine<> ensures that all state
objects are destructed before the exception is caught by the client. The
scope guard does not attempt to call any exit functions (see
Two stage exit below) that states might define
as these could themselves throw other exceptions which would mask the
original exception. Consequently, if a state machine should do something
more sensible when exceptions are thrown, it has to catch them before they
are propagated into the Boost.Statechart framework. This exception handling
scheme is often appropriate but it can lead to considerable code
duplication in state machines where many actions can trigger exceptions
that need to be handled inside the state machine (see Error handling in the Rationale).
That's why exception handling can be customized through the
ExceptionTranslator parameter of the
state_machine class template. Since the out-of-the box
behavior is to not translate any exceptions, the default argument
for this parameter is null_exception_translator. A
state_machine<> subtype can be configured for advanced
exception handling by specifying the library-supplied
exception_translator<> instead. This way, the following
happens when an exception is propagated from user code:

The exception is caught inside the framework

In the catch block, an exception_thrown event is
allocated on the stack

Also in the catch block, an immediate dispatch of the
exception_thrown event is attempted. That is, possibly
remaining events in the queue are dispatched only after the exception has
been handled successfully

If the exception was handled successfully, the state machine returns
to the client normally. If the exception could not be handled
successfully, the original exception is rethrown so that the client of
the state machine can handle the exception

Successful exception handling

An exception is considered handled successfully, if:

an appropriate reaction for the exception_thrown event
has been found, and

the state machine is in a stable state after the reaction has
completed.

The second condition is important for scenarios 2 and 3 in the next
section. In these scenarios, the state machine is in the middle of a
transition when the exception is handled. The machine would be left in an
invalid state, should the reaction simply discard the event without doing
anything else. exception_translator<> simply rethrows
the original exception if the exception handling was unsuccessful. Just as
with simple exception handling, in this case a scope guard inside the
state_machine<> ensures that all state objects are
destructed before the exception is caught by the client.

Which states can react to an exception_thrown event?

Short answer: If the state machine is stable when the exception is
thrown, the state that caused the exception is first tried for a reaction.
Otherwise the outermost unstable
state is first tried for a reaction.

Longer answer: There are three scenarios:

A react member function propagates an exception
before calling any of the reaction functions or the action
executed during an in-state reaction propagates an exception. The state
that caused the exception is first tried for a reaction, so the following
machine will transit to Defective after receiving an EvStart event:

A state entry action (constructor) propagates an exception:

If there are no orthogonal regions, the direct outer state of the
state that caused the exception is first tried for a reaction, so the
following machine will transit to Defective after trying to enter
Stopped:

If there are orthogonal regions, the outermost unstable state is first tried
for a reaction. The outermost unstable state is found by first
selecting the direct outer state of the state that caused the
exception and then moving outward until a state is found that is
unstable but has no direct or indirect outer states that are
unstable. This more complex rule is necessary because only reactions
associated with the outermost unstable state (or any of its direct or
indirect outer states) are able to bring the machine back into a
stable state. Consider the following statechart:

Whether this state machine will ultimately transition to E or F after
initiation depends on which of the two orthogonal regions is
initiated first. If the upper orthogonal region is initiated first,
the entry sequence is as follows: A, D, B, (exception is thrown).
Both D and B were successfully entered, so B is the outermost
unstable state when the exception is thrown and the machine will
therefore transition to F. However, if the lower orthogonal region is
initiated first, the sequence is as follows: A, B, (exception is
thrown). D was never entered so A is the outermost unstable state
when the exception is thrown and the machine will therefore
transition to E.
In practice these differences rarely matter as top-level error
recovery is adequate for most state machines. However, since the
sequence of initiation is clearly defined (orthogonal region 0 is
always initiated first, then region 1 and so forth), users can
accurately control when and where they want to handle
exceptions

A transition action propagates an exception: The innermost common
outer state of the source and the target state is first tried for a
reaction, so the following machine will transit to Defective after
receiving an EvStartStop event:

As with a normal event, the dispatch algorithm will move outward to find
a reaction if the first tried state does not provide one (or if the
reaction explicitly returned forward_event();). However, in
contrast to normal events, it will give up once it has unsuccessfully tried
an outermost state, so the following machine will not transit to
Defective after receiving an EvNumLockPressed event:

Instead, the machine is terminated and the original exception
rethrown.

Unfortunately, this idiom (using throw; inside a
try block nested inside a catch block) does not
work on at least one very popular compiler. If you have to use one of
these platforms, you can pass a customized exception translator class to
the state_machine class template. This will allow you to
generate different events depending on the type of the exception.

If a simple_state<> or state<>
subtype declares a public member function with the signature void
exit() then this function is called just before the state object is
destructed. As explained under Error
handling in the Rationale, this is useful for two things that would
otherwise be difficult or cumbersome to achieve with destructors only:

To signal a failure in an exit action

To execute certain exit actions only during a transition or a
termination but not when the state machine object is destructed

A few points to consider before employing exit():

There is no guarantee that exit() will be called:

If the client destructs the state machine object without calling
terminate() beforehand then the currently active states
are destructed without calling exit(). This is necessary
because an exception that is possibly thrown from exit()
could not be propagated on to the state machine client

exit() is not called when a previously executed
action propagated an exception and that exception has not (yet) been
handled successfully. This is because a new exception that could
possibly be thrown from exit() would mask the original
exception

A state is considered exited, even if its exit function
propagated an exception. That is, the state object is inevitably
destructed right after calling exit(), regardless of whether
exit() propagated an exception or not. A state machine
configured for advanced exception handling is therefore always unstable
while handling an exception propagated from an exit
function

In a state machine configured for advanced exception handling the
processing rules for an exception event resulting from an exception
propagated from exit() are analogous to the ones defined for
exceptions propagated from state constructors. That is, the outermost
unstable state is first tried for a reaction and the dispatcher then
moves outward until an appropriate reaction is found

Submachines are to event-driven programming what functions are to
procedural programming, reusable building blocks implementing often needed
functionality. The associated UML notation is not entirely clear to me. It
seems to be severely limited (e.g. the same submachine cannot appear in
different orthogonal regions) and does not seem to account for obvious
stuff like e.g. parameters.

Boost.Statechart is completely unaware of submachines but they can be
implemented quite nicely with templates. Here, a submachine is used to
improve the copy-paste implementation of the keyboard machine discussed
under Orthogonal states:

Why asynchronous state machines are necessary

As the name suggests, a synchronous state machine processes each event
synchronously. This behavior is implemented by the
state_machine class template, whose process_event
function only returns after having executed all reactions (including the
ones provoked by internal events that actions might have posted). This
function is strictly non-reentrant (just like all other member functions,
so state_machine<> is not thread-safe). This makes it
difficult for two state_machine<> subtype objects to
communicate via events in a bi-directional fashion correctly, even in a
single-threaded program. For example, state machine A is
in the middle of processing an external event. Inside an action, it decides
to send a new event to state machine B (by calling
B::process_event()). It then "waits" for B to send back an
answer via a boost::function<>-like call-back, which
references A::process_event() and was passed as a data member
of the event. However, while A is "waiting" for B
to send back an event, A::process_event() has not yet returned
from processing the external event and as soon as B answers
via the call-back, A::process_event() is unavoidably
reentered. This all really happens in a single thread, that's why "wait" is
in quotes.

How it works

The asynchronous_state_machine class template has none of
the member functions the state_machine class template has.
Moreover, asynchronous_state_machine<> subtype objects
cannot even be created or destroyed directly. Instead, all these operations
must be performed through the Scheduler object each
asynchronous state machine is associated with. All these
Scheduler member functions only push an appropriate item into
the schedulers' queue and then return immediately. A dedicated thread will
later pop the items out of the queue to have them processed.

Applications will usually first create a
fifo_scheduler<> object and then call
fifo_scheduler<>::create_processor<>() and
fifo_scheduler<>::initiate_processor() to schedule the
creation and initiation of one or more
asynchronous_state_machine<> subtype objects. Finally,
fifo_scheduler<>::operator()() is either called directly
to let the machine(s) run in the current thread, or, a
boost::function<> object referencing
operator()() is passed to a new boost::thread.
Alternatively, the latter could also be done right after constructing the
fifo_scheduler<> object. In the following code, we are
running one state machine in a new boost::thread and the other
in the main thread (see the PingPong example for the full source code):

In all the examples above,
fifo_scheduler<>::operator()() waits on an empty event
queue and will only return after a call to
fifo_scheduler<>::terminate(). The Player
state machine calls this function on its scheduler object right before
terminating.