Boost logo

Boost :

From: Andreas Huber (ahd6974-spamgroupstrap_at_[hidden])
Date: 2005-02-13 17:39:27


David Abrahams wrote:
> "Andreas Huber" <ahd6974-spamgroupstrap_at_[hidden]> writes:
>
>> You very often encounter the situation that you need a variable that
>> is only used in a part of a state machine (i.e. only one state or a
>> few states need access to it). IMO, it is good design to confine the
>> lifetime of such a variable so that it will not even exist when the
>> machine does not happen to reside in the states that need access to
>> the variable. Even for a very tiny state machine like the StopWatch
>> in my tutorial it made sense to limit the lifetime of one variable.
>> See http://tinyurl.com/5q9hk (State-local storage) for details.
>
> But as I pointed out and -- you seem to agree -- that variable must
> often persist through several states to which it applies.

Yes, often.

> In that
> case, if you want the lifetime to change based on those states, you
> can't store the variable in the state object.

Not in an innermost state, no. But you can simply store the variable in
an outer state that contains all the states that need to access the
variable. More often than not the outer state already exists for other
reasons (e.g. reactions that all inner states have in common). E.g. in
the StopWatch example, the Active state not only exists so that it can
store the elapsedTime_ member but also because there is a
self-transition that can be triggered when the machine is in either the
Stopped or Running states.

> boost::optional in the
> state machine itself is the proper generalization of the idea.

It makes things global that should rather be left local. Below, as a
counter-measure, you devise a system that does away with one aspect of
the globality (the lifetime). But, other negative aspects of the
globality remain, i.e. you still have to change the FSM class when you
want to introduce a new variable or change an existing one.

>>> it doesn't match up with the domain abstraction of state
>>> machines.
>>
>> How do you come to that conclusion?
>
> I have never seen a formal description of the FSM abstraction that
> described states as carrying additional data inside them. Have you?

No I haven't. To me this just follows naturally and at least a few
boost::fsm users seem to agree. I think it is awkward to store variables
in the state machine object, where they can be accessed from states that
are not supposed to access them. Of course this can be managed by the
framework as you suggest below, but the FSM class still becomes a change
hotspot. To me, such hotspots are an indication that there is something
wrong with the design. Moreover, parameterized states (aka submachines,
which are reusable FSM building blocks) are hard to implement without
state-local storage.

>>> The state's identity should be enough.
>>
>> It is sometimes enough for small simple machines but not almost never
>> for large complex ones.
>
> I believe that auxilliary data is sometimes needed, but I don't
> believe it's ever needed *in the state*. A framework that managed
> auxilliary state data might accept a a structure like this:
>
> mpl::vector<
> // speed applies to the "running" state
> aux_data<&player::speed, running>
>
> // title applies to the "stopped" and "paused" states
> , aux_data<&player::title, stopped, paused>
> >
>
> where speed and title are boost::optional objects that are
> automatically cleared by the state machine framework upon leaving the
> states listed with them.

As outlined above, I think it is more natural and much more obvious to
just store variables in outer states.

Regards,

-- 
Andreas Huber
When replying by private email, please remove the words spam and trap
from the address shown in the header. 

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk