Re: finite state machine : transitions in absence of external events
srp113 <sunilsreenivas2001@yahoo.com> writes:
This was only solution I could think of. What I dont like about what
happens when we move from say A-B, we finally end in D (A-B,B-C,C-D)
and then at runtime call graph looks like: procesTimeoutInA()->B::entry
()->B's actions->B()::exit()- (B'S::exit called from with B::s entry
()!!)->C::entry()->C's actions->C's::exit() (again C's exit is called
from C's entry)->D's::entry() and unwind in the opposite order. Is
there any better way to handle this?
The call graph shouldn't matter. This was a perfectly good option.
An alternative would be to reify the events, which would allow you to
enqueue epsilon events.
class Event{ ... };
class Timeout:public Event{ ... };
class Epsilon:public Event{ ... };
class EventQueue {
protected: std::queue<Event*> queue;
Epsilon* epsilon;
static template<T> T pop(std::queue<T>& q){ T result=q.front(); q.pop(); return(result); }
public:
void enqueue(Epsilon* e){ epsilon=e; }
void enqueue(Event* e){ queue.push(e); }
Event* dequeue(){ Event* result=((epsilon!=0)
? epsilon
: (queue.empty()
? 0
: pop(queue)));
epsilon=0;
return(result); }
...
};
So now your state machine would have a queue of event to process, and
you could enqueue epsilon events:
class FSM {
proctected:
EventQueue* events;
State* currentState;
public:
void postEvent(Event* e){
events->enqueue(e);
}
void processEvents(){
Event* e=events.dequeue();
while(e){
currentState->processEvent(this,e);
e=events.dequeue();
}
}
void doTransition(State* oldState,Event* event,State* newState){
log("transition %1% ---(%2%)---> %3%",oldState->name(),event->name(),newState->name());
currentState->onExit(this);
currentState=newState;
currentState->onEntry(this);
}
};
class StateC:public State{
void onEntry(FSM* m){
m->postEvent(new Epsilon());
}
void processEvent(FSM* m,Event* e){
// ignore other events
}
void processEvent(FSM* m,Epsilon* e){
m->doTransition(this,e,new StateD);
}
};
This way, in the processEvent loop, the calls to the old state return
before processing the next event, including epsilon events.
--
__Pascal Bourguignon__