Boost logo

Boost Users :

Subject: [Boost-users] [Statechart] Order of Trigger/Event/Guard at state transition
From: Franz Alt (f.alt_at_[hidden])
Date: 2008-12-22 12:06:59


Hi all,

I've tried to use the Statechart library for modelling a simple state
machine. I've created three states and three transitions between them
and added some debug outputs. When I've looked to the debug outputs I've
wondered a little bit. I've thought that the processing of events are in
the order 1) exit actions of source state 2) transition actions and 3)
entry actions of target state. When I look at my result I see the order
1) transition action 2) exit action of source state and 3) entry action
of target state. Does anybody know what I'm doing wrong here?

Best regards,

Franz


#include <iostream>

#include "FSMSimple.h"

using namespace std;

int main(int argc, char * argv[])
{
        // Instanciate the FSM ...
        FSMSimple sm;

        // ... and start it
        sm.initiate();

        // Process some events ...
        cout << "trigger event 'Event1'" << endl;
        sm.process_event(Event1());

        cout << "trigger event 'Event2'" << endl;
        sm.process_event(Event2());

        return 0;
}


#include "FSMSimple.h"

#include <iostream>

using namespace std;

// The FSM
void FSMSimple::action1(const Event1 & /*e*/)
{
        cout << "process action 'action1'" << endl;
}

void FSMSimple::action2(const Event2 & /*e*/)
{
        cout << "process action 'action2'" << endl;
}

void FSMSimple::action3(const Event2 & /*e*/)
{
        cout << "process action 'action3'" << endl;
}

bool FSMSimple::guard1()
{
        cout << "process guard 'guard1'" << endl;
        return true;
}

// FSM state 'StateA'
StateA::StateA()
{
        cout << "enter state 'StateA'" << endl;
}

StateA::~StateA()
{
        cout << "leave state 'StateA'" << endl;
}

// FSM state 'StateB'
StateB::StateB()
{
        cout << "enter state 'StateB'" << endl;
}

StateB::~StateB()
{
        cout << "leave state 'StateB'" << endl;
}

sc::result StateB::react(const Event2 & e)
{
        if (context<FSMSimple>().guard1())
        {
                context<FSMSimple>().action3(e);
                return transit<StateC>();
        }
        else
        {
                context<FSMSimple>().action2(e);
                return transit<StateA>();
        }
}

// FSM state 'StateC'
StateC::StateC()
{
        cout << "enter state 'StateC'" << endl;
}

StateC::~StateC()
{
        cout << "leave state 'StateC'" << endl;
}


#ifndef FSMSIMPLE_H
#define FSMSIMPLE_H

#include <iostream>

#include <boost/mpl/list.hpp>

#include <boost/statechart/event.hpp>
#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/custom_reaction.hpp>
#include <boost/statechart/transition.hpp>

namespace mpl = boost::mpl;
namespace sc = boost::statechart;

// FSM events
struct Event1 : sc::event<Event1>
{
        Event1()
        {
                std::cout << "process event 'Event1'" << std::endl;
        }
};

struct Event2 : sc::event<Event2>
{
        Event2()
        {
                std::cout << "process event 'Event2'" << std::endl;
        }
};

// FSM initial state
struct StateA;

// The FSM
struct FSMSimple : sc::state_machine<FSMSimple, StateA>
{
        void action1(const Event1 & e);
        void action2(const Event2 & e);
        void action3(const Event2 & e);

        bool guard1();
};

// FSM states (forward declarations)
struct StateA;
struct StateB;
struct StateC;

// FSM states
struct StateA : sc::simple_state<StateA, FSMSimple>
{
        typedef mpl::list<
        sc::transition<Event1, StateB, FSMSimple, &FSMSimple::action1>
> reactions;

        StateA();
        ~StateA();
};

struct StateB : sc::simple_state<StateB, FSMSimple>
{
        typedef mpl::list<
                sc::custom_reaction<Event2>
> reactions;

        StateB();
        ~StateB();

        sc::result react(const Event2 & e);
};

struct StateC : sc::simple_state<StateC, FSMSimple>
{
        typedef mpl::list<
> reactions;

        StateC();
        ~StateC();
};

#endif // FSMSIMPLE_H

enter state 'StateA'
trigger event 'Event1'
process event 'Event1'
leave state 'StateA'
process action 'action1'
enter state 'StateB'
trigger event 'Event2'
process event 'Event2'
process guard 'guard1'
process action 'action3'
leave state 'StateB'
enter state 'StateC'
leave state 'StateC'


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