
On Saturday 30 August 2008 1:55:57 am Andrey Semashev wrote:
Chris Knight wrote:
I do note my agreement that transition handler concept should be allowed to return values on invalid events rather than be forced to throw exceptions since in many cases an invalid event for a particular state is an error only when viewed at the level of the state machine's "protocol" and often times occurs just as often as the situation in which there is a valid match.
This is somewhat provided with the switch_to<> mechanism however this seems to exist outside the realm of the well-defined state machine's transition rules.
There's no connection between unexpected events handling and the switch_to mechanism. Unexpected events are detected before the FSM has a chance to call switch_to (effectively, such events are detected at compile time).
Sorry, I should have chosen my words more carefully. What I meant by an "invalid event" in this case was really an "error event" - a well defined event that simply is posted from within another event handler to handle protocol level errors. My only point was that one could implement a post_event via the switch_to<> functionality.
This approach forces error handling into what would best be described as the lexer (state_machine::process()'s callee) and thus outside the domain of the state machine.
I disagree. When an event is unexpected, there's no handler in the FSM that would be able to handle it. This is the whole point behind the term "unexpected".
Once again f(x) := "invalid => error" transforms my statements to more sensible ones. :-)
Since, as you said yourself, such unexpected events may actually appear quite often, the library must provide an option to customize the behavior when receiving them. This is accomplished with the unexpected events handler, which is basically a user-provided functor, that is called on such event receipt.
Completely in agreement as there are really 3 forms of events. *) Expected and "correct" ones (a network packet with the next expected seqnum) *) Expected but "incorrect" ones (a packet with a seqnum indicating packet loss) *) Unexpected events (events that do not conform to the state machine)
A better approach would be to allow dynamic posting of events from within transition handlers. These "error events" are thus included in the definition of the state machine's transtition table.
This would make these events quite expected. You can already include such events in the transition table and have the desired behavior. As for event posting, there's been a discussion about it during the review.
Furthermore, while CTM's example fsm does not allow transition handlers to prevent the transition from "matching", it mirrors my internal implementation in most other regards as it too is implemented as fold(transitions_for_current_state, default_event_dispatcher, event_dispatcher<_2, _1>>).
That's because the transition is matched at compile time only.
The last note I would make regards the BOOST_FSM_MUST_HANDLE_ALL_EVENTS macro one uses to enforce compile-time state machine consistency. This is rather a suprise as my expectation would be for this to be an intrinsic function of an fsm.
Do you mean that the FSM should never compile if it detects unexpected events?
Yes. If I say state_machine.process(Logon) when, for instance, the machine is in the Disconnected state I would expect that to be detected by default if for no other reason than the cost of doing so should be trivial/zero since the check is done at compile time. It could potentially matter with the addition of a post_event functionality as that would necessarily add the additional requirement of state machien variant checking in the machine's event double dispatcher that would process and dispatch posted base_events.