
Rob Stewart wrote:
Is it? In the current design the state machine object owns the state objects (it does so for good reasons). How can you destruct the state machine object without destructing the state objects (and thus inevitably also exiting them and terminating the state machine as a result)?
You're still collapsing separate concepts.
The current implementation does. I don't think I did with the above reasoning.
I read "in the current design...how can you destruct [sic] the state machine object without destructing [sic] the state objects (and thus...exiting them,..." as clearly linking the ideas. (Points 2 and 4, above.)
I think you misunderstood why this particular discussion stared: Andreas Huber wrote:
Furthermore, it seems as though, if you want that behavior, it's trivial to get it by wrapping the FSM in a derived class whose destructor finalizes the state machine.
Yes, but only at the cost of making the current interface (and implementation) more complex (we'd need to have at least a separate exit() function, right?).
IIRC, with "that behavior" Dave meant that a state machine is terminated on destruction. The rest of the argument then is about whether an interface change is necessary or not (and I still don't see how it could possibly be done without introducing exit()). But this isn't relevant anymore anyway, see below.
If destruction of a state machine involved no exit actions or transitions, but merely released memory and other resources, and similarly, if destruction of state objects involved no actions or transitions, but merely released resources, then management of those objects is simplified. The library can impose upon such objects that no transitions or actions are permitted. This could be handled by tracking a Boolean that indicates whether the FSM was terminated and disallowing any further activity or by simply saying, "I told you so," when things go wrong due to violating that design tenet.
You've lost me here. Can you please rephrase what you mean with this?
If termination of a state machine was a specific action -- either external by calling terminate() -- or internal via a state transition, the resulting FSM seems to me to be more like one would hand code. Is that better? I think so, but I'm no expert. I think that's what another poster was arguing.
I'm actually unsure about this too. It could well be that state_machine<> will lose the terminate() function.
If exit of a state was separate from destruction, it could throw an exception. At that point, the state machine could be declared unstable and could be forcibly terminated. (Remember that Boolean I mentioned?) IOW, you could require that all exceptions be handled specifically via an exception handler installed by the client to turn execeptions into transitions -- I think that's essentially what you've described thus far. Any unhandled exception can be treated like C++ does it: it calls terminate(). (In this case, I mean terminate() for the FSM so that nothing more may occur.)
terminate() is the wrong word for that. In FSM terminology it is clearly defined what termination means.
With your approach, since construction implied entering the initial state, that isn't necessarily possible.
No. There's state_machine<>::initiate().
Sure, you may need to make changes to accommodate the ideas being discussed, but let's focus on the ideas for now. If the ideas prove beneficial, even if you had good reasons to dismiss them previously, then shouldn't we seriously consider them?
Darryl Green convinced me that exit() (or an equivalent feature that allows the user to separate termination from destruction) is sometimes necessary.
Ideally, we need more FSM experts to participate in this discussion in order to bring their experience to bear on the discussion. It seems rather one sided right now (the experienced FSM person on the side of the current design, and the less experienced on the side that's questioning some design decisions).
I think Darryl and Eugene are quite experienced FSM folks... Regards, Andreas