Table driven Finite State Machine library based on the Harel state machine, supporting actions on transitions, state entry and state exit. Comes with example illustrating use with interrupts and timers. 03/01/2010 - fixed potential memory leak in DebugTrace.
State.h
- Committer:
- snatch59
- Date:
- 2010-01-03
- Revision:
- 0:918566a376fb
File content as of revision 0:918566a376fb:
/* * FiniteStateMachine. Table driven Finite State Machine library * based on theHarel state machine, supporting actions on transitions, state * entry and state exit. * * Copyright (C) <2009> Petras Saduikis <petras@petras.co.uk> * * This file is part of FiniteStateMachine. * * FiniteStateMachine is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FiniteStateMachine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with DebugTrace. If not, see <http://www.gnu.org/licenses/>. */ #ifndef SNATCH59_STATE_H #define SNATCH59_STATE_H #include <mbed.h> #include "FSMDefs.h" #include "FSM.h" STATE_TEMPLATE_ class StateTransition; #include "StateTransition.h" STATE_TEMPLATE_ class State { public: State(const char* state_name, ActionPtrType entry_action_ptr, ActionPtrType exit_action_ptr); ~State( ); STATE_* match(const int event_id, STATE_TRANSITION_* &transition) const; void addTransitions(const TRANSITION_DEFINITION_* &transitions, const int total_transitions, STATE_** states, const int total_states); void doEntryAction(StateObjectType* &its_state_object); void doExitAction(StateObjectType* &its_state_object); const char* getName( ) const; private: const char* name; int totalTransitions; ActionPtrType entryAction; ActionPtrType exitAction; STATE_TRANSITION_** itsTransitions; }; STATE_TEMPLATE_ inline const char* STATE_::getName() const { return name; } STATE_TEMPLATE_ STATE_::State(const char* state_name, ActionPtrType entry_action_ptr, ActionPtrType exit_action_ptr) : name(state_name), entryAction(entry_action_ptr), exitAction(exit_action_ptr), totalTransitions(0) { } STATE_TEMPLATE_ STATE_::~State( ) { if (itsTransitions != NULL) { for (int i = 0; i < totalTransitions; i++) { delete itsTransitions[i]; } // dust to dust, ashes to ashes free(itsTransitions); } } STATE_TEMPLATE_ void STATE_::addTransitions(const TRANSITION_DEFINITION_* &transitions, const int total_transitions, STATE_** states, const int total_states) { int tcount = 0; for (int i = 0; i < total_transitions; i++) { TRANSITION_DEFINITION_ tdef = transitions[i]; if (0 == strcmp(name, tdef.ownerState)) { tcount++; } } itsTransitions = (STATE_TRANSITION_**)malloc(sizeof(STATE_TRANSITION_*)*tcount); for (int i = 0; i < total_transitions; i++) { TRANSITION_DEFINITION_ tdef = transitions[i]; if (0 == strcmp(name, tdef.ownerState)) { STATE_* new_state_ptr = NULL; for (int k = 0; k < total_states; k++) { if (0 == strcmp(states[k]->getName(), tdef.newState)) { new_state_ptr = states[k]; break; } } itsTransitions[totalTransitions++] = new STATE_TRANSITION_(tdef.eventId, tdef.action, new_state_ptr, tdef.mode); } } } STATE_TEMPLATE_ STATE_* STATE_::match(const int event_id, STATE_TRANSITION_* &transition) const { if (0 == totalTransitions) { return NULL; } STATE_* new_state = NULL; int i = 0; do { new_state = itsTransitions[i]->match(event_id); transition = itsTransitions[i++]; } while (NULL == new_state && i < totalTransitions); return new_state; } STATE_TEMPLATE_ void STATE_::doEntryAction(StateObjectType* &its_state_object) { if (entryAction != NULL) { (its_state_object->*entryAction)( ); } } STATE_TEMPLATE_ void STATE_::doExitAction(StateObjectType* &its_state_object) { if (exitAction != NULL) { (its_state_object->*exitAction)( ); } } #endif