From: Robert Bell (belvis_at_[hidden])
Date: 2004-05-26 17:34:57
Andreas Huber wrote:
> Robert Bell wrote:
>>Here's one argument in favor of entry()/exit() over
>>constructor/destructor. If you use constructors/destructors, your
>>will be tied if someday you want to change your mind about the
>>implementation of state entry and exit constructing and destructing
>>states (a couple of alternatives have been discussed here, such as
>>constructing states when they're entered but not destroying them when
>>they're exited). If instead you implement entry and exit with entry()
>>and exit() member functions, it doesn't matter if the states are
>>constructed and destructed as they are now, constructed at entry point
>>and destroyed at machine destruction time, or constructed all at once
>>at machine construction time.
>>I don't have any idea if this flexibility is important or not, but if
>>was implementing fsm, I'd consider it.
> Believe me, I *am* considering it. I even started dreaming about it :-).
That happens to me sometimes too. Sometimes I think it's cool. Other
times I think it means I need a vacation. ;-)
> However, no matter from what angle I start to think this through I always
> end up with the same bad feeling. If we introduce entry()/exit() for the
> reasons you give (more flexibility for optimization?)
More flexibility to change the implementation, for any reason (not
necessarily optimization). By using constructors and destructors for
entry and exit, you're telling users that fsm guarantess that States
will be constructed and destroyed at specific times, which means that
for all time fsm must provide those guarantees.
> this essentially means
> to tell the users that they must not under any circumstances rely on when
> exactly constructors and destructors of state objects are called.
Keep in mind that it's entirely possible that I'm missign something.
That said, they can't rely on when exactly constructors and destructors
are called today.
> worse, they must not even rely on how many times state ctors/dtors are
They can't rely on the number of times they're called now.
> Today they might be called exactly as often as entry()/exit() but
> tomorrow they might be called only exactly once.
None of these issues having to do with when and how many times
constructors and destructors are called sound bad to me; why would
> This means that most
> non-POD data members of states need to be created on the heap, as you
> otherwise wouldn't have a chance to create them inside entry() and destroy
> them inside exit(). And believe me, you definitely need to do that when you
> design non-trivial FSMs. Therefore, to me entry()/exit() means falling at
> least halfway back into medieval times where you always had to explictly
> call constructors and destructors yourself (Turbo Pascal).
I don't quite see it this way myself, but in any event, this is a
concern for the implementer of fsm, not a user of fsm.
> Please have a look at the StopWatch example and imagine the additional
> complexity introduced with entry()/exit() (and ctors/dtors called at
> unspecified times). I only want to go there if there are compelling reasons:
> - I believe that boost::fsm is already reasonably fast (and there is still
> some potential for optimization). Nobody who is actually using it has ever
> complained that it is too slow. Someone has even reported that it performs
> "very well".
I'm not so concerned about performance; if the interfaces are reasonably
clean, it can always be optimized later.
> - Nobody has so far presented hard technical facts that support the view
> that mapping entry/exit to ctor/dtor is wrong. To the contrary, I think I
> have almost proved in my discussion with Dave that exit actions must not
> fail and that you *can* recover from failing entry actions.
I'm not so sure there _are_ hard technical facts; there are just two
different interface choices, each with different tradeoffs.
I'm sure you've thought this out more than I have. I'm just coming from
a gut-level reaction I have to linking entry/exit to
construction/destruction. It just feels weird. For example, if entry and
exit actions are things a state "does", then I'd expect them to be
overridable; constructors and destructors can't be overridden.
(In the past, when I've implemented state machines I've made Action a
separate class; that way, Actions are attached to States, which makes it
easier to reuse Actions in different States.)
Don't take this as me saying you're doing it wrong or that fsm is
ill-designed or anything like that. I just wanted to raise a point I
have not yet seen raised, and as I said, you've obviously spent a lot
more time working on this than I. I don't quite understand the objection
to entry() and exit() member functions, but then again I don't have to
understand it for fsm to proceed.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk