# cfsm.h

    00001 //==========================================================================
    00002 //   CFSM.H  -  header for
    00003 //                     OMNeT++/OMNEST
    00004 //            Discrete System Simulation in C++
    00005 //
    00006 //  Contents:
    00007 //    FSM building macros
    00008 //    class cFSM: stores the state of an FSM
    00009 //
    00010 //==========================================================================
    00011
    00012 /*--------------------------------------------------------------*
    00013   Copyright (C) 1992-2005 Andras Varga
    00014
    00015   This file is distributed WITHOUT ANY WARRANTY. See the file
    00016   `license' for details on this and other legal matters.
    00017 *--------------------------------------------------------------*/
    00018
    00019 #ifndef __CFSM_H
    00020 #define __CFSM_H
    00021
    00022 #include "cobject.h"
    00023
    00029
    00034 #define FSM_MAXT  64
    00035
    00076 //
    00077 // operation:
    00078 // - __i counts up (starting from 1) until the FSM reaches a steady state.
    00079 // - at __i=1,3,5,7,etc, FSM_Exit code is executed
    00080 // - at __i=2,4,6,8,etc, FSM_Enter code is executed
    00081 // - FSM_Enter code must not contain state change (this is verified)
    00082 // - state changes should be encoded in FSM_Exit code
    00083 // - infinite loops (when control never reaches steady state) are detected (FSM_MAXT)
    00084 //
    00085 #define FSM_Switch(fsm)  \
    00086    for (int __i=1, __savedstate;  \
    00087         (__i<3 || (__i&1)==0 || (fsm).inTransientState()) &&  \
    00088         (__i<2*FSM_MAXT || (opp_error(eINFLOOP,(fsm).stateName()),0));  \
    00089         ((__i&1)==0 && __savedstate!=(fsm).state() &&  \
    00090          (opp_error(eSTATECHG,(fsm).stateName()),0)),  \
    00091          __savedstate=(fsm).state(),++__i)  \
    00092      switch (FSM_Print(fsm,__i&1),(((fsm).state()<<1)|(__i&1)))
    00093
    00113 #define FSM_Transient(state)   (-(state))
    00114
    00122 #define FSM_Steady(state)      (state)
    00123
    00132 #define FSM_Enter(state)  ((state)<<1)
    00133
    00141 #define FSM_Exit(state)   (((state)<<1)|1)
    00142
    00153 #define FSM_Goto(fsm,state)   (fsm).setState(state,#state)
    00154
    00155 #ifdef FSM_DEBUG
    00156
    00163 #define FSM_Print(fsm,exiting) \
    00164     (ev << "FSM " << (fsm).name() \
    00165         << ((exiting) ? ": leaving state  " : ": entering state ") \
    00166         << (fsm).stateName() << endl)
    00167 // this may also be useful as third line:
    00168 //      << ((fsm).inTransientState() ? "transient state " : "steady state ")
    00169 #else
    00170 #define FSM_Print(fsm,entering) ((void)0)
    00171 #endif
    00172
    00174
    00175 //-----------------------------------------------------
    00176
    00184 class SIM_API cFSM : public cObject
    00185 {
    00186   private:
    00187     //
    00188     // About state codes:
    00189     //  initial state is number 0
    00190     //  negative state codes are transient states
    00191     //  positive state codes are steady states
    00192     //
    00193     int _state;
    00194     const char *_statename;   // just a ptr to an external string
    00195
    00196   public:
    00199
    00203     explicit cFSM(const char *name=NULL);
    00204
    00208     cFSM(const cFSM& vs) : cObject() {setName(vs.name());operator=(vs);}
    00209
    00214     cFSM& operator=(const cFSM& vs);
    00216
    00219
    00224     virtual cPolymorphic *dup() const   {return new cFSM(*this);}
    00225
    00230     virtual std::string info() const;
    00231
    00236     virtual void writeContents(std::ostream& os);
    00237
    00243     virtual void netPack(cCommBuffer *buffer);
    00244
    00250     virtual void netUnpack(cCommBuffer *buffer);
    00252
    00255
    00259     int state() const  {return _state;}
    00260
    00264     const char *stateName() const {return _statename?_statename:"";}
    00265
    00269     int inTransientState() const  {return _state<0;}
    00270
    00281     void setState(int state, const char *stn=NULL)  {_state=state;_statename=stn;}
    00283 };
    00284
    00285 #endif