From: Andreas Huber (ah2003_at_[hidden])
Date: 2004-05-23 17:28:41
David Abrahams wrote:
> "Andreas Huber" <ah2003_at_[hidden]> writes:
>>> That seems like a bad limitation, and for me it calls into question
>>> the idea of mapping state exit to destructors. Can you explain why
>>> that's the right design?
>> Yes, there's a lot of evidence that state exit actions must not fail:
>> Say you have a state_machine<> subclass S and an object of that
>> class, which currently resides in state A and state B nested in A
>> (see the picture under Error handling in ratinale.html). Inside
>> S::~S, the state machine is terminated what leads to the exit
>> actions of B and A being executed. If B's exit action fails, what
>> can you do with the resulting exception? I guess we agree that you
>> cannot propagate it out of S::~S.
> You miss my point. I know destructors must not fail. I am suggesting
> that it may have been the wrong decision to represent state exit
> actions with destructors; you could've used some other protocol.
I don't think I have missed your point and I know that I'm talking to an
exception handling expert. Have you read that whole paragraph? Agreed, after
posting I noticed that the first half isn't exactly the best explanation of
why exit actions must not fail. However, I believe that the second half is a
good argument why throwing exit actions are a bad idea:
... However, even if exit actions are called in the
course of a normal transition what are you going to do if B's exit action
throws an exception? Technically, the state machine still resides in B, so
you have pretty few options for continuing. You cannot exit A as that would
violate the state machine invariant that inner states are always exited
before outer states. You cannot make a transition to another state, as that
would also require successful exit from B. So, the only sensible thing is to
try to handle the error inside B's exit action. If the error cannot be
handled there it must either be ignored or, in the case of a really serious
error, be handled with a different mechanism than exceptions.
A maybe more convincing argument:
In the course of a transition a state entry action throws an exception. Note
that the state machine is in an invalid state (unstable) when this happens.
If the state machine does not successfully handle the exception, the
exception must be propagated to the state machine client. Because the state
machine is unstable, it *must* be terminated before propagating to the
client. Termination calls the exit actions of all currently active states.
What are you going to do with exceptions thrown by these exit actions?
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk