Main Page | Namespace List | Class List | File List | Namespace Members | Class Members | File Members

fsm.h

Go to the documentation of this file.
00001 
00005 //
00006 // Date:      23 January  2003
00007 // Modified:  29 November 2003
00008 //            01 December 2003
00009 //            31 July     2004
00010 //            01 August   2004
00011 //            07 August   2004   Doxygen remarks
00012 //            20 August   2005   exception safety changes
00013 //
00014 // Copyright (c) Sergey Satskiy 2003 - 2005
00015 //               <sergesatsky@yahoo.com>
00016 //
00017 // Permission to copy, use, modify, sell and distribute this software 
00018 // is granted provided this copyright notice appears in all copies. 
00019 // This software is provided "as is" without express or implied
00020 // warranty, and with no claim as to its suitability for any purpose.
00021 //
00022 
00023 
00024 #ifndef FSMTEMPLATE_H
00025 #define FSMTEMPLATE_H
00026 
00027 #include <vector>
00028 #include <algorithm>
00029 #include <stdexcept>
00030 #include <deque>
00031 #include <string>
00032 #include <functional>
00033 #include <iterator>
00034 #include <iostream>
00035 #include <boost/function.hpp>
00036 
00037 
00038 
00039 
00045 #define FSM_BEGIN( StartFSMState ) (StartFSMState),                         \
00046                                    FSM::SStateMachineProxy<FSMStateType,    \
00047                                                            FSMEventType>    \
00048                                        () << (                              \
00049                                    FSM::SStatesListProxy<FSMStateType>() <<
00050 
00051 
00056 #define FSM_STATES
00057 
00058 
00064 #define FSM_EVENT( Arg )           )                                        \
00065                                    << (FSM::STransitionsProxy<FSMStateType, \
00066                                                               FSMEventType> \
00067                                       ( Arg ) <<
00068 
00069 
00074 #define FSM_END                    )
00075 
00076 
00081 #define FSM_RESET                   FSM::ResetMachine
00082 
00083 
00084 
00085 
00091 #define FUNCFSM_BEGIN( StartFSMState ) (StartFSMState),                         \
00092                                    FSM::SFuncStateMachineProxy<FSMStateType,    \
00093                                                                FSMEventType>    \
00094                                        () << (                                  \
00095                                    FSM::SStatesListProxy<FSMStateType>() <<
00096 
00097 
00102 #define FUNCFSM_STATES
00103 
00104 
00110 #define FUNCFSM_EVENT( Arg )           )                                        \
00111                                    << (FSM::SFuncTransitionsProxy<FSMStateType, \
00112                                                                   FSMEventType> \
00113                                       ( Arg ) <<
00114 
00115 
00120 #define FUNCFSM_END                    )
00121 
00122 
00126 #define FUNCFSM_RESET                   FSM::ResetMachine
00127                                       
00128 
00129 
00130 
00134 namespace FSM
00135 {
00136 
00138     enum SMachineManipulator 
00139     { 
00140         ResetMachine = 0        
00141     };
00142 
00143 
00145     enum STransitionManipulator 
00146     { 
00147         NONE = 0,               
00148         EXCEPTION = 1           
00149     };
00150     
00151 
00153     class SStateMachineException : public std::exception
00154     {
00155         private:
00156             const std::string      Message;
00157 
00158         public:
00161             SStateMachineException( const std::string &  Msg ) : Message( Msg ) 
00162             {}
00163 
00166             SStateMachineException( const char *         Msg ) : Message( Msg ) 
00167             {}
00168 
00171             virtual const char * what( void ) const throw() 
00172             { return Message.c_str(); }
00173 
00175             virtual ~SStateMachineException() throw () {}
00176 
00177         private:
00178             SStateMachineException();
00179     };
00180 
00181 
00187     template < typename SState, typename SEvent >
00188     class SEmptyFunctor
00189     {
00190         public:
00192             void operator() ( const SState &, 
00193                               const SEvent &, 
00194                               const SState &  ) 
00195             { return; }
00196     };
00197 
00198 
00204     template < typename SState, typename SEvent >
00205     class SOnEnterFunctor
00206     {
00207         public:
00213             void operator() ( SState &        From, 
00214                               const SEvent &  Event, 
00215                               SState &        To )
00216             { To.OnEnter( From, Event ); }
00217     };
00218 
00219 
00225     template < typename SState, typename SEvent >
00226     class SOnExitFunctor
00227     {
00228         public:
00234             void operator() ( SState &        From, 
00235                               const SEvent &  Event, 
00236                               SState &        To )
00237             { From.OnExit( Event, To ); }
00238     };
00239 
00240 
00246     template < typename SState, typename SEvent >
00247     class SOnMoveFunctor
00248     {
00249         public:
00256             void operator() ( SState &        From, 
00257                               const SEvent &  Event, 
00258                               SState &        To )
00259             { 
00260               const SState &  FromConst( From );
00261               const SState &  ToConst( To );
00262   
00263               From.OnExit( Event, ToConst ); 
00264               To.OnEnter( FromConst, Event ); 
00265             }
00266     };
00267         
00268 
00273     template < typename SEvent >
00274     class SThrowStrategy
00275     {
00276         public:
00281             void operator() ( const SEvent & ) const 
00282             { throw SStateMachineException( "Unknown event." ); }
00283     };
00284 
00285 
00290     template < typename SEvent >
00291     class SIgnoreStrategy
00292     {
00293         public:
00295             void operator() ( const SEvent & ) const 
00296             { return; }
00297     };
00298 
00299 
00300 
00302 
00303         //
00304         // Temporary class to collect all the registered states
00305         //
00306     template < typename SState >
00307     class SStatesListProxy
00308     {
00309         private:
00310             std::vector<SState>    StatesProxy;
00311 
00312         public:
00313             SStatesListProxy() { return; }
00314 
00315             SStatesListProxy &  operator << ( const SState &  TheState )
00316             { 
00317                     // Check whether the state is unique
00318                 if ( std::find( StatesProxy.begin(), 
00319                                 StatesProxy.end(), 
00320                                 TheState ) != StatesProxy.end() )
00321                 {
00322                     throw SStateMachineException( "States must be unique." );
00323                 }
00324                 StatesProxy.push_back( TheState ); 
00325                 return *this; 
00326             }
00327 
00328             const std::vector<SState> &  GetStates( void ) const 
00329             { return StatesProxy; }
00330     };
00331 
00332     
00334 
00335 
00337 
00338         //
00339         // Temporary class to collect transitions for a single event
00340         //
00341     template < typename SState, typename SEvent >
00342     class STransitionsProxy
00343     {
00344         private:
00345             SEvent                  Event;
00346             std::vector<SState>     NewStates;
00347             std::vector< int >      Manipulators;
00348 
00349         public:
00350             explicit STransitionsProxy( const SEvent &  TheEvent ) : 
00351                 Event( TheEvent ) 
00352             { return; }
00353 
00354             STransitionsProxy & operator << ( const SState &  TheState ) 
00355             { 
00356                 NewStates.push_back( TheState ); 
00357                 Manipulators.push_back( -1 );
00358                 return *this; 
00359             }
00360 
00361             STransitionsProxy & operator << ( const STransitionManipulator &  Manipulator )
00362             {
00363                 NewStates.push_back( SState() );
00364                 Manipulators.push_back( Manipulator );
00365                 return *this;
00366             }
00367 
00368             const std::vector<SState> &  GetStates( void ) const 
00369             { return NewStates; }
00370 
00371             const std::vector<int> &  GetManipulators( void ) const
00372             { return Manipulators; }
00373 
00374             const SEvent &  GetEvent( void ) const 
00375             { return Event; }
00376 
00377         private:
00378             STransitionsProxy();
00379     };
00380 
00382 
00383 
00384 
00386 
00387         //
00388         // Temporary class to collect all the transitions
00389         //
00390     template < typename SState, typename SEvent >
00391     class SStateMachineProxy
00392     {
00393             typedef SState                   StateType;
00394             typedef SEvent                   EventType;
00395             typedef std::vector<StateType>   SStatesList;
00396             typedef std::vector<EventType>   SEventsList;
00397 
00398             typedef std::vector< int >       SManipulatorsList;
00399 
00400         private:
00401             SStatesList                     MachineStatesProxy;
00402             bool                            HaveStates;
00403             SEventsList                     MachineEventsProxy;
00404             std::vector<SStatesList>        Transitions;
00405             std::vector<SManipulatorsList>  TransitionsManipulators;
00406     
00407         public:
00408             SStateMachineProxy() : HaveStates( false ) 
00409             { return; }
00410 
00411             SStateMachineProxy & operator << 
00412                 ( const SStatesListProxy<SState> &   TheStates )
00413             { 
00414                 if ( HaveStates ) 
00415                 {
00416                     throw SStateMachineException( "Too much state lists." );
00417                 }
00418                 HaveStates = true;
00419                 MachineStatesProxy = TheStates.GetStates();
00420                 return *this; 
00421             }
00422 
00423             SStateMachineProxy & operator << 
00424                 ( const STransitionsProxy<SState,SEvent> &  TheTransitions )
00425             { 
00426                 if ( !HaveStates ) 
00427                 {
00428                     throw SStateMachineException( "States must be defined "
00429                                                   "before the transitions." );
00430                 }
00431             
00432                 if ( MachineStatesProxy.size() != 
00433                          TheTransitions.GetStates().size() ) 
00434                 {
00435                     throw SStateMachineException( "Transition states do not "
00436                                                   "coincide to the states list." );
00437                 }
00438 
00439                     // Check that the event is unique
00440                 if ( std::find( MachineEventsProxy.begin(), 
00441                                 MachineEventsProxy.end(), 
00442                                 TheTransitions.GetEvent() ) 
00443                          != MachineEventsProxy.end() ) 
00444                 {
00445                     throw SStateMachineException( "Events must be unique." );
00446                 }
00447                     
00448                     // Check the transition validity
00449                 CheckTransitionValidity( TheTransitions.GetStates().begin(), 
00450                                          TheTransitions.GetStates().end(),
00451                                          TheTransitions.GetManipulators().begin(),
00452                                          TheTransitions.GetManipulators().begin() );
00453 
00454                 MachineEventsProxy.push_back( TheTransitions.GetEvent() );
00455                 Transitions.push_back( TheTransitions.GetStates() );
00456                 TransitionsManipulators.push_back( TheTransitions.GetManipulators() );
00457                 return *this; 
00458             }
00459                 
00460                 
00461                 //
00462                 // Check that the transitions lead to a registered state
00463                 //
00464             void CheckTransitionValidity( 
00465                     typename SStatesList::const_iterator  First, 
00466                     typename SStatesList::const_iterator  Last,
00467                     std::vector<int>::const_iterator      ManipulatorFirst,
00468                     std::vector<int>::const_iterator      ManipulatorLast )
00469             {
00470                 for ( ; First != Last; ++First, ++ManipulatorFirst )
00471                 {
00472                     if ( *ManipulatorFirst == -1 )  // It's not a manipulator
00473                     {
00474                         if ( std::find( MachineStatesProxy.begin(), 
00475                                         MachineStatesProxy.end(), *First ) 
00476                                  == MachineStatesProxy.end() ) 
00477                         {
00478                             throw SStateMachineException( "Transition state "
00479                                                           "is not valid." );
00480                         }
00481                     }
00482                 }
00483             }       
00484 
00485             const SStatesList &  GetStates( void ) const
00486             { return MachineStatesProxy; }
00487 
00488             const std::vector<SStatesList> & GetTransitions( void ) const
00489             { return Transitions; }
00490 
00491             const std::vector<SManipulatorsList> &  GetManipulators( void ) const
00492             { return TransitionsManipulators; }
00493 
00494             const SEventsList &  GetEvents( void ) const
00495             { return MachineEventsProxy; }
00496     };
00497 
00499 
00500 
00501             
00511     template < typename SState, 
00512                typename SEvent, 
00513                typename SFunctor = SEmptyFunctor<SState,SEvent>, 
00514                typename SUnknownEventStrategy = SThrowStrategy<SEvent> > 
00515     class SStateMachine
00516     {
00517         public:
00519             typedef SState                          StateType;
00520             typedef SEvent                          EventType;
00521             typedef std::vector<StateType>          SStatesList;
00522             typedef std::vector<EventType>          SEventsList;
00523             typedef std::vector<SStatesList>        TransitionsType;
00524             typedef std::deque<EventType>           EventsQueueType;
00525             typedef std::vector<int>                ManipulatorsList;
00526             typedef std::vector<ManipulatorsList>   ManipulatorsType;
00528 
00529         private:
00530             StateType              CurrentState;          // Current machine state
00531             SStatesList            States;                // A list of the registered states
00532             SEventsList            Events;                // A list of the registered events
00533             TransitionsType        Transitions;           // A table of transitions between states
00534             ManipulatorsType       Manipulators;          // A table of manipulators
00535             SFunctor               Functor;               // Transition function
00536             SUnknownEventStrategy  UnknownEventStrategy;  // Unknown event strategy
00537             EventsQueueType        EventsQueue;           // Internal events queue to support events 
00538                                                           //   that were generated in the transition 
00539                                                           //   functions
00540             bool                   InProcess;             // To be sure that we are processing the events
00541             int                    CurrentStateIndex;     // Index of column in a transition table 
00542                                                           //   (0 - based)
00543             StateType              InitialState;          // Start machine state
00544 
00545         public:
00553             SStateMachine( const StateType &  StartState, 
00554                            const SStateMachineProxy<StateType,
00555                                                     EventType> &  ProxyMachine ) :
00556                 CurrentState( StartState ), 
00557                 States( ProxyMachine.GetStates() ),
00558                 Events( ProxyMachine.GetEvents() ), 
00559                 Transitions( ProxyMachine.GetTransitions() ), 
00560                 Manipulators( ProxyMachine.GetManipulators() ),
00561                 InProcess( false ),
00562                 CurrentStateIndex( -1 ), 
00563                 InitialState( StartState )
00564             {
00565                     // Check that the start state is valid
00566                 typename SStatesList::iterator  k( std::find( States.begin(), 
00567                                                               States.end(), 
00568                                                               StartState ) );
00569                 if ( k == States.end() ) 
00570                 {
00571                     throw SStateMachineException( "Start state is invalid." );
00572                 }
00573                 CurrentStateIndex = std::distance( States.begin(), k );
00574             }
00575 
00576 
00581             SStateMachine & Reset( void ) 
00582             {
00583                 CurrentState = InitialState; 
00584                 CurrentStateIndex = GetStateIndex( CurrentState );
00585                 InProcess = false;
00586                 EventsQueue.clear();
00587                 return *this;
00588             }
00589 
00590 
00594             StateType GetCurrentState( void ) const 
00595             { return CurrentState; }
00596 
00597 
00598 
00606             SStateMachine &  AcceptEvent( const EventType &  Event )
00607             {
00608                 EventsQueue.push_back( Event );
00609                 if ( InProcess ) return *this;
00610                 InProcess = true;
00611                 while ( !EventsQueue.empty() )
00612                 {
00613                     ProcessEvent( EventsQueue.front() );
00614                     EventsQueue.pop_front();
00615                 }
00616                 InProcess = false;
00617                 return *this;
00618             }
00619 
00620 
00628             SStateMachine & operator << ( const EventType &  Event )
00629             { return AcceptEvent( Event ); }
00630 
00631 
00636             SStateMachine & operator << ( SMachineManipulator Manipulator )
00637             { 
00638                 if ( Manipulator != ResetMachine ) 
00639                 {
00640                     Reset();
00641                     throw SStateMachineException( "Unknown manipulator. Machine is reset." );
00642                 }
00643                 return Reset();
00644             } 
00645         
00646         private:
00647             void ProcessEvent( const EventType &  Event )
00648             {   
00649                 try
00650                 {
00651                     int  EventIndex( GetEventIndex( Event ) );
00652                     if ( EventIndex == -1 ) return;
00653 
00654                     StateType      OldState( CurrentState );
00655             
00656                     if ( (Manipulators[EventIndex])[CurrentStateIndex] == EXCEPTION )
00657                     {
00658                         throw SStateMachineException( "Transition is forbidden. Machine is reset." );
00659                     }
00660                 
00661                     if ( (Manipulators[EventIndex])[CurrentStateIndex] == NONE )
00662                     {
00663                         return;
00664                     }
00665 
00666                     CurrentState = (Transitions[EventIndex])[CurrentStateIndex];
00667                     CurrentStateIndex = GetStateIndex( CurrentState );
00668 
00669                     Functor( OldState, Event, CurrentState );
00670                 }
00671                 catch ( ... )
00672                 {
00673                     Reset();
00674                     throw;
00675                 }
00676             }
00677         
00678             int GetEventIndex( const EventType &  Event ) const
00679             {   
00680                 typename SEventsList::const_iterator   k( std::find( Events.begin(), 
00681                                                                      Events.end(), 
00682                                                                      Event ) );
00683                 if ( k == Events.end() ) 
00684                 { 
00685                     UnknownEventStrategy( Event ); 
00686                     return -1; 
00687                 }
00688                 return std::distance( Events.begin(), k );
00689             }
00690 
00691             int GetStateIndex( const StateType &  State ) const
00692             {
00693                 return std::distance( States.begin(), 
00694                                       std::find( States.begin(), 
00695                                                  States.end(), 
00696                                                  State ) );
00697             }
00698 
00699         private:
00700                 //
00701                 // Prevent the illegal usage
00702                 //
00703             SStateMachine();
00704             SStateMachine & operator= ( const SStateMachine & );
00705             SStateMachine( const SStateMachine & );
00706     };
00707     
00708 
00709 
00715     template < typename SState, 
00716                typename SEvent, 
00717                typename SFunctor, 
00718                typename SUnknownEventStrategy > 
00719         std::ostream & operator << (std::ostream &  Stream, 
00720                                     const SStateMachine<SState,
00721                                                         SEvent,
00722                                                         SFunctor,
00723                                                         SUnknownEventStrategy> &  Machine )
00724     { return Stream << Machine.GetCurrentState(); }
00725     
00726 
00727 
00728 
00729         //
00730         // Second vertion of the finite state machine where functions are
00731         // linked to transitions but not to the states
00732         //
00733     
00734 
00739     template < typename  Child,
00740                typename  Event >
00741     class StateBase
00742     {
00743             // Should all of them be const? - No. It is easy to imagine that
00744             // some fields in the states and events should be changed
00745         typedef boost::function< void ( Child &,
00746                                         Event &,
00747                                         Child & ) >   CallbackType;
00748 
00749         private:
00750             CallbackType    Callback;
00751 
00752         protected:
00753             StateBase() : Callback( 0 ) {}
00754 
00755         public:
00760             Child & operator [] ( const CallbackType &  NewCallback )
00761             {
00762                 Callback = NewCallback;
00763                 return static_cast< Child & >( *this );
00764             }
00765             
00770             CallbackType  GetCallback( void )
00771             {
00772                 CallbackType        Temporary( Callback );
00773 
00774                 Callback = 0;
00775                 return Temporary;
00776             }
00777     };
00778 
00779 
00781 
00782         // A bundle of the state related information
00783     template < typename SState, typename SEvent >
00784     struct SFuncBundle
00785     {
00786         SState                                  NewState;
00787         int                                     Manipulator;
00788         boost::function< void ( SState &,
00789                                 SEvent &,
00790                                 SState & ) >    Callback;
00791 
00792         SFuncBundle() {}
00793     };
00794 
00796 
00797 
00798         // Start state spec is the same as in the first version
00799         // States list is the same as in the first version
00800 
00801         // Transition accepting class is different.
00802         // Let's define it.
00803 
00804 
00806 
00807         //
00808         // Temporary class to collect transitions for a single event
00809         //
00810     template < typename SState, typename SEvent >
00811     class SFuncTransitionsProxy
00812     {
00813         typedef SFuncBundle< SState, SEvent >   Bundle;
00814         
00815         private:
00816             SEvent                  Event;
00817             std::vector<Bundle>     NewStates;
00818 
00819         public:
00820             explicit SFuncTransitionsProxy( const SEvent &  TheEvent ) : 
00821                 Event( TheEvent ) 
00822             { return; }
00823 
00824             SFuncTransitionsProxy & operator << ( SState &  TheState ) 
00825             { 
00826                 Bundle      NewBundle;
00827 
00828                 NewBundle.NewState = TheState;
00829                 NewBundle.Manipulator = -1;
00830                 NewBundle.Callback = TheState.GetCallback();
00831 
00832                 NewStates.push_back( NewBundle );
00833                 return *this; 
00834             }
00835 
00836             SFuncTransitionsProxy & operator << ( const STransitionManipulator &  Manipulator )
00837             {
00838                 Bundle      NewBundle;
00839 
00840                 NewBundle.NewState = SState();
00841                 NewBundle.Manipulator = Manipulator;
00842                 NewBundle.Callback = 0;
00843                 
00844                 NewStates.push_back( NewBundle );
00845                 return *this;
00846             }
00847 
00848             const std::vector<Bundle> &  GetStates( void ) const 
00849             { return NewStates; }
00850 
00851             const SEvent &  GetEvent( void ) const 
00852             { return Event; }
00853 
00854         private:
00855             SFuncTransitionsProxy();
00856     };
00857 
00859 
00860 
00861                
00863 
00864         //
00865         // Temporary class to collect all the transitions
00866         //
00867     template < typename SState, typename SEvent >
00868     class SFuncStateMachineProxy
00869     {
00870         typedef SFuncBundle< SState, SEvent >   Bundle;
00871         
00872         typedef SState                   StateType;
00873         typedef SEvent                   EventType;
00874         typedef std::vector<StateType>   SStatesList;
00875         typedef std::vector<EventType>   SEventsList;
00876         typedef std::vector< Bundle >    SBundlesList;
00877 
00878         private:
00879             SStatesList                     MachineStatesProxy;
00880             bool                            HaveStates;
00881             SEventsList                     MachineEventsProxy;
00882             std::vector<SBundlesList>       Transitions;
00883     
00884         public:
00885             SFuncStateMachineProxy() : HaveStates( false ) 
00886             { return; }
00887 
00888             SFuncStateMachineProxy & operator << 
00889                 ( const SStatesListProxy<SState> &   TheStates )
00890             { 
00891                 if ( HaveStates ) 
00892                 {
00893                     throw SStateMachineException( "Too much state lists." );
00894                 }
00895                 HaveStates = true;
00896                 MachineStatesProxy = TheStates.GetStates();
00897                 return *this; 
00898             }
00899 
00900             SFuncStateMachineProxy & operator << 
00901                 ( const SFuncTransitionsProxy<SState,SEvent> &  TheTransitions )
00902             { 
00903                 if ( !HaveStates ) 
00904                 {
00905                     throw SStateMachineException( "States must be defined "
00906                                                   "before the transitions." );
00907                 }
00908             
00909                 if ( MachineStatesProxy.size() != 
00910                          TheTransitions.GetStates().size() ) 
00911                 {
00912                     throw SStateMachineException( "Transition states do not "
00913                                                   "coincide to the states list." );
00914                 }
00915 
00916                     // Check that the event is unique
00917                 if ( std::find( MachineEventsProxy.begin(), 
00918                                 MachineEventsProxy.end(), 
00919                                 TheTransitions.GetEvent() ) 
00920                          != MachineEventsProxy.end() ) 
00921                 {
00922                     throw SStateMachineException( "Events must be unique." );
00923                 }
00924                     
00925                     // Check the transition validity
00926                 CheckTransitionValidity( TheTransitions.GetStates().begin(), 
00927                                          TheTransitions.GetStates().end()      );
00928 
00929                 MachineEventsProxy.push_back( TheTransitions.GetEvent() );
00930                 Transitions.push_back( TheTransitions.GetStates() );
00931                 return *this; 
00932             }
00933                 
00934                 
00935                 //
00936                 // Check that the transitions lead to a registered state
00937                 //
00938             void CheckTransitionValidity( 
00939                     typename std::vector<Bundle>::const_iterator  First, 
00940                     typename std::vector<Bundle>::const_iterator  Last )
00941             {
00942                 for ( ; First != Last; ++First )
00943                 {
00944                     if ( First->Manipulator == -1 )  // It's not a manipulator
00945                     {
00946                         if ( std::find( MachineStatesProxy.begin(), 
00947                                         MachineStatesProxy.end(), First->NewState ) 
00948                                  == MachineStatesProxy.end() ) 
00949                         {
00950                             throw SStateMachineException( "Transition state "
00951                                                           "is not valid." );
00952                         }
00953                     }
00954                 }
00955             }       
00956 
00957             const SStatesList &  GetStates( void ) const
00958             { return MachineStatesProxy; }
00959 
00960             const std::vector<SBundlesList> & GetTransitions( void ) const
00961             { return Transitions; }
00962 
00963             const SEventsList &  GetEvents( void ) const
00964             { return MachineEventsProxy; }
00965     };
00966 
00968 
00969 
00970 
00978     template < typename SState, 
00979                typename SEvent, 
00980                typename SUnknownEventStrategy = SThrowStrategy<SEvent> > 
00981     class SFuncStateMachine
00982     {
00983         public:
00985         typedef SFuncBundle< SState, SEvent >   Bundle;
00986 
00987         typedef SState                          StateType;
00988         typedef SEvent                          EventType;
00989         typedef std::vector<StateType>          SStatesList;
00990         typedef std::vector<EventType>          SEventsList;
00991         typedef std::vector<SStatesList>        TransitionsType;
00992         typedef std::deque<EventType>           EventsQueueType;
00993         typedef std::vector< Bundle >           SBundlesList;
00995 
00996         private:
00997             StateType                   CurrentState;          // Current machine state
00998             SStatesList                 States;                // A list of the registered states
00999             SEventsList                 Events;                // A list of the registered events
01000             std::vector<SBundlesList>   Transitions;           // A table of transitions between states
01001             SUnknownEventStrategy       UnknownEventStrategy;  // Unknown event strategy
01002             EventsQueueType             EventsQueue;           // Internal events queue to support events 
01003                                                                //   that were generated in the 
01004                                                                //   transition functions
01005             bool                        InProcess;             // To be sure that we are processing 
01006                                                                //   the events
01007             int                         CurrentStateIndex;     // Index of column in a transition 
01008                                                                //   table (0 - based)
01009             StateType                   InitialState;          // Start machine state
01010 
01011         public:
01018             SFuncStateMachine( const StateType &  StartState, 
01019                                const SFuncStateMachineProxy<StateType,
01020                                                             EventType> &  ProxyMachine ) :
01021                 CurrentState( StartState ), 
01022                 States( ProxyMachine.GetStates() ),
01023                 Events( ProxyMachine.GetEvents() ), 
01024                 Transitions( ProxyMachine.GetTransitions() ), 
01025                 InProcess( false ),
01026                 CurrentStateIndex( -1 ), 
01027                 InitialState( StartState )
01028             {
01029                     // Check that the start state is valid
01030                 typename SStatesList::iterator  k( std::find( States.begin(), 
01031                                                               States.end(), 
01032                                                               StartState ) );
01033                 if ( k == States.end() ) 
01034                 {
01035                     throw SStateMachineException( "Start state is invalid." );
01036                 }
01037                 CurrentStateIndex = std::distance( States.begin(), k );
01038             }
01039 
01040 
01045             SFuncStateMachine & Reset( void ) 
01046             {
01047                 CurrentState = InitialState; 
01048                 CurrentStateIndex = GetStateIndex( CurrentState );
01049                 InProcess = false;
01050                 EventsQueue.clear();
01051                 return *this;
01052             }
01053 
01054 
01058             StateType GetCurrentState( void ) const 
01059             { return CurrentState; }
01060 
01061 
01069             SFuncStateMachine &  AcceptEvent( EventType &  Event )
01070             {
01071                 EventsQueue.push_back( Event );
01072                 if ( InProcess ) return *this;
01073                 InProcess = true;
01074                 while ( !EventsQueue.empty() )
01075                 {
01076                     ProcessEvent( EventsQueue.front() );
01077                     EventsQueue.pop_front();
01078                 }
01079                 InProcess = false;
01080                 return *this;
01081             }
01082 
01090             SFuncStateMachine & operator << ( EventType &  Event )
01091             { return AcceptEvent( Event ); }
01092 
01093 
01098             SFuncStateMachine & operator << ( SMachineManipulator Manipulator ) 
01099             { 
01100                 if ( Manipulator != ResetMachine ) 
01101                 {
01102                     Reset();
01103                     throw SStateMachineException( "Unknown manipulator. Machine is reset." );
01104                 }
01105                 return Reset();
01106             } 
01107         
01108         private:
01109             void ProcessEvent( EventType &  Event )
01110             {   
01111                 try
01112                 {
01113                     int  EventIndex( GetEventIndex( Event ) );
01114                     if ( EventIndex == -1 ) return;
01115 
01116                     StateType      OldState( CurrentState );
01117             
01118                     if ( Transitions[EventIndex][CurrentStateIndex].Manipulator == EXCEPTION )
01119                     {
01120                         throw SStateMachineException( "Transition is forbidden. Machine is reset." );
01121                     }
01122 
01123                     if ( Transitions[EventIndex][CurrentStateIndex].Manipulator == NONE )
01124                     {
01125                         return;
01126                     }
01127 
01128                     boost::function< void ( SState &, SEvent &, SState & ) >    
01129                             Functor( Transitions[EventIndex][CurrentStateIndex].Callback );
01130                 
01131                     CurrentState = Transitions[EventIndex][CurrentStateIndex].NewState;
01132                     CurrentStateIndex = GetStateIndex( CurrentState );
01133 
01134                     if ( Functor != 0 )     Functor( OldState, Event, CurrentState );
01135                 }
01136                 catch ( ... )
01137                 {
01138                     Reset();
01139                     throw;
01140                 }
01141             }
01142         
01143 
01144             int GetEventIndex( const EventType &  Event ) const
01145             {   
01146                 typename SEventsList::const_iterator   k( std::find( Events.begin(), 
01147                                                                      Events.end(), 
01148                                                                      Event ) );
01149                 if ( k == Events.end() ) 
01150                 { 
01151                     UnknownEventStrategy( Event ); 
01152                     return -1; 
01153                 }
01154                 return std::distance( Events.begin(), k );
01155             }
01156 
01157             int GetStateIndex( const StateType &  State ) const
01158             {
01159                 return std::distance( States.begin(), 
01160                                       std::find( States.begin(), 
01161                                                  States.end(), 
01162                                                  State ) );
01163             }
01164 
01165         private:
01166                 //
01167                 // Prevent the illegal usage
01168                 //
01169             SFuncStateMachine();
01170             SFuncStateMachine & operator= ( const SFuncStateMachine & );
01171             SFuncStateMachine( const SFuncStateMachine & );
01172     };
01173     
01174 
01179     template < typename SState, 
01180                typename SEvent, 
01181                typename SUnknownEventStrategy > 
01182         std::ostream & operator << (std::ostream &  Stream, 
01183                                     const SFuncStateMachine<SState,
01184                                                             SEvent,
01185                                                             SUnknownEventStrategy> &  Machine )
01186     { return Stream << Machine.GetCurrentState(); }
01187     
01188     
01189                
01190 }   // End of the FSM namespace
01191 
01192 #endif
01193 

Generated on Thu Sep 15 21:35:19 2005 for Finite State Machine C++ Templates by  doxygen 1.4.4