SourceForge Project Site
Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

FiniteStateMachine.cpp

Go to the documentation of this file.
00001 // $Log: FiniteStateMachine.cpp,v $
00002 // Revision 1.3  2002/08/20 14:48:41  vofka
00003 // FiniteStateMachine-config.h removed from installing. Loading exported to the loader class. Saver introduced. Error codes exported to FSMErrorCodes.
00004 //
00005 // Revision 1.2  2002/08/13 11:06:32  vofka
00006 // automake support added
00007 //
00008 // Revision 1.1  2002/07/22 17:21:00  vofka
00009 // SimpleTransition, PushTransition, PopTransition added, not implemented yet
00010 //
00011 // Revision 1.15  2002/06/20 12:22:10  bobka
00012 // LGPL license
00013 //
00014 //
00015 
00016 #ifdef _MSC_VER
00017         #pragma warning( disable : 4786 ) // 'identifier' : identifier was truncated to 'number' characters in the debug information
00018 //      #pragma warning( disable : 4503 ) // 'identifier' : decorated name length exceeded, name was truncated
00019 //      #pragma warning( disable : 4250 ) // 'class1' : inherits 'class2::member' via dominance
00020         #pragma warning( disable : 4251 ) // 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
00021 #endif
00022 #ifdef __INTEL_COMPILER
00023         #pragma warning( disable : 985  ) // == C4786
00024 #endif
00025 #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
00026 //      #pragma set woff 1174
00027 #endif
00028 
00029 #include "FSM.h"
00030 #include "FiniteStateMachine-config.h"
00031 #include "FSMErrorCodes.h"
00032 
00033 #ifdef HAVE_LIBIWRAPPER
00034 #       include <ilibrary.h>
00035 #else
00036 #       ifdef WIN32
00037 #               include <windows.h>
00038 #       else
00039 #               include <dlfcn.h>
00040 #       endif
00041 #endif
00042 
00043 namespace FSM {
00044         #ifdef HAVE_LIBIWRAPPER
00045                 using iLIB::iLibrary;
00046         #endif
00047 
00049 //              Constructor
00051 CFiniteStateMachine::CFiniteStateMachine()
00052 :m_InitialState("")
00053 ,m_CurrentState(NULL)
00054 ,m_Running(false)
00055 {
00056         RegisterBaseTypes();
00057 }
00058 
00060 //              Destructor
00062 CFiniteStateMachine::~CFiniteStateMachine()
00063 {
00064         if (m_Running) Stop();
00065         Clear();
00066 }
00067 
00069 //              States
00071 CFSMState* CFiniteStateMachine::AddState(const char *stateName, const char *className)
00072 {
00073         CFSMState *State = NULL;
00074 
00075         State = (CFSMState *)Create(className);
00076         if(State)
00077         {
00078                 State->SetName(stateName);
00079 
00080                 const pair<State_Map::iterator,bool>result = m_States.insert(State_Map::value_type(stateName, State));
00081                 if(result.second == false)
00082                 {
00083                         iThrow(WARNING(FSM_STATE_DEFINED_TWICE), stateName);
00084                 }
00085         }
00086         return State;
00087 }
00088 
00089 CFSMState*      CFiniteStateMachine::GetState(const char *stateName) const
00090 {
00091         CFSMState* res = NULL;
00092         if (stateName)
00093         {
00094                 State_Map::const_iterator i = m_States.find(stateName);
00095                 if(!(i==m_States.end()))
00096                 {
00097                         res = (*i).second;
00098                 } else {
00099                         iThrow(CRITICAL(FSM_STATE_NOT_FOUND), stateName);
00100                 }
00101         } else
00102         {
00103                         iThrow(CRITICAL(FSM_STATE_NOT_FOUND), "");
00104         }
00105         return res;
00106 }
00107 
00108 bool CFiniteStateMachine::DeleteState(CFSMState *state)
00109 {
00110         bool res = false;
00111 
00112         State_Map::iterator i = m_States.begin();
00113         while( !( i == m_States.end() ) )
00114         {
00115                 if ( (*i).second == state )
00116                 {
00117                         if(!(m_Running && m_CurrentState==state))
00118                         {
00119                                 state->DeleteThis();
00120                                 m_States.erase(i);
00121                                 res = true;
00122                         } else {
00123                                 iThrow(CRITICAL(FSM_CANNOT_DELETE_CURRENT), state->GetName());
00124                         }
00125                         break;
00126                 }
00127                 ++i;
00128         }
00129         if (res==false)
00130         {
00131                 iThrow(CRITICAL(FSM_STATE_NOT_FOUND), state->GetName());
00132         }
00133         return res;
00134 }
00135 
00136 bool CFiniteStateMachine::DeleteState(const char *stateName)
00137 {
00138         bool res = false;
00139         CFSMState* state = GetState(stateName);
00140         if (state)
00141         {
00142                 res = DeleteState(state);
00143         } else
00144         {
00145                 iRethrow();
00146         }
00147         return res;
00148 }
00149 
00150 State_Map::const_iterator CFiniteStateMachine::GetStatesBegin() const
00151 {
00152         return m_States.begin();
00153 }
00154 
00155 State_Map::const_iterator CFiniteStateMachine::GetStatesEnd() const
00156 {
00157         return m_States.end();
00158 }
00159 
00161 //              Transitions
00163 CFSMTransition* CFiniteStateMachine::AddTransition(const char *stateName, const char* onEvent, const char *className)
00164 {
00165         CFSMTransition* res = NULL;
00166         CFSMState* state = GetState(stateName);
00167         if (state)
00168         {
00169                 res = state->AddTransition(onEvent, className);
00170                 if (!res)
00171                 {
00172                         iRethrow();
00173                 }
00174         } else {
00175                 iRethrow();
00176         }
00177         return res;
00178 }
00179 
00180 CFSMTransition* CFiniteStateMachine::AddSimpleTransition(const char *stateName, const char *toStateName, const char* onEvent)
00181 {
00182         CFSMTransition* res = NULL;
00183         CFSMState* state = GetState(stateName);
00184         if (state)
00185         {
00186                 res = state->AddSimpleTransition(toStateName, onEvent);
00187                 if (!res)
00188                 {
00189                         iRethrow();
00190                 }
00191         } else {
00192                 iRethrow();
00193         }
00194         return res;
00195 }
00196 
00197 /*
00198 bool CFiniteStateMachine::DeleteTransition(const char* fromState, const char* event, const char* toState)
00199 {
00200         bool res = false;
00201         CFSMState* state = NULL;
00202         CFSMTransition* trans = NULL;
00203         if (fromState)
00204         {
00205                 state = GetState(fromState);
00206                 if (state)
00207                 {
00208                         trans = state->GetTransition(event, toState);
00209                         if (!trans)     iRethrow();
00210                 } else // state not found
00211                 {
00212                         iRethrow();
00213                 }
00214         } else
00215         {
00216                 // alle states durchgehen
00217                 State_Map::const_iterator item = m_States.begin();
00218                 while(!(item==m_States.end()))
00219                 {
00220                         state = (*item).second;
00221                         trans = state->GetTransition(event, toState);
00222                         if (trans) break;
00223                 }
00224                 if(item==m_States.end())
00225                 {
00226                         iThrow(CRITICAL(FSM_TRANSITION_NOT_FOUND));
00227                 }
00228         }
00229 
00230         if (trans)
00231         {
00232                 res = state->DeleteTransition(trans);
00233                 if (!res)
00234                 {
00235                         iRethrow();
00236                 }
00237         } else {
00238                 iRethrow();
00239         }
00240         return res;
00241 }
00242 */
00243 
00244 bool CFiniteStateMachine::DeleteTransition(const char* fromState, int index)
00245 {
00246         bool res = false;
00247         CFSMState* state = NULL;
00248         CFSMTransition* trans = NULL;
00249         if (fromState)
00250         {
00251                 state = GetState(fromState);
00252                 if (state)
00253                 {
00254                         trans = state->GetTransition(index);
00255                         if (!trans)     iRethrow();
00256                 } else // state not found
00257                 {
00258                         iRethrow();
00259                 }
00260         } else
00261         {
00262                 iThrow(CRITICAL(FSM_STATE_NOT_FOUND), "");
00263         }
00264 
00265         if (trans)
00266         {
00267                 res = state->DeleteTransition(trans);
00268                 if (!res)
00269                 {
00270                         iRethrow();
00271                 }
00272         } else {
00273                 iRethrow();
00274         }
00275         return res;
00276 }
00277 
00279 //              Conditions
00281 CFSMCondition* CFiniteStateMachine::AddCondition(const char *stateName, int index, const char *className)
00282 {
00283         CFSMState *state = GetState(stateName);
00284         if (!state)
00285         {
00286                 iRethrow();
00287                 return NULL;
00288         }
00289 
00290         CFSMTransition *transition = state->GetTransition(index);
00291         if (!transition)
00292         {
00293                 iRethrow();
00294                 return NULL;
00295         }
00296 
00297         CFSMCondition *condition = transition->AddCondition(className);
00298         if (!condition)
00299         {
00300                 iRethrow();
00301         }
00302 
00303         return condition;
00304 }
00305 
00307 //              Actions
00309 CFSMAction* CFiniteStateMachine::AddEnterAction(const char *stateName, const char *className)
00310 {
00311         CFSMAction* res = NULL;
00312         CFSMState* state = GetState(stateName);
00313         if (state)
00314         {
00315                 res = state->AddEnterAction(className);
00316                 if (!res)
00317                 {
00318                         iRethrow();
00319                 }
00320         } else {
00321                 iRethrow();
00322         }
00323         return res;
00324 }
00325 
00326 CFSMAction* CFiniteStateMachine::AddLeaveAction(const char *stateName, const char *className)
00327 {
00328         CFSMAction* res = NULL;
00329         CFSMState* state = GetState(stateName);
00330         if (state)
00331         {
00332                 res = state->AddLeaveAction(className);
00333                 if (!res)
00334                 {
00335                         iRethrow();
00336                 }
00337         } else {
00338                 iRethrow();
00339         }
00340         return res;
00341 }
00342 
00343 CFSMAction* CFiniteStateMachine::AddAction(const char *stateName, int index, const char *className)
00344 {
00345         CFSMState *state = GetState(stateName);
00346         if (!state)
00347         {
00348                 iRethrow();
00349                 return NULL;
00350         }
00351 
00352         CFSMTransition *transition = state->GetTransition(index);
00353         if (!transition)
00354         {
00355                 iRethrow();
00356                 return NULL;
00357         }
00358 
00359         CFSMAction *action = transition->AddAction(className);
00360         if (!action)
00361         {
00362                 iRethrow();
00363         }
00364 
00365         return action;
00366 }
00367 
00369 //              Variables
00371 bool CFiniteStateMachine::AddVariable(const char *varName, const int initValue)
00372 {
00373         VM_VT v(varName, initValue);
00374         const pair<Var_Map::iterator,bool>result = m_Variables.insert(v);
00375         if(result.second == false)
00376         {
00377                 iThrow(WARNING(FSM_VARAIBLE_DEFINED_TWICE), varName);
00378         }
00379         return result.second;
00380 }
00381 
00382 bool CFiniteStateMachine::DeleteVariable(const char* varName)
00383 {
00384         bool res = false;
00385 
00386         Var_Map::iterator i = m_Variables.find(varName);
00387         if(!(i==m_Variables.end()))
00388         {
00389                 m_Variables.erase(i);
00390                 res = true;
00391         } else
00392         {
00393                 iThrow(CRITICAL(FSM_VARIABLE_NOT_FOUND), varName);
00394         }
00395         return res;
00396 }
00397 
00398 bool CFiniteStateMachine::SetVariable(const char *varName, const int value)
00399 {
00400         bool res = false;
00401         Var_Map::iterator i = m_Variables.find(varName);
00402         if(!(i==m_Variables.end()))
00403         {
00404                 (*i).second = value;
00405                 res = true;
00406         } else {
00407                 iThrow(CRITICAL(FSM_VARIABLE_NOT_FOUND), varName);
00408         }
00409         return res;
00410 }
00411 
00412 bool CFiniteStateMachine::GetVariable(const char *varName, int &value) const
00413 {
00414         bool res = false;
00415         Var_Map::const_iterator i = m_Variables.find(varName);
00416         if(!(i==m_Variables.end()))
00417         {
00418                 value = (*i).second;
00419                 res = true;
00420         } else {
00421                 iThrow(CRITICAL(FSM_VARIABLE_NOT_FOUND), varName);
00422         }
00423         return res;
00424 }
00425 
00426 Var_Map::const_iterator CFiniteStateMachine::GetVarsBegin() const
00427 {
00428         return m_Variables.begin();
00429 }
00430 
00431 Var_Map::const_iterator CFiniteStateMachine::GetVarsEnd() const
00432 {
00433         return m_Variables.end();
00434 }
00435 
00437 //              Operate FSM
00439 bool CFiniteStateMachine::SetInitialState(const char *stateName)
00440 {
00441         bool res = false;
00442         if(m_Running)
00443         {
00444                 iThrow(WARNING(FSM_INITIAL_AFTER_START));
00445         } else
00446         {
00447                 m_InitialState = stateName;
00448                 res = true;
00449         }
00450         return res;
00451 }
00452 
00453 const char* CFiniteStateMachine::GetInitialState() const
00454 {
00455         return m_InitialState.c_str();
00456 }
00457 
00458 bool CFiniteStateMachine::Start(const char *stateName)
00459 {
00460         if(!m_Running)
00461         {
00462                 if(stateName!=NULL)
00463                 {
00464                         m_InitialState = stateName;
00465                 }
00466                 m_CurrentState = GetState(m_InitialState.c_str());
00467                 if (!m_CurrentState)
00468                 {
00469                         iRethrow();
00470                 } else
00471                 {
00472                         m_CurrentState->Activate();
00473                         m_Running=true;
00474                 }
00475         } else
00476         {
00477                 iThrow(CRITICAL(FSM_ALREADY_STARTED));
00478         }
00479         return m_Running;
00480 }
00481 
00482 void CFiniteStateMachine::Stop()
00483 {
00484         if (m_Running)
00485         {
00486                 m_CurrentState->Deactivate();
00487                 m_CurrentState=NULL;
00488                 m_Running = false;
00489         }
00490 }
00491 
00492 bool CFiniteStateMachine::ProcessEvent(const char *Event, void *a, void *b, bool *consumed)
00493 {
00494         bool res = false;
00495         if(m_Running)
00496         {
00497                 CFSMTransition* trans = NULL;
00498                 if (m_CurrentState->GetTransition(&trans, Event, a, b))
00499                 {
00500                         if (trans)
00501                         {
00502                                 if(consumed)
00503                                 {
00504                                         *consumed = true;
00505                                 }
00506                                 if(! (res = trans->Execute(Event, a, b)))
00507                                 {
00508                                         iRethrow();
00509                                 }
00510                         } else
00511                         {
00512                                 if (consumed)
00513                                 {
00514                                         *consumed = false;
00515                                 }
00516                                 res = true;
00517                         }
00518                 } else
00519                 {
00520                         iRethrow();
00521                 }
00522         } else
00523         {
00524                 iThrow(CRITICAL(FSM_NOT_STARTED));
00525         }
00526         return res;
00527 }
00528 
00529 CFSMState *CFiniteStateMachine::GetCurrentState() const
00530 {
00531         return m_CurrentState;
00532 }
00533 
00534 bool CFiniteStateMachine::Clear()
00535 {
00536         bool res = false;
00537         if (!m_Running)
00538         {
00539                 // delete states
00540                 State_Map::iterator s = m_States.begin();
00541                 if(!(s==m_States.end()))
00542                 {
00543                         delete (*s).second;
00544                         (*s).second = NULL;
00545                         m_States.erase(s);
00546                         s = m_States.begin(); // The first is erased. Now get the new begin.
00547 
00548                 }
00549 
00550                 // delete varaibles
00551                 Var_Map::iterator v = m_Variables.begin();
00552                 if(!(v==m_Variables.end()))
00553                 {
00554                         (*v).second = 0;
00555                         m_Variables.erase(v);
00556                         v = m_Variables.begin();
00557                 }
00558 
00559                 m_InitialState = "";
00560                 res = true;
00561         } else
00562         {
00563                 iThrow(CRITICAL(FSM_CLEAR_STARTED));
00564         }
00565         return res;
00566 }
00567 
00569 //              Private Functions
00571 
00572 void CFiniteStateMachine::RegisterBaseTypes()
00573 {
00574         Register("State", CFSMState::Create);
00575         Register("SimpleTransition", CFSMSimpleTransition::Create);
00576         Register("PushTransition", CFSMPushTransition::Create);
00577         Register("PopTransition", CFSMPopTransition::Create);
00578         Register("TestVariable", CFSMConditionTestVariable::Create);
00579         Register("SetVariable", CFSMActionSetVariable::Create);
00580         Register("IncrVariable", CFSMActionIncrVariable::Create);
00581 }
00582 
00583 bool CFiniteStateMachine::SwitchToState(CFSMState* newState)
00584 {       
00585         bool res = true;
00586         if (newState)
00587         {
00588                 if (newState != m_CurrentState)
00589                 {
00590                         if (m_CurrentState) res = m_CurrentState->Deactivate();
00591                         if (res)
00592                         {
00593                                 m_CurrentState=newState;
00594                                 res = m_CurrentState->Activate();
00595                                 if (res)
00596                                 {
00597                                         res = ProcessEvent("UPDATE");
00598                                         if (!res)
00599                                         {
00600                                                 iRethrow();
00601                                         }
00602                                 } else
00603                                 {
00604                                         iRethrow();
00605                                 }
00606                         } else
00607                         {
00608                                 iRethrow();
00609                         }
00610                 }
00611         } else 
00612         {
00613                 iThrow(CRITICAL(FSM_STATE_NOT_FOUND), "NULL");
00614         }
00615         return res;
00616 }
00617 
00618 bool CFiniteStateMachine::PushState(CFSMState* newState)
00619 {       
00620         bool res = SwitchToState(newState);
00621         if (res)
00622         {
00623                 // push the state onto the stack
00624         } else
00625         {
00626                 iRethrow();
00627         }
00628         return res;
00629 }
00630 
00631 bool CFiniteStateMachine::PopState()
00632 {       
00633         bool res = false;
00634         CFSMState *newState = NULL;
00635 
00636         // pop state from stack, return false if not stack ampty
00637 
00638         SwitchToState(newState);
00639         if( !res )
00640         {
00641                 iRethrow();
00642         }
00643         return res;
00644 }
00645 
00647 // Register dynamic loaded DLL
00649 void CFiniteStateMachine::Register(const char *className, FSMObjectCreateMethod create)
00650 {
00651         // register
00652         if (FSMObjectCreationMethods.find(className)!=FSMObjectCreationMethods.end())
00653         {
00654                 iThrow(WARNING(FSM_CLASS_REGISTERED_TWICE), className);
00655                 return;
00656         }
00657         FSMObjectCreationMethods.insert(pair<const string,FSMObjectCreateMethod>(className,create));
00658 }
00659 
00661 // Create Instance for named Class
00663 CFSMObject* CFiniteStateMachine::Create(const char *className)
00664 {
00665         if (className==NULL || className[0]=='\0')
00666         {
00667                 iThrow(WARNING(FSM_CANNOT_CREATE_CLASS), "");
00668                 return NULL;
00669         }
00670 
00671         FSMObjectCreate_Map::iterator item = FSMObjectCreationMethods.find(className);
00672         if (item==FSMObjectCreationMethods.end())
00673         {
00674 #ifndef _WIN32_WCE
00675                 if(!LoadClass(className))
00676                 {
00677                         iRethrow();
00678                         return NULL;
00679                 }
00680 
00681                 item = FSMObjectCreationMethods.find(className);
00682                 if (item==FSMObjectCreationMethods.end())
00683                 {
00684                         iThrow(WARNING(FSM_CANNOT_CREATE_CLASS), className);
00685                         return NULL;
00686                 }
00687 #else
00688                 iThrow(WARNING(FSM_CANNOT_CREATE_CLASS), className);
00689                 return NULL;
00690 #endif
00691         }
00692 
00693         FSMObjectCreateMethod create = (*item).second;
00694         CFSMObject *obj = create();
00695         obj->SetFSM(this);
00696         obj->SetClassName(className);
00697         return (obj);
00698 }
00699 
00700 #ifndef _WIN32_WCE
00701 
00702 // Dynamiclly load external Object
00704 bool CFiniteStateMachine::LoadClass(const char *className)
00705 {
00706         string libName("");
00707 
00708 #       ifdef WIN32
00709         libName += className;
00710         libName += ".dll";
00711 #       else 
00712         libName += "lib";
00713         libName += className;
00714         libName += ".so";
00715 #       endif
00716 
00717 #       ifdef HAVE_LIBIWRAPPER
00718         iLibrary* lib = iLibrary::Load(libName.c_str());
00719 #       else
00720 #               ifdef WIN32
00721                 HINSTANCE lib = LoadLibrary(libName.c_str());
00722 #               else
00723                 void *lib = dlopen(libName.c_str(), RTLD_NOW);
00724 #               endif
00725 #       endif
00726 
00727         if (lib==NULL)
00728         {
00729                 return false;
00730         }
00731 
00732         InitClassF InitClass;
00733 #       ifdef HAVE_LIBIWRAPPER
00734                 InitClass = (InitClassF)lib->GetProc("InitClass");
00735 #       else
00736 #               ifdef WIN32
00737                 InitClass = (InitClassF)GetProcAddress(lib, "InitClass");
00738 #               else
00739                 InitClass = (InitClassF)dlsym(lib, "InitClass");
00740 #               endif
00741 #       endif
00742 
00743         if (!InitClass)
00744         {
00745                 iHandleLastError();
00746                 return false;
00747         }
00748 
00749         (*InitClass)(this);
00750 
00751         // the library have to be unloaded at application exit !!!
00752 
00753         return true;
00754 }
00755 #endif
00756 
00757 
00759 }; // namespace FSM
00760 

© 2002 by C-LAB
generated by doxygen