|
Boost : |
From: David Abrahams (dave_at_[hidden])
Date: 2005-02-15 10:08:45
Andreas Huber <ahd6974-spamgroupstrap_at_[hidden]> writes:
> David Abrahams <dave <at> boost-consulting.com> writes:
>>
>> "Andreas Huber" <ahd6974-spamgroupstrap <at> yahoo.com> writes:
>>
>> > David Abrahams wrote:
>> >> "Andreas Huber" <ahd6974-spamgroupstrap <at> yahoo.com> 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.
>>
>> Can't we call that thing "the state's associated data object?"
>
> You mean the variable?
No, I mean the thing you're calling "the state." It's really the
collection of data that is live when the machine is in a particular
state. The machine's state does _not_ correspond to the identity of
that object. Maybe it corresponds to that object's type.
>> Calling it "the state" gives me the willies.
>
> Huh? I don't see where I have called the variable a state, so my
> assumption above must be wrong. I guess you lost me...
Let me know if you're still confused.
>> > 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.
>>
>> Sorry, details please? Where is this example?
>
> http://tinyurl.com/5q9hk (State-local storage)
So, it's a shorthand for writing the same transition to stop out of
all of its substates.
>> Do you agree with Mr. Nasonov that outer states should be implemented
>> as base classes of inner states?
>
> Not as a general rule, no. However, sometimes it can be a valuable way of
> implementing FSMs but this of course limits the value of variables in states,
> see below.
>
>> Because I don't see how the data lifetime issues work out if you do
>> that. Transitioning from INNER1 to INNER2 still causes all the
>> data members of OUTER to be destroyed, because the INNER1/2
>> instances have distinct OUTER sub-objects.
>
> I guess you could copy the relevant portion of the old state object by the
> means of giving each inner state a templated constructor (untested):
Copying data doesn't extend its lifetime; it makes a copy. It may be
important not to destroy the original. Furthermore, the original may
not be copyable.
<snip>
> Anyway, your observation is correct: Without the workaround above,
> there is no difference in lifetime no matter whether you store your
> variable in an innermost state or any of its direct or indirect
> outer states. It gets destructed with each transition. However, such
> variables would still be useful for in-state reactions.
>
> BTW, this lifetime issue is the primary reason why in boost::fsm an
> inner state does not derive from its direct outer state.
I see.
-- Dave Abrahams Boost Consulting www.boost-consulting.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk