This library is designed to create and run state graphs. It supports hierarchical states and parallel states execution.
Diff: StateMachineLib/ParallelStateMachine.h
- Revision:
- 0:f4fdca2c4c67
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/StateMachineLib/ParallelStateMachine.h Tue Oct 03 08:29:22 2017 +0000 @@ -0,0 +1,165 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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__*/ \ No newline at end of file