// FSM_DEM3.CPP // Finite State Machine (FSM) implementation of Elevator Simulation // Design notes for machine type #3: // ================================= // 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 // - initialize next state pointers using friend function // 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 redefines event // processing appropriate for it's state transitions. // The way it works: // - Each state owns a pointer to its next state. // - The client constructs all the states and then connects them // by passing each state its next pointer via a friend function // connect(). // - After connection, the client starts the machine in its // first state by making the current state the first state and // starting up an event loop. // Advantages: // - States are defined in static memory, e.g. no calls to new // and delete. This implies faster operation than type #1. // - There are no shared pointers so multiple machines can be // defined // Disadvantages: // - Client must connect machine. This requires client knowledge // of the machine design. Probably ok since FSM design must be // specific to the application, but preferable not to require // client to know so much. /* */ // Define States and state processing with class hierarchy // ======================================================= class ElevState { friend void connect(ElevState* thisState, ElevState* next); 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: ElevState* nextState; }; void connect(ElevState* thisState, ElevState* next) { thisState->nextState = next; } class StateOnFirstFloor: public ElevState { public: ElevState* UPbutton() { return nextState; } char* Description() { return "on first floor"; } }; class StateGoingUp: public ElevState { public: ElevState* Arrived() { return nextState; } char* Description() { return "going up"; } }; class StateOnSecondFloor: public ElevState { public: ElevState* DOWNbutton() { return nextState; } char* Description() { return "on second floor"; } }; class StateGoingDown: public ElevState { public: ElevState* Arrived() { return nextState; } char* Description() { return "going down"; } }; /* */ // Define events and event processing // ================================== #include 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; // connect machine states connect(&OnFF,&GoUp); connect(&GoUp,&OnSF); connect(&OnSF,&GoDn); connect(&GoDn,&OnFF); // start machine's event loop do { int event; GetNextEvent(*currentState, event); currentState = ProcessNextEvent(*currentState, event); } while (currentState); }