This library is designed to create and run state graphs. It supports hierarchical states and parallel states execution.

Committer:
martin13
Date:
Tue Feb 12 08:56:43 2019 +0000
Revision:
3:d4d69d0d8381
Parent:
0:f4fdca2c4c67
Added README.md

Who changed what in which revision?

UserRevisionLine numberNew contents of line
martin13 0:f4fdca2c4c67 1 ////////////////////////////////////////////////////////////////////////////////
martin13 0:f4fdca2c4c67 2 // Copyright Rottor SAS 2017
martin13 0:f4fdca2c4c67 3 // All rigths reserved.
martin13 0:f4fdca2c4c67 4 //
martin13 0:f4fdca2c4c67 5 // File Name : ParallelStateMachine.h
martin13 0:f4fdca2c4c67 6 // Authors : Martin Matignon
martin13 0:f4fdca2c4c67 7 //
martin13 0:f4fdca2c4c67 8 // If you find any bug or if you have any question please contact
martin13 0:f4fdca2c4c67 9 // Martin Matignon <martin.matignon@rottor.fr>
martin13 0:f4fdca2c4c67 10 // Nicolas Forestier <nicolas.forestier@rottor.fr>
martin13 0:f4fdca2c4c67 11 //
martin13 0:f4fdca2c4c67 12 ////////////////////////////////////////////////////////////////////////////////
martin13 0:f4fdca2c4c67 13
martin13 0:f4fdca2c4c67 14 #ifndef __SM_PARALLEL_STATE_MACHINE_H__
martin13 0:f4fdca2c4c67 15 #define __SM_PARALLEL_STATE_MACHINE_H__
martin13 0:f4fdca2c4c67 16
martin13 0:f4fdca2c4c67 17 #include "StateMachine.h"
martin13 0:f4fdca2c4c67 18
martin13 0:f4fdca2c4c67 19 /** A class for storing and calling a pointer to a static or member function
martin13 0:f4fdca2c4c67 20 */
martin13 0:f4fdca2c4c67 21 class OutcomesResolver {
martin13 0:f4fdca2c4c67 22
martin13 0:f4fdca2c4c67 23 public:
martin13 0:f4fdca2c4c67 24
martin13 0:f4fdca2c4c67 25 /** Constructor
martin13 0:f4fdca2c4c67 26 */
martin13 0:f4fdca2c4c67 27 OutcomesResolver():
martin13 0:f4fdca2c4c67 28 _function(0),
martin13 0:f4fdca2c4c67 29 _object(0)
martin13 0:f4fdca2c4c67 30 {
martin13 0:f4fdca2c4c67 31 /* Empty */
martin13 0:f4fdca2c4c67 32 }
martin13 0:f4fdca2c4c67 33
martin13 0:f4fdca2c4c67 34 /** Attach a static function
martin13 0:f4fdca2c4c67 35 */
martin13 0:f4fdca2c4c67 36 void attachOutcomesResolver(const char* (*function)(const char**, int) = 0) {
martin13 0:f4fdca2c4c67 37 _function = function;
martin13 0:f4fdca2c4c67 38 _object = 0;
martin13 0:f4fdca2c4c67 39 }
martin13 0:f4fdca2c4c67 40
martin13 0:f4fdca2c4c67 41 /** Attach a member function
martin13 0:f4fdca2c4c67 42 *
martin13 0:f4fdca2c4c67 43 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
martin13 0:f4fdca2c4c67 44 * @param function The address of member function to attach
martin13 0:f4fdca2c4c67 45 */
martin13 0:f4fdca2c4c67 46 template<typename T>
martin13 0:f4fdca2c4c67 47 void attachOutcomesResolver(T *object, const char* (T::*member)(const char**, int)) {
martin13 0:f4fdca2c4c67 48 _object = static_cast<void*>(object);
martin13 0:f4fdca2c4c67 49 memcpy(_member, (char*)&member, sizeof(member));
martin13 0:f4fdca2c4c67 50 _membercaller = &OutcomesResolver::membercaller<T>;
martin13 0:f4fdca2c4c67 51 _function = 0;
martin13 0:f4fdca2c4c67 52 }
martin13 0:f4fdca2c4c67 53
martin13 0:f4fdca2c4c67 54 /** Call the attached static or member function
martin13 0:f4fdca2c4c67 55 */
martin13 0:f4fdca2c4c67 56 const char* callOutcomesResolver(const char** outcomes, int nb_outcomes) {
martin13 0:f4fdca2c4c67 57 if (_function) {
martin13 0:f4fdca2c4c67 58 return _function(outcomes, nb_outcomes);
martin13 0:f4fdca2c4c67 59 } else if (_object) {
martin13 0:f4fdca2c4c67 60 return _membercaller(_object, _member, outcomes, nb_outcomes);
martin13 0:f4fdca2c4c67 61 }
martin13 0:f4fdca2c4c67 62 return NULL;
martin13 0:f4fdca2c4c67 63 }
martin13 0:f4fdca2c4c67 64
martin13 0:f4fdca2c4c67 65 private:
martin13 0:f4fdca2c4c67 66
martin13 0:f4fdca2c4c67 67 template<typename T>
martin13 0:f4fdca2c4c67 68 static const char* membercaller(void *object,
martin13 0:f4fdca2c4c67 69 char *member,
martin13 0:f4fdca2c4c67 70 const char** outcomes,
martin13 0:f4fdca2c4c67 71 int nb_outcomes) {
martin13 0:f4fdca2c4c67 72 T* o = static_cast<T*>(object);
martin13 0:f4fdca2c4c67 73 const char* (T::*m)(const char**, int);
martin13 0:f4fdca2c4c67 74 memcpy((char*)&m, member, sizeof(m));
martin13 0:f4fdca2c4c67 75 return (o->*m)(outcomes, nb_outcomes);
martin13 0:f4fdca2c4c67 76 }
martin13 0:f4fdca2c4c67 77
martin13 0:f4fdca2c4c67 78 /** Static function pointer - 0 if none attached
martin13 0:f4fdca2c4c67 79 */
martin13 0:f4fdca2c4c67 80 const char* (*_function)(const char**, int);
martin13 0:f4fdca2c4c67 81
martin13 0:f4fdca2c4c67 82 /** Object this pointer - 0 if none attached
martin13 0:f4fdca2c4c67 83 */
martin13 0:f4fdca2c4c67 84 void *_object;
martin13 0:f4fdca2c4c67 85
martin13 0:f4fdca2c4c67 86 /** Raw member function pointer storage - converted back by registered _membercaller
martin13 0:f4fdca2c4c67 87 */
martin13 0:f4fdca2c4c67 88 char _member[16];
martin13 0:f4fdca2c4c67 89
martin13 0:f4fdca2c4c67 90 /** Registered membercaller function to convert back and call _member on _object
martin13 0:f4fdca2c4c67 91 */
martin13 0:f4fdca2c4c67 92 const char* (*_membercaller)(void*, char*, const char**, int);
martin13 0:f4fdca2c4c67 93
martin13 0:f4fdca2c4c67 94 };
martin13 0:f4fdca2c4c67 95
martin13 0:f4fdca2c4c67 96 /** A class to store and execute parallel states
martin13 0:f4fdca2c4c67 97 */
martin13 0:f4fdca2c4c67 98 class ParallelStateMachine : public StateMachine,
martin13 0:f4fdca2c4c67 99 public OutcomesResolver {
martin13 0:f4fdca2c4c67 100
martin13 0:f4fdca2c4c67 101 public:
martin13 0:f4fdca2c4c67 102
martin13 0:f4fdca2c4c67 103 ParallelStateMachine(const char* uuid, UserData *ud = new UserData()):
martin13 0:f4fdca2c4c67 104 StateMachine(uuid, ud)
martin13 0:f4fdca2c4c67 105 {
martin13 0:f4fdca2c4c67 106 attachOutcomesResolver(this, &ParallelStateMachine::defaultOutcomesResolver);
martin13 0:f4fdca2c4c67 107 }
martin13 0:f4fdca2c4c67 108
martin13 0:f4fdca2c4c67 109 virtual void onEntry(){};
martin13 0:f4fdca2c4c67 110
martin13 0:f4fdca2c4c67 111 virtual const char* onExecute(){
martin13 0:f4fdca2c4c67 112
martin13 0:f4fdca2c4c67 113 int nbStates = this->getNumberStates();
martin13 0:f4fdca2c4c67 114 State *stateList[nbStates];
martin13 0:f4fdca2c4c67 115 Thread thread[nbStates];
martin13 0:f4fdca2c4c67 116 const char* outcomes[nbStates];
martin13 0:f4fdca2c4c67 117
martin13 0:f4fdca2c4c67 118 StateMachine::StateItem_t* states = getStatesList();
martin13 0:f4fdca2c4c67 119
martin13 0:f4fdca2c4c67 120 for (int i=0; i < nbStates; i++)
martin13 0:f4fdca2c4c67 121 {
martin13 0:f4fdca2c4c67 122 stateList[i] = states->state;
martin13 0:f4fdca2c4c67 123 stateList[i]->onEntry();
martin13 0:f4fdca2c4c67 124 thread[i].start(callback(stateList[i], &State::_onParallelExecute));
martin13 0:f4fdca2c4c67 125 states = states->next;
martin13 0:f4fdca2c4c67 126 }
martin13 0:f4fdca2c4c67 127
martin13 0:f4fdca2c4c67 128 for (int i=0; i < nbStates; i++){
martin13 0:f4fdca2c4c67 129 thread[i].join();
martin13 0:f4fdca2c4c67 130 stateList[i]->onExit();
martin13 0:f4fdca2c4c67 131 }
martin13 0:f4fdca2c4c67 132
martin13 0:f4fdca2c4c67 133 for (int i=0; i < nbStates; i++){
martin13 0:f4fdca2c4c67 134 outcomes[i] = stateList[i]->getOutcome();
martin13 0:f4fdca2c4c67 135 if (strcmp(outcomes[i], PREEMPTED) == 0){
martin13 0:f4fdca2c4c67 136 return PREEMPTED;
martin13 0:f4fdca2c4c67 137 }
martin13 0:f4fdca2c4c67 138 }
martin13 0:f4fdca2c4c67 139
martin13 0:f4fdca2c4c67 140 // Resolve the states outcomes
martin13 0:f4fdca2c4c67 141 const char* out = callOutcomesResolver(outcomes, nbStates);
martin13 0:f4fdca2c4c67 142 if (out != NULL) {
martin13 0:f4fdca2c4c67 143 return out;
martin13 0:f4fdca2c4c67 144 }
martin13 0:f4fdca2c4c67 145
martin13 0:f4fdca2c4c67 146 return ABORTED;
martin13 0:f4fdca2c4c67 147 }
martin13 0:f4fdca2c4c67 148
martin13 0:f4fdca2c4c67 149 virtual void onExit(){}
martin13 0:f4fdca2c4c67 150
martin13 0:f4fdca2c4c67 151 const char* defaultOutcomesResolver(const char** outcomes, int nb_outcomes){
martin13 0:f4fdca2c4c67 152
martin13 0:f4fdca2c4c67 153 // Check if all outcomes are succeded else return aborted
martin13 0:f4fdca2c4c67 154 for(int i = 0; i < nb_outcomes; i++){
martin13 0:f4fdca2c4c67 155
martin13 0:f4fdca2c4c67 156 if (strcmp(outcomes[i], SUCCEDED) != 0){
martin13 0:f4fdca2c4c67 157 return ABORTED;
martin13 0:f4fdca2c4c67 158 }
martin13 0:f4fdca2c4c67 159 }
martin13 0:f4fdca2c4c67 160
martin13 0:f4fdca2c4c67 161 return SUCCEDED;
martin13 0:f4fdca2c4c67 162 }
martin13 0:f4fdca2c4c67 163 };
martin13 0:f4fdca2c4c67 164
martin13 0:f4fdca2c4c67 165 #endif /* #ifndef __SM_PARALLEL_STATE_MACHINE_H__*/