From: Andreas Huber (ah2003_at_[hidden])
Date: 2004-05-27 05:05:16
Robert Bell <belvis <at> imageworks.com> writes:
> > 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).
Why else would you want to change the implementation (while leaving the
interface as is)?
> 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.
Yes, what's so bad about that? We'd have to guarantee the same with entry()
> > 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.
Yes they can. It is clearly defined when state ctors/dtors are called.
> > Even
> > worse, they must not even rely on how many times state ctors/dtors are
> > called.
> They can't rely on the number of times they're called now.
Again, yes they can. The docs clearly define how often they are called.
> > 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
> anyone care?
> > 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.
No, users are directly affected. Assume for a moment that we have entry()/exit
() and that you want to create a non-pod object of type A in the entry action
and destroy it in the exit action. For the reasons given before you cannot do
this in the ctor/dtor. So, your state object cannot have a data member of type
A, instead you need to either have A * (or the smart equivalent) as member. In
entry(), you then allocate a new A object on the heap and set the data member
pointer to that object. In exit() you need to delete the object and set the
pointer back to 0.
> > - 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.
So what exactly are the tradeoffs then, if it isn't performance?
> 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.
How exactly would you want to override entry and exit actions? I mean, I
personally haven't ever seen a framework allowing this, much less UML.
> (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.)
While I do sometimes reuse transition actions, I have never felt the urge to
do so for entry and exit actions. If you need to do that, no problem: Just
call a function from ctor/dtor
> 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.
The objection is that it violates KISS. If there are hard *technical*
arguments in favor of entry()/exit() then I'll happily add them. I hope we
agree that so far no such arguments have been presented.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk