1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
// A <STATETABLE> is an array of STATEROWS.
//
// Where <TS> , <TE>, <TA> are enumerations for the states, events, and action
// specific to the state machine.
//
// DoAction is pure virtual and should be implemented in a derived class.
//
template <typename TS, typename TE, typename TA>
class STATETABLE
{
public:
typedef struct __staterow
{ TS state;
TE event;
TA action;
TS next_state;
} STATEROW;
private:
const STATEROW * m_rows; // Pointer to array of rows terminated by -1
protected:
// Terminate due to overloaded action not found
void ST_Error (TA action)
{ Abort ("ST=%s Action=%d not handled", m_name, (short) action);
}
// Terminate due to missing state table row
void ST_Error (TS state, TE event)
{ Abort ("ST=%s Row not found S=%d E=%d", m_name, state, event);
}
// Return pointer to matching current state and event
const SR * FindRow (TS state, TE event)
{ const STATEROW * row;
row = m_rows;
while (row->state != -1)
{ if (row->state == state && row->event == event)
return row;
row++;
}
ST_Error (state, event);
return NULL; // Not reached
}
// Returns another event, or 0 if state machine should exit
virtual TE DoAction (TA act) = 0; // pure virtual
// State Machine
// Called with event
// Loops until an action returns an EXIT (0) event
void state_machine (TS & state, TE event)
{ const STATEROW * row;
while (event)
{ row = FindRow (state, event);
state = row->next_state;
event = DoAction (row->action);
}
}
public:
STATETABLE (const STATEROW * rows)
{ m_rows = rows;
}
virtual ~STATETABLE (void)
{}
};
|