FACT++  1.0
int StateMachineImp::Run ( bool  dummy)
virtual

Start the mainloop.

This is the main loop, or what could be called the running state machine. The flow diagram below shows what the loop is actually doing. It's main purpose is to serialize command excecution and the main loop in the state machine (e.g. the tracking loop)

Leaving the loop can be forced by setting fExitRequested to another value than zero. This is done automatically if dim's EXIT command is received or can be forced by calling Stop().

As long as no new command arrives the Execute() command is called continously. This should implement the current action which should be performed in the current state, e.g. calculating a new command value and sending it to the hardware.

If a command is received it is put into the fifo by the commandHandler(). The main loop now checks the fifo. If commands are in the fifo, it is checked whether the command is valid ithin this state or not. If it is not valid it is ignored. If it is valid the corresponding action is performed. This can either be a call to Configure() (when no state change is connected to the command) or Transition() (if the command involves a state change). In both cases areference to the received command (Command) is passed to the function. Note that after the functions have finished the command will go out of scope and be deleted.

None of the commands should take to long for execution. Otherwise the response time of the main loop will become too slow.

Any of the three commands should usually return the current state or (in case of the Transition() command) return the new state. However, all three command can issue a state change by returning a new state. However, this will just change the internal state. Any action which is connected with the state change must have been executed already.

dot_inline_dotgraph_4.png
Parameters
dummyIf this parameter is set to treu then no action is executed and now events are dispatched from the event list. It is usefull if functions are assigned directly to any event to simulate a running loop (e.g. block until Stop() was called or fExitRequested was set by an EXIT command. If dummy==true, fRunning is not set to true to allow handling events directly from the event handler.
Returns
In the case of a a fatal error -1 is returned, fExitRequested-1 in all other cases (This corresponds to the exit code either received by the EXIT event or given to the Stop() function)
Todo:
Fix docu (kSM_SetReady, HandleEvent)

Implements MainImp.

Examples:
chatserv.cc.

Definition at line 994 of file StateMachineImp.cc.

References MessageImp::Error(), Execute(), MessageImp::Fatal(), fCond, fCurrentState, fExitRequested, fMutex, fRunning, HandleEvent(), HandleNewState(), IsQueueEmpty(), kSM_NotReady, kSM_Ready, PopEvent(), and SetCurrentState().

Referenced by main(), and RunThread().

995 {
997  {
998  Error("Run() can only be called in the NotReady state.");
999  return -1;
1000  }
1001 
1002  if (!fExitRequested)
1003  {
1004  fRunning = !dummy;
1005 
1006  SetCurrentState(kSM_Ready, "by Run()");
1007 
1008  std::unique_lock<std::mutex> lock(fMutex);
1009  fMutex.unlock();
1010 
1011  while (1)
1012  {
1013  fMutex.lock();
1014  if (IsQueueEmpty())
1015  fCond.wait_for(lock, chrono::microseconds(10000));
1016  fMutex.unlock();
1017 
1018  if (fExitRequested)
1019  break;
1020 
1021  if (dummy)
1022  continue;
1023 
1024  // If the command stack is empty go on with processing in the
1025  // current state
1026  if (!IsQueueEmpty())
1027  {
1028  // Pop the next command which arrived from the stack
1029  const shared_ptr<Event> cmd(PopEvent());
1030  if (!HandleEvent(*cmd))
1031  break;
1032  }
1033 
1034  // Execute a step in the current state of the state machine
1035  if (!HandleNewState(Execute(), 0, "by Execute-command"))
1036  break;
1037  }
1038 
1039  fRunning = false;
1040 
1041  if (!fExitRequested)
1042  {
1043  Fatal("Fatal Error occured... shutting down.");
1044  return -1;
1045  }
1046 
1047  SetCurrentState(kSM_NotReady, "due to return from Run().");
1048  }
1049 
1050  const int exitcode = fExitRequested-1;
1051 
1052  // Prepare for next call
1053  fExitRequested = 0;
1054 
1055  return exitcode;
1056 }
int fCurrentState
Name of the state-machine / server (e.g. DRIVE)
int fExitRequested
Machine is in main-loop.
Mainloop running, state machine in operation.
bool HandleEvent(const EventImp &evt)
bool HandleNewState(int newstate, const EventImp *evt, const char *txt)
bool fRunning
Flag if events should be buffered outside the event loop.
int Error(const std::string &str)
Definition: MessageImp.h:49
Mainloop not running, state machine stopped.
virtual std::string SetCurrentState(int state, const char *txt="", const std::string &cmd="")
int Fatal(const std::string &str)
Definition: MessageImp.h:51
bool IsQueueEmpty() const
std::condition_variable fCond
Mutex to ensure thread-safe access to the command fifo.
std::shared_ptr< Event > PopEvent()
Pop a command from the fifo.
virtual int Execute()
Is called continously to execute actions in the current state.
std::mutex fMutex
Event queue (fifo) for the received commands.

+ Here is the call graph for this function:

+ Here is the caller graph for this function: