// FSM_DEM2.CPP // Finite State Machine (FSM) implementation of Elevator Simulation // Design notes for machine type #2: // ================================= // example in "Object Oriented State Machines", Ted Faison, // Software Development, Sep 1993, pg 36 // Modifications by Jim Fawcett 5/30/94 // - eliminate calls to new and delete for each change of state // - share state pointers among all state objects // Base class provides interface for all states which: // define events - action defaults to no state transition // report state to user - default to invalid // Derived classes: // - Each derived class represents a state and is responsible for // initializing shared pointer to itself. // - States also redefine event processing appropriate for it's // state transitions. // The way it works: // - All states share a set of pointers to each state object. // - The client constructs all state objects and starts the // machine by making the current state the first state and // starting up an event loop. Each state passes back a // pointer to its next state when it completes processing. // Advantages: // - States are defined in static memory, e.g. no calls to new // and delete. This implies faster operation than type #1. // Disadvantages: // State pointers are static members so they can be shared. // This means that only one state machine can be constructed. /* */ // Define States and state processing with class hierarchy // ======================================================= class ElevState { // base class provides complete interface // describing events and state reporting public: virtual ~ElevState() {} virtual ElevState* UPbutton() { return this; } virtual ElevState* DOWNbutton() { return this; } virtual ElevState* Arrived() { return this; } virtual char* Description() { return "Invalid State"; } protected: // shared state pointers static ElevState* ptrTo_OnFirstFloor; static ElevState* ptrTo_GoingUp; static ElevState* ptrTo_OnSecondFloor; static ElevState* ptrTo_GoingDown; }; class StateOnFirstFloor: public ElevState { public: StateOnFirstFloor() { ptrTo_OnFirstFloor = this; } ElevState* UPbutton() { return ptrTo_GoingUp; } char* Description() { return "on first floor"; } }; class StateGoingUp: public ElevState { public: StateGoingUp() { ptrTo_GoingUp = this; } ElevState* Arrived() { return ptrTo_OnSecondFloor; } char* Description() { return "going up"; } }; class StateOnSecondFloor: public ElevState { public: StateOnSecondFloor() { ptrTo_OnSecondFloor = this; } ElevState* DOWNbutton() { return ptrTo_GoingDown; } char* Description() { return "on second floor"; } }; class StateGoingDown: public ElevState { public: StateGoingDown() { ptrTo_GoingDown = this; } ElevState* Arrived() { return ptrTo_OnFirstFloor; } char* Description() { return "going down"; } }; /* */ // Define events and event processing // ================================== #include // Pointers to state objects, shared by all states ElevState* ElevState::ptrTo_OnFirstFloor = 0; ElevState* ElevState::ptrTo_GoingUp = 0; ElevState* ElevState::ptrTo_OnSecondFloor = 0; ElevState* ElevState::ptrTo_GoingDown = 0; void GetNextEvent(ElevState& state, int& event) { cout << "\n\nCurrent state = " << state.Description() << endl; cout << "Event types:" << endl << "1 - UP button" << endl << "2 - Arrived at floor" << endl << "3 - DOWN button" << endl << "enter next event type "; cin >> event; } ElevState* ProcessNextEvent(ElevState& state, int event) { enum { UPbutton = 1, Arrived = 2, DOWNbutton = 3 }; switch(event) { case UPbutton : return state.UPbutton(); case Arrived : return state.Arrived(); case DOWNbutton : return state.DOWNbutton(); default : return 0; } } void main() { // construct machine states StateOnFirstFloor OnFF; StateGoingUp GoUp; StateOnSecondFloor OnSF; StateGoingDown GoDn; ElevState* currentState = &OnFF; // start machine's event loop do { int event; GetNextEvent(*currentState, event); currentState = ProcessNextEvent(*currentState, event); } while (currentState); }