Boost logo

Boost Users :

Subject: Re: [Boost-users] [MSM] state transitions and exceptions
From: Stephan Menzel (stephan.menzel_at_[hidden])
Date: 2012-03-30 05:27:37


Christophe,

On Thu, Mar 29, 2012 at 9:46 PM, Christophe Henry
<christophe.j.henry_at_[hidden]> wrote:
> First of all, I have to give a word of caution. The UML Standard does not
> foresee exceptions and they don't mix well with the run-to-completion
> algorithm on which state machines rely. Try to avoid them if you can.

Yes, mum. ;-)
I know, it's quite a pain and I have to deal with that quite often.
Doing UML interface descriptions in common tools expose this
particular problem all the time. In my opinion however, it is a
problem the UML Standard has, not me. *duck*

> Like the no_transition handler, you can overwrite it with your own.
> When this is called, the transition is interrupted where it was and ceases
> processing. This leaves you in a not very desirable state because you have
> been interrupted somewhere in the guard/exit/action/entry chain.
> When this happens, I advise you to process to yourself an error event to
> handle this gracefully. For example:
>
>   template <class FSM,class Event>
>   void exception_caught (Event const&,FSM& fsm,std::exception& )
>   {
>       fsm.process_event(ErrorConnection());
>   }

Yes, that can work. I wasn't aware I can post events from within the
state machine. But they are actually queued, as I see. Nice. It's
getting even better. This should be able to deal with the problem.
Only downside I can see is that I'd need an entry in the transition
table for each state. I already had to adjust those MPL settings. But
this will work, thanks.

> You can prevent MSM from catching the exception by activating in your front
> end a switch:
>
> typedef int no_exception_thrown;
>
> Then, you get the exception thrown from your process_event call.

I think your first solution ist better because it allows me better to
reset internal data to reasonable values.

> In any case, the transition where the exception occurs is terminated and you
> don't need to terminate yourself.

OK, thanks. This should be explicitly stated like that in the
tutorial. Or maybe it is and I just couldn't find it. Maybe there's
room for one of those little chapters titled "exceptions".

On a side note, there also could be room for a few words about how do
I position such a thing in an existing (or new) architecture. Like
best or common practice. When I started to work with it I was entirely
unsure about it. I am here in a MVC arch with basically a GUI and a
backend and threaded multiplexing controller (part of the GUI) ->
backend functions and demultiplexing data signals -> GUI changes. As a
first try, I understood the state machine as part of the controller
logic belonging to one functionality and essentially one widget. Which
meant that the SM was posting events to the backend functions in a
threaded Q. This proved no good as the result of this was that a state
could easily be switched without the backend having reacted yet,
creating races and the possibility of acting twice. So I have moved it
back behind the multiplexing, not posting async and so far I think I'm
far better off. Another issue were interactions with other parts of
the applications that send signals about, interfering with things the
SM is now concerned with. Effectively creating need for far more reach
the SM needs to have. Stuff like that. Christophe, if you are
interested, I may be able to churn out a little article and about that
if you are interested.

Cheers,

Stephan


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net