//----------- FSM declaration ------------
#include "ABS_eventhandler.h"
#include "list.h"
typedef struct StructEvent
{
// event identifier
int Id;
// event parameters
void *parameters;
} STRUCT_EVENT;
Makelista(STRUCT_EVENT);
class FSM
{
private :
typedef struct
{
int source_state;
int destination_state;
int event;
int index;
} TransitionType;
TransitionType* myptrArrayTrans; // a pointer to the
// array of transitions
int myMaxNumTransitions; // max transitions supported
int myCurrentState; // current state of the FSM
// an event queue
STRUCT_EVENTlista myList;
ABSEventHandler* myptrHandler; // a pointer to the
// abstract server class
void insertInQueue(int inEvent, void *inParameters );
// Search using hash functions
int hash(int inSourceState, int inEvent);
int hash(int inEvent);
public :
// Constructor
FSM(ABSEventHandler *inTrans, int inMaxNumTransitions,
int inInitialState );
// Destructor
~FSM( void );
void defineTransition(int inSourceState, int inDestinationState,
int inEvent, int inIndex);
int control(int inEvent, void *inParameters = NULL );
void generateEvent(int inEvent, void *inParameters = NULL );
};
//----------- FSM definition ------------
#include <memory.h>
#include <stdlib.h>
#include "FSM.h"
FSM::FSM(ABSEventHandler *inTrans, int inMaxNumTransitions,
int inInitialState)
{
myptrHandler = inTrans;
// Initialize the maximal number of transitions
myMaxNumTransitions = inMaxNumTransitions;
// Initialize the current state
myCurrentState = inInitialState;
// Initialize the array of transitions
myptrArrayTrans = 0;
myptrArrayTrans = new TransitionType[myMaxNumTransitions];
memset(myptrArrayTrans, -1,
myMaxNumTransitions * sizeof(TransitionType));
}
FSM::~FSM()
{
if ( myptrArrayTrans )
delete []myptrArrayTrans;
}
void FSM::insertInQueue(int inEvent, void *inParametros)
// not shown
int FSM::hash(int inSourceState, int inEvent)
{
int i = 0;
int where = ((inEvent << 8) + inSourceState) % myMaxNumTransitions;
// Look for the first available position
while((myptrArrayTrans[(where + i)%myMaxNumTransitions].index != -1)
&& (i < myMaxNumTransitions))
i++;
// Return negative value if the table is full
if ( i >= myMaxNumTransitions )
return -1;
else // Return free position?s index
return ((where + i) % myMaxNumTransitions);
}
int FSM::hash( int inEvent )
{
int i = 0;
int where = ((inEvent << 8) + myCurrentState) % myMaxNumTransitions;
// rest the same as above
}
int FSM::defineTransition(int inSourceState, int inDestinationState,
int inEvent, int inIndex)
{
int index;
// Search free position in the table of transitions
index = hash(inSourceState, inEvent);
if ( index != -1 )
{
myptrArrayTrans[index].source_state = inSourceState;
myptrArrayTrans[index].destination_state = inDestinationState;
myptrArrayTrans[index].event = inEvent;
myptrArrayTrans[index].index = inIndex;
}
return index;
}
int FSM::control( int inEvent, void *inParametros )
{
int result = FALSE;
int trans_num;
StructEvent* anEvent = NULL;
// Insert the received event in the queue
insertInQueue(inEvent, inParametros);
anEvent = myList.first();
while ( anEvent )
{
// check if it is valid transition
if ((trans_num = hash(anEvent->Id)) >= 0)
{
if (myptrArrayTrans[trans_num].index == -1)
{
// Missing transition - generate an internal error event
generateEvent(INTERNAL_ERROR);
}
else
{
// Execute an event handler
result = (myptrHandler->*myptrHandler->
functions[myptrArrayTrans[trans_num].index])
(anEvent->parameters);
// Change the FSM's state
myCurrentState =
myptrArrayTrans[trans_num].destination_state;
}
}
// Missing transition - generate an internal error event
else
{
generateEvent(INTERNAL_ERROR);
}
// Remove the processed event
myList.remove(anEvent);
// pull the next event
// from the queue
anEvent = myList.next();
}
return result;
}
void FSM::generateEvent(int inEvent, void *inParametros )
{
insertInQueue(inEvent, inParametros);
}
//End of File