|
Boost : |
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2008-08-17 07:00:20
Phil Endecott wrote:
> Dear All,
>
> I have just spent a few minutes comparing an ad-hoc FSM implementation
> with an implementation using the proposed library. The example that
> I've used is the USB device state machine, which I recently had to
> understand for an embedded application, and I've put an image of the
> state graph here:
>
> http://chezphil.org/tmp/fsm.png
[snip]
> Here is my ad-hoc implementation (note that I haven't tried to even
> compile any of this code):
[snip code]
Well, your code is not an FSM. I mean, the usb_device behavior does not
in any way depend on its state. I could simply remove the state variable
and have the same result. And I agree, in case when there are two
variables that need to be changed in arbitrary order, there is no need
in an FSM library (no matter which FSM library we may have in mind).
However, if you try to implement state/event correctness checks and
define the device behavior in each state (given that the behavior
differs, of course), I'm sure that your code will eventually become less
obvious.
> In comparison, here's what I've come up with using Boost.FSM:
[snip]
> The latter is clearly more verbose than the former. Some of the
> verbosity would go if I put the common events (e.g. PowerOff) into a
> base class, but that adds verbosity of its own.
Why? Base classes for states help a lot to reduce code redundancy. I've
attached a slightly modified version of the code above, with base
classes and library-provided events (this allows you not to define event
classes, which also reduces the code). See usb_fsm_state_based.cpp.
> There are a few characteristics of this particular design that favour
> the ad-hoc code. Firstly, the device's behaviour is allowed to be
> undefined if an unexpected event occurs.
IMO, undefined behavior usually is a design flaw, and this case is
clearly one of the "usual" ones. Otherwise, like I said, you don't need
FSM, because its whole purpose is to _define_ the behavior.
> Secondly, many events have the
> same effect irrespective of the state (e.g. power off).
This, as you noted yourself, can be handled with base classes. Also, one
can use transition maps to define state changes, and transition maps
provide an any_state placeholder for this purpose. I've attached another
version of the example with a transition map (see
usb_fsm_transition_based.cpp). Note that all transition logic is
encapsulated in transitions and all processing is in states.
> Finally, the
> effect of events often depends on their data (i.e. zero has a special
> meaning).
In fact, this is quite common, according to my experience. That's why
the events can be processed in run time both in transitions and states.
> Perhaps more complex FSMs would benefit more from what this library
> offers. In that case, can we see an example? I note that this library
> is targeted at simpler FSMs than Boost.Statechart (which I have not
> used). Is there a category of FSMs that are simple enough that
> Boost.Statechart's features are not needed (e.g. hierarchy) yet too
> complex for an ad-hoc implementation?
Generally, if performance matters and if you don't need to span your FSM
across several dlls and you don't need to create an asynchronous FSM,
you should be fine with Boost.FSM. For example, various protocols (INAP,
for what I had experience with) and their clients may benefit from using
Boost.FSM. Simple parsers can also be implemented on top of the library.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk