Boost logo

Boost Users :

Subject: Re: [Boost-users] [MSM] state transitions and exceptions
From: Gábor Márton (martongabesz_at_[hidden])
Date: 2012-04-06 03:22:07


>   template <class FSM,class Event>
>   void exception_caught (Event const&,FSM& fsm,std::exception& )
>   {
>       fsm.process_event(ErrorConnection());
>   }

In a telecom application we are doing something similar, but we have
several submachines, and we can have exceptions during the processing
of the error event.

In each submachnie we throw the exception further to the container machine.

// Base template class for submachines
template <typename T>
class BaseStateMachine: public msm::front::state_machine_def<T>
{
public:
   // ...
   // Exception Handling
    template <class FSM,class Event>
    void exception_caught (Event const&,FSM& fsm,std::exception& e)
    {
                _DEBUG_LIB(&fsm.getLogger()," exception_caught ");
                boost::exception* be = dynamic_cast<boost::exception*>(&e);
                if(be){
                        *be << EMsmEvent(removeNamespace<Event>());
                        throw;
                }
                else{
                        BOOST_THROW_EXCEPTION(MsmException() << EMsmEvent(removeNamespace<Event>()));
                }
                throw;
    }
// ...
};

In the outermost machine we have:

// Base template class for the outermost machines
template <typename T>
class BaseOutermostStateMachine: public BaseStateMachine<T> {
public:
    // Exception Handling
    template <class FSM,class Event>
    void exception_caught (Event const& event,FSM& fsm,std::exception& e)
    {
                _WARNING_LIB(&fsm.getLogger()," Error during state machine event
processing ");
                _INFO_LIB(&fsm.getLogger(),boost::diagnostic_information(e));
                _DEBUG_LIB(&fsm.getLogger()," processing event EvError ");
                    fsm.process_event(EvError());
    }
    template <class FSM> // error during error handling
    void exception_caught (EvError const& event, FSM& fsm, std::exception& e)
    {
            _INFO_LIB(&fsm.getLogger()," exception_caught during processing EvError");
            // Propagate the exception out from the fsm. The fsm will be terminated.
            BaseStateMachine<T>::exception_caught(event, fsm, e);
    }
};

When there is an error in the outermost statemachine we propagate the
exception out from it. At this point, the client code (which calls
the process_event function) shall restart the state machine therefore
resetting it to the initial state. But we cannot simply restart the
machine because after we have thrown the exception out from it, it
becomes nonresponsive, i.e. it does not react to the fsm->stop() and
fsm->start() sequence.

So we came up with the following:

void Client::reCreateBackEnd()
{
        if(backEnd){ // backEnd is a smart pointer
                backEnd->stop();
                backEnd.reset();
        }

        // Constructing the BackEnd
        backEnd.reset(new ...);
        backEnd->set_states( ... );
        backEnd->start();
}

It is too drastic to recreate the back end, I think. Christophe, is
there any more elegant solution to do this? Why is it that the state
machine becomes not restartable if an exception is thrown out from it?

BR,
Gabor


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