appkit  1.5.1
RoadNarrows Robotics Application Kit
rnr::StateMach Class Reference

Finite State Machine Class. More...

#include <StateMach.h>

Public Types

typedef std::map< int, State * > StateTblMap_T
 state table type
 

Public Member Functions

 StateMach (int nStateMachId=0, const std::string &strStateMachName="sm")
 Default contructor. More...
 
 StateMach (int nStateMachId, const std::string &strStateMachName, int nStartStateId, State *listStates[])
 List contructor. More...
 
virtual ~StateMach ()
 Destructor.
 
int addStates (State *pState,...)
 Add a list of states to this state machine. More...
 
void addState (State *pState)
 Add state to this state machine. More...
 
bool deleteState (int nStateId)
 Delete state from this state machine. More...
 
void setStartStateId (int nStartStateId)
 Set state machine's start state id. More...
 
virtual void run ()
 Run the state machine from the start. More...
 
virtual void startRecording (size_t uLimit=NO_LIMIT)
 Start recording states ids. More...
 
virtual void stopRecording ()
 Stop recording of states ids. More...
 
virtual void resumeRecording ()
 Resume recording of states ids. More...
 
virtual void eraseRecording ()
 Erase recording of states ids. More...
 
int getStateMachId () const
 Get state machine id. More...
 
std::string getStateMachName () const
 Get state machine name. More...
 
int getCurrStateId () const
 Get the current state id. More...
 
int getPrevStateId () const
 Get the previously recorded state id. More...
 
virtual void printStateMach (FILE *fp=stdout, int indent=0)
 Print out state machine. More...
 

Static Public Attributes

static const size_t NO_LIMIT = 0
 no limit on length of recording
 

Protected Member Functions

void pushStateId (int nStateid)
 Push state id onto stack of state ids. More...
 
int popStateId ()
 Pop state id from stack of state ids. More...
 
virtual void logTransition (int nCurrStateId, int nEventId, int nNextStateId)
 Log state transition. More...
 

Protected Attributes

int m_nStateMachId
 state machine id
 
std::string m_strStateMachName
 state machine name
 
StateTblMap_T m_mapStateTbl
 state table
 
int m_nStartStateId
 starting state id
 
int m_nCurrStateId
 current state id
 
int m_nMarkStateId
 mark state id of last run cycle
 
std::vector< int > m_stackStateIds
 stack of previous state ids
 
size_t m_uMaxRecording
 max recording length
 
bool m_bIsRecording
 is [not] recording work flow
 

Detailed Description

Finite State Machine Class.

Definition at line 83 of file StateMach.h.

Constructor & Destructor Documentation

rnr::StateMach::StateMach ( int  nStateMachId = 0,
const std::string &  strStateMachName = "sm" 
)

Default contructor.

Parameters
nStateMachIdState machine id.
strStateMachNameState machine name.
rnr::StateMach::StateMach ( int  nStateMachId,
const std::string &  strStateMachName,
int  nStartStateId,
State listStates[] 
)

List contructor.

This state machine owns all of the states and will automatically delete them when this state machine is deleted.

Parameters
nStateMachIdState machine id.
strStateMachNameState machine name.
nStartStateIdState id.
listStatesDeclaration list of allocated states. NULL terminated.

Member Function Documentation

void StateMach::addState ( State pState)

Add state to this state machine.

This state machine owns the state and will automatically delete it when this state machine is deleted.

Parameters
pStateAllocated state object.

Definition at line 151 of file StateMach.cxx.

References rnr::State::getStateId(), rnr::State::getStateName(), m_mapStateTbl, m_nStateMachId, and m_strStateMachName.

Referenced by addStates().

152 {
153  StateTblMap_T::iterator pos;
154 
155  if( pState != NULL )
156  {
157  if((pos = m_mapStateTbl.find(pState->getStateId())) != m_mapStateTbl.end())
158  {
159  LOGWARN("%s.%d: State [%s.%d] already exists - replacing.",
161  pos->second->getStateName().c_str(), pos->second->getStateId());
162  delete pos->second;
163  m_mapStateTbl.erase(pos);
164  }
165 
166  m_mapStateTbl[pState->getStateId()] = pState;
167 
168  LOGDIAG3("%s.%d: [%s.%d] state added.",
170  pState->getStateName().c_str(), pState->getStateId());
171  }
172 }
std::string m_strStateMachName
state machine name
Definition: StateMach.h:280
int getStateId() const
Get state id.
Definition: State.h:337
std::string getStateName() const
Get state name.
Definition: State.h:347
int m_nStateMachId
state machine id
Definition: StateMach.h:279
StateTblMap_T m_mapStateTbl
state table
Definition: StateMach.h:281
int StateMach::addStates ( State pState,
  ... 
)

Add a list of states to this state machine.

This state machine owns all of the states and will automatically delete them when this state machine is deleted.

Parameters
pStateFirst allocated state object.
...Subsequent allocated state object. Terminate list with NULL.
Returns
Returns the number of states added.

Definition at line 134 of file StateMach.cxx.

References addState().

135 {
136  va_list ap;
137  int i;
138 
139  va_start(ap, pState);
140 
141  for(i=0; pState != NULL; pState = va_arg(ap, State *), ++i)
142  {
143  addState(pState);
144  }
145 
146  va_end(ap);
147 
148  return i;
149 }
void addState(State *pState)
Add state to this state machine.
Definition: StateMach.cxx:151
bool StateMach::deleteState ( int  nStateId)

Delete state from this state machine.

Parameters
nStateIdState id.
Returns
Returns true if state is deleted, false otherwise.

Definition at line 174 of file StateMach.cxx.

References m_mapStateTbl, m_nStateMachId, and m_strStateMachName.

175 {
176  StateTblMap_T::iterator pos;
177 
178  if( (pos = m_mapStateTbl.find(nStateId)) != m_mapStateTbl.end() )
179  {
180  delete pos->second;
181  m_mapStateTbl.erase(pos);
182  return true;
183  }
184  else
185  {
186  LOGERROR("%s.%d: No state found in state table with state id=%d.",
187  m_strStateMachName.c_str(), m_nStateMachId, nStateId);
188  return false;
189  }
190 }
std::string m_strStateMachName
state machine name
Definition: StateMach.h:280
int m_nStateMachId
state machine id
Definition: StateMach.h:279
StateTblMap_T m_mapStateTbl
state table
Definition: StateMach.h:281
virtual void rnr::StateMach::eraseRecording ( )
inlinevirtual

Erase recording of states ids.

The recording start/stop state is not changed.

Definition at line 212 of file StateMach.h.

References m_stackStateIds.

213  {
214  m_stackStateIds.clear();
215  }
std::vector< int > m_stackStateIds
stack of previous state ids
Definition: StateMach.h:285
int rnr::StateMach::getCurrStateId ( ) const
inline

Get the current state id.

Returns
State id.

Definition at line 242 of file StateMach.h.

References m_nCurrStateId.

243  {
244  return m_nCurrStateId;
245  }
int m_nCurrStateId
current state id
Definition: StateMach.h:283
int rnr::StateMach::getPrevStateId ( ) const
inline

Get the previously recorded state id.

State id recording must be enabled. The previous state id never equals the current state id.

Returns
If recording is enabled and there are elements on the stack, then the state id found on the top of the stack is returned.
Otherwise State::StateIdUndef is returned.

Definition at line 258 of file StateMach.h.

References rnr::io::indent(), m_bIsRecording, m_stackStateIds, printStateMach(), and rnr::State::StateIdUndef.

259  {
260  if( m_bIsRecording && (m_stackStateIds.size() > 0) )
261  {
262  return m_stackStateIds[m_stackStateIds.size()-1];
263  }
264  else
265  {
266  return State::StateIdUndef;
267  }
268  }
std::vector< int > m_stackStateIds
stack of previous state ids
Definition: StateMach.h:285
bool m_bIsRecording
is [not] recording work flow
Definition: StateMach.h:287
static const int StateIdUndef
undefined state
Definition: State.h:166
int rnr::StateMach::getStateMachId ( ) const
inline

Get state machine id.

Returns
State machine id.

Definition at line 222 of file StateMach.h.

References m_nStateMachId.

223  {
224  return m_nStateMachId;
225  }
int m_nStateMachId
state machine id
Definition: StateMach.h:279
std::string rnr::StateMach::getStateMachName ( ) const
inline

Get state machine name.

Returns
String.

Definition at line 232 of file StateMach.h.

References m_strStateMachName.

233  {
234  return m_strStateMachName;
235  }
std::string m_strStateMachName
state machine name
Definition: StateMach.h:280
void StateMach::logTransition ( int  nCurrStateId,
int  nEventId,
int  nNextStateId 
)
protectedvirtual

Log state transition.

Todo:
Moderate logging.
Parameters
nCurrStateIdCurrent state id.
nEventIdReceived event id.
nNextStateIdNext (new) state id.

Definition at line 316 of file StateMach.cxx.

References m_mapStateTbl, m_nStateMachId, and m_strStateMachName.

317 {
318  static const char *sUndef = "#undef";
319 
320  StateTblMap_T::iterator pos;
321  string strCurr;
322  string strEvent;
323  string strAction;
324  string strNext;
325 
326  if( (pos = m_mapStateTbl.find(nCurrStateId)) != m_mapStateTbl.end() )
327  {
328  strCurr = pos->second->getStateName();
329  strEvent = pos->second->getEventName(nEventId);
330  strAction = pos->second->getActionName(nEventId);
331  }
332  else
333  {
334  strCurr = sUndef;
335  strEvent = sUndef;
336  strAction = sUndef;
337  }
338 
339  if( (pos = m_mapStateTbl.find(nNextStateId)) != m_mapStateTbl.end() )
340  {
341  strNext = pos->second->getStateName();
342  }
343  else
344  {
345  strNext = "#undef";
346  }
347 
348  LOGDIAG3("%s.%d: [%s.%d] -- %s(%s.%d) --> [%s.%d]",
350  strCurr.c_str(), nCurrStateId,
351  strAction.c_str(), strEvent.c_str(), nEventId,
352  strNext.c_str(), nNextStateId);
353 }
std::string m_strStateMachName
state machine name
Definition: StateMach.h:280
int m_nStateMachId
state machine id
Definition: StateMach.h:279
StateTblMap_T m_mapStateTbl
state table
Definition: StateMach.h:281
int StateMach::popStateId ( )
protected

Pop state id from stack of state ids.

Returns
If recording is enabled and there are elements on the stack, then the state id found on the top of the stack is returned.
Otherwise State::StateIdUndef is returned.

Definition at line 287 of file StateMach.cxx.

References m_bIsRecording, m_stackStateIds, and rnr::State::StateIdUndef.

Referenced by run().

288 {
289  int nStateId;
290 
291  if( m_bIsRecording && (m_stackStateIds.size() > 0) )
292  {
293  nStateId = m_stackStateIds.back();
294  m_stackStateIds.pop_back();
295  return nStateId;
296  }
297  else
298  {
299  return State::StateIdUndef;
300  }
301 }
std::vector< int > m_stackStateIds
stack of previous state ids
Definition: StateMach.h:285
bool m_bIsRecording
is [not] recording work flow
Definition: StateMach.h:287
static const int StateIdUndef
undefined state
Definition: State.h:166
void StateMach::printStateMach ( FILE *  fp = stdout,
int  indent = 0 
)
virtual

Print out state machine.

Parameters
fpOutput file pointer.
indentLeft indentation.

Definition at line 303 of file StateMach.cxx.

References m_mapStateTbl, m_nStateMachId, and m_strStateMachName.

Referenced by getPrevStateId().

304 {
305  StateTblMap_T::iterator iter;
306 
307  fprintf(fp, "%*sState Machine: %s.%d\n",
309 
310  for(iter = m_mapStateTbl.begin(); iter != m_mapStateTbl.end(); ++iter)
311  {
312  iter->second->printState(fp, indent+2);
313  }
314 }
std::string m_strStateMachName
state machine name
Definition: StateMach.h:280
osManipIndent indent()
Left indent at current stream indentation level.
Definition: IOManip.cxx:115
int m_nStateMachId
state machine id
Definition: StateMach.h:279
StateTblMap_T m_mapStateTbl
state table
Definition: StateMach.h:281
void StateMach::pushStateId ( int  nStateid)
protected

Push state id onto stack of state ids.

The stack preserves the state workflow history.

Note
No consecutive states with the same id are pushed onto the stack. That is, graph path cylces of length 1 are not recorded. However, cycle lengths > 1 are not detected and, so, could be recorded. For example, the state sequence a b a b (length == 2).
Parameters
nStateIdState id to be pushed.

Definition at line 265 of file StateMach.cxx.

References m_bIsRecording, m_stackStateIds, m_uMaxRecording, and NO_LIMIT.

Referenced by run().

266 {
267  size_t n;
268 
269  if( m_bIsRecording )
270  {
271  if( (n = m_stackStateIds.size()) == 0 )
272  {
273  m_stackStateIds.push_back(nStateId);
274  }
275  else if( (m_uMaxRecording != NO_LIMIT) && (n >= m_uMaxRecording) )
276  {
277  m_stackStateIds.erase(m_stackStateIds.begin());
278  m_stackStateIds.push_back(nStateId);
279  }
280  else if( m_stackStateIds[n-1] != nStateId )
281  {
282  m_stackStateIds.push_back(nStateId);
283  }
284  }
285 }
std::vector< int > m_stackStateIds
stack of previous state ids
Definition: StateMach.h:285
bool m_bIsRecording
is [not] recording work flow
Definition: StateMach.h:287
static const size_t NO_LIMIT
no limit on length of recording
Definition: StateMach.h:88
size_t m_uMaxRecording
max recording length
Definition: StateMach.h:286
virtual void rnr::StateMach::resumeRecording ( )
inlinevirtual

Resume recording of states ids.

The recording is not erased.

Definition at line 202 of file StateMach.h.

References m_bIsRecording.

203  {
204  m_bIsRecording = true;
205  }
bool m_bIsRecording
is [not] recording work flow
Definition: StateMach.h:287
void StateMach::run ( )
virtual

Run the state machine from the start.

This function does not return until the terminate state is reached.

Definition at line 192 of file StateMach.cxx.

References rnr::State::actionEnterState(), rnr::State::actionExitState(), rnr::State::dispatchEvent(), LOGTRANSITION, m_mapStateTbl, m_nCurrStateId, m_nMarkStateId, m_nStartStateId, m_nStateMachId, m_strStateMachName, popStateId(), pushStateId(), rnr::State::receiveEvent(), rnr::State::StateIdPrev, rnr::State::StateIdTerminate, and rnr::State::StateIdThis.

Referenced by setStartStateId().

193 {
194  StateTblMap_T::iterator pos;
195  State *pState;
196  int nEventId;
197  int nNextStateId;
198 
201 
202  // run from the start
204  {
205  //
206  // Found the state in state machine. (Block) receive event and dispatch.
207  //
208  if( (pos = m_mapStateTbl.find(m_nCurrStateId)) != m_mapStateTbl.end() )
209  {
210  pState = pos->second;
211 
212  // entering this state, execute any 'enter state' action
214  {
215  pState->actionEnterState(m_nMarkStateId, nEventId);
216  }
217 
218  // (block) receive event
219  nEventId = pState->receiveEvent();
220 
221  // dispatch event
222  nNextStateId = pState->dispatchEvent(m_nMarkStateId, nEventId);
223 
224  // this state
225  if( nNextStateId == State::StateIdThis )
226  {
227  nNextStateId = m_nCurrStateId;
228  }
229 
230  // previous state
231  else if( nNextStateId == State::StateIdPrev )
232  {
233  nNextStateId = popStateId();
234  }
235 
236  // exiting this state, execute any 'exit state' action
237  if( m_nCurrStateId != nNextStateId )
238  {
239  pState->actionExitState(nNextStateId, nEventId);
240  }
241 
242  // log
243  LOGTRANSITION(m_nCurrStateId, nEventId, nNextStateId);
244 
246  m_nCurrStateId = nNextStateId;
247 
248  // record state (if enabled)
250  }
251 
252  //
253  // Badly formed state machine. No state associated with state id. Terminate.
254  //
255  else
256  {
257  LOGERROR("%s.%d: No state found in state table with state id=%d.",
261  }
262  }
263 }
std::string m_strStateMachName
state machine name
Definition: StateMach.h:280
int m_nMarkStateId
mark state id of last run cycle
Definition: StateMach.h:284
void pushStateId(int nStateid)
Push state id onto stack of state ids.
Definition: StateMach.cxx:265
virtual void actionEnterState(int nPrevStateId, int nEventId)
Execute &#39;enter state&#39; action.
Definition: State.h:305
virtual int receiveEvent()
Receive next event.
Definition: State.cxx:204
int m_nCurrStateId
current state id
Definition: StateMach.h:283
virtual int dispatchEvent(int nPrevStateId, int nEventId)
Dispatch received event by executing associated action and transitioning to the next state...
Definition: State.cxx:225
int m_nStartStateId
starting state id
Definition: StateMach.h:282
static const int StateIdTerminate
terminate state
Definition: State.h:170
int m_nStateMachId
state machine id
Definition: StateMach.h:279
StateTblMap_T m_mapStateTbl
state table
Definition: StateMach.h:281
static const int StateIdThis
the current (this) state
Definition: State.h:169
#define LOGTRANSITION(nCurrStateId, nEventId, nNextStateId)
Log state transition at diagnostic level 3.
Definition: StateMach.cxx:78
virtual void actionExitState(int nNextStateId, int nEventId)
Execute &#39;exit state&#39; action.
Definition: State.h:315
int popStateId()
Pop state id from stack of state ids.
Definition: StateMach.cxx:287
static const int StateIdPrev
the previous state
Definition: State.h:168
void rnr::StateMach::setStartStateId ( int  nStartStateId)
inline

Set state machine's start state id.

Parameters
nStartStateIdState id.

Definition at line 158 of file StateMach.h.

References m_nStartStateId, and run().

159  {
160  m_nStartStateId = nStartStateId;
161  }
int m_nStartStateId
starting state id
Definition: StateMach.h:282
virtual void rnr::StateMach::startRecording ( size_t  uLimit = NO_LIMIT)
inlinevirtual

Start recording states ids.

Any previous recording is erased.

Typical uses for recording states are work flows, in which the previous states may need backtracing, given a previous event.

Parameters
uLimitLimit the length of the recording.

Definition at line 180 of file StateMach.h.

References m_bIsRecording, m_stackStateIds, and m_uMaxRecording.

181  {
182  m_stackStateIds.clear();
183  m_uMaxRecording = uLimit;
184  m_bIsRecording = true;
185  }
std::vector< int > m_stackStateIds
stack of previous state ids
Definition: StateMach.h:285
bool m_bIsRecording
is [not] recording work flow
Definition: StateMach.h:287
size_t m_uMaxRecording
max recording length
Definition: StateMach.h:286
virtual void rnr::StateMach::stopRecording ( )
inlinevirtual

Stop recording of states ids.

The recording is not erased.

Definition at line 192 of file StateMach.h.

References m_bIsRecording.

193  {
194  m_bIsRecording = false;
195  }
bool m_bIsRecording
is [not] recording work flow
Definition: StateMach.h:287

The documentation for this class was generated from the following files: