This library is designed to create and run state graphs. It supports hierarchical states and parallel states execution.
StateMachineLib/ParallelStateMachine.h
- Committer:
- martin13
- Date:
- 2021-02-02
- Revision:
- 4:22b4462fcb26
- Parent:
- 0:f4fdca2c4c67
File content as of revision 4:22b4462fcb26:
//////////////////////////////////////////////////////////////////////////////// // Copyright Rottor SAS 2017 // All rigths reserved. // // File Name : ParallelStateMachine.h // Authors : Martin Matignon // // If you find any bug or if you have any question please contact // Martin Matignon <martin.matignon@rottor.fr> // Nicolas Forestier <nicolas.forestier@rottor.fr> // //////////////////////////////////////////////////////////////////////////////// #ifndef __SM_PARALLEL_STATE_MACHINE_H__ #define __SM_PARALLEL_STATE_MACHINE_H__ #include "StateMachine.h" /** A class for storing and calling a pointer to a static or member function */ class OutcomesResolver { public: /** Constructor */ OutcomesResolver(): _function(0), _object(0) { /* Empty */ } /** Attach a static function */ void attachOutcomesResolver(const char* (*function)(const char**, int) = 0) { _function = function; _object = 0; } /** Attach a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of member function to attach */ template<typename T> void attachOutcomesResolver(T *object, const char* (T::*member)(const char**, int)) { _object = static_cast<void*>(object); memcpy(_member, (char*)&member, sizeof(member)); _membercaller = &OutcomesResolver::membercaller<T>; _function = 0; } /** Call the attached static or member function */ const char* callOutcomesResolver(const char** outcomes, int nb_outcomes) { if (_function) { return _function(outcomes, nb_outcomes); } else if (_object) { return _membercaller(_object, _member, outcomes, nb_outcomes); } return NULL; } private: template<typename T> static const char* membercaller(void *object, char *member, const char** outcomes, int nb_outcomes) { T* o = static_cast<T*>(object); const char* (T::*m)(const char**, int); memcpy((char*)&m, member, sizeof(m)); return (o->*m)(outcomes, nb_outcomes); } /** Static function pointer - 0 if none attached */ const char* (*_function)(const char**, int); /** Object this pointer - 0 if none attached */ void *_object; /** Raw member function pointer storage - converted back by registered _membercaller */ char _member[16]; /** Registered membercaller function to convert back and call _member on _object */ const char* (*_membercaller)(void*, char*, const char**, int); }; /** A class to store and execute parallel states */ class ParallelStateMachine : public StateMachine, public OutcomesResolver { public: ParallelStateMachine(const char* uuid, UserData *ud = new UserData()): StateMachine(uuid, ud) { attachOutcomesResolver(this, &ParallelStateMachine::defaultOutcomesResolver); } virtual void onEntry(){}; virtual const char* onExecute(){ int nbStates = this->getNumberStates(); State *stateList[nbStates]; Thread thread[nbStates]; const char* outcomes[nbStates]; StateMachine::StateItem_t* states = getStatesList(); for (int i=0; i < nbStates; i++) { stateList[i] = states->state; stateList[i]->onEntry(); thread[i].start(callback(stateList[i], &State::_onParallelExecute)); states = states->next; } for (int i=0; i < nbStates; i++){ thread[i].join(); stateList[i]->onExit(); } for (int i=0; i < nbStates; i++){ outcomes[i] = stateList[i]->getOutcome(); if (strcmp(outcomes[i], PREEMPTED) == 0){ return PREEMPTED; } } // Resolve the states outcomes const char* out = callOutcomesResolver(outcomes, nbStates); if (out != NULL) { return out; } return ABORTED; } virtual void onExit(){} const char* defaultOutcomesResolver(const char** outcomes, int nb_outcomes){ // Check if all outcomes are succeded else return aborted for(int i = 0; i < nb_outcomes; i++){ if (strcmp(outcomes[i], SUCCEDED) != 0){ return ABORTED; } } return SUCCEDED; } }; #endif /* #ifndef __SM_PARALLEL_STATE_MACHINE_H__*/