FACT++  1.0
StateMachineImp.h
Go to the documentation of this file.
1 #ifndef FACT_StateMachineImp
2 #define FACT_StateMachineImp
3 
4 #include <map>
5 #include <list>
6 #include <mutex>
7 #include <vector>
8 #include <memory>
9 #include <condition_variable>
10 
11 #include "MainImp.h"
12 #include "MessageImp.h"
13 
14 class Event;
15 class EventImp;
16 
17 class StateMachineImp : public MainImp, public MessageImp
18 {
19 public:
24  {
25  kSM_KeepState = -42,
27  kSM_NotReady = -1,
28  kSM_Ready = 0,
30  kSM_Error = 0x100,
31  kSM_FatalError = 0xffff,
32  };
33 
34 private:
35  std::string fName;
36 
38 
39  typedef std::map<const int, std::pair<std::string, std::string>> StateNames;
40 
41 protected:
43  StateNames fStateNames;
44 
45 private:
46  std::vector<EventImp*> fListOfEvents;
47  std::list<std::shared_ptr<Event>> fEventQueue;
48 
49  std::mutex fMutex;
50  std::mutex fMutexEvt;
51 
52  std::condition_variable fCond;
53 
55 
56 protected:
57  bool fRunning;
59 
61  virtual void PushEvent(Event *cmd);
63  std::shared_ptr<Event> PopEvent();
64 
65  bool HandleNewState(int newstate, const EventImp *evt, const char *txt);
66 
67 protected:
69  virtual int Execute() { return fCurrentState; }
71  //virtual int Configure(const Event &) { return kSM_FatalError; }
73  //virtual int Transition(const Event &) { return kSM_FatalError; }
74 
75 private:
76  virtual EventImp *CreateEvent(const std::string &name, const std::string &fmt) = 0;
77  virtual EventImp *CreateService(const std::string &);
78 
79  virtual void Lock() { }
80  virtual void UnLock() { }
81 
82  int Wrapper(const std::function<int(const EventImp &)> &f, const EventImp &imp)
83  {
84  const int rc = f(imp);
85  return rc==kSM_KeepState ? GetCurrentState() : rc;
86  }
87 
88 protected:
89 
90  bool HandleEvent(const EventImp &evt);
91 
94  virtual std::string SetCurrentState(int state, const char *txt="", const std::string &cmd="");
95 
96  EventImp &AddEvent(const std::string &name, const std::string &states, const std::string &fmt);
97  EventImp &AddEvent(const std::string &name, int s1=-1, int s2=-1, int s3=-1, int s4=-1, int s5=-1);
98  EventImp &AddEvent(const std::string &name, const std::string &fmt, int s1=-1, int s2=-1, int s3=-1, int s4=-1, int s5=-1);
99 
100  virtual bool AddStateName(const int state, const std::string &name, const std::string &doc="");
101 
102  void SetDefaultStateNames();
103 
104 public:
105  StateMachineImp(std::ostream &out=std::cout, const std::string &name="");
107 
108  std::function<int(const EventImp &)> Wrap(const std::function<int(const EventImp &)> &func)
109  {
110  return bind(&StateMachineImp::Wrapper, this, func, std::placeholders::_1);
111  }
112 
113  const std::string &GetName() const { return fName; }
114 
115  EventImp &Subscribe(const std::string &name);
116  void Unsubscribe(EventImp *evt);
117 
119  int GetCurrentState() const { return fCurrentState; }
120 
121  void SetReady() { SetCurrentState(kSM_Ready, "set manually"); }
122  void SetNotReady() { SetCurrentState(kSM_NotReady, "set manually"); }
123 
125  virtual int Run(bool dummy);
126  int Run() { return Run(false); }
127 
129  virtual void Stop(int code=0);
130 
132  bool IsRunning() const { return fRunning; }
133 
135  void EnableBuffer(bool b=true) { fBufferEvents=b; }
136 
138  bool PostEvent(std::ostream &lout, const std::string &str);
139  bool PostEvent(const std::string &evt) { return PostEvent(std::cout, evt); }
140  bool PostEvent(const EventImp &evt);
141  bool PostEvent(const EventImp &evt, const char *ptr, size_t siz);
142 
143  // Event handling
144  bool HasEvent(const EventImp *cmd);
145  EventImp *FindEvent(const std::string &evt);
146 
147  bool IsQueueEmpty() const { return fEventQueue.empty(); }
148 
149  //const std::vector<EventImp*> &GetListOfEvents() const { return fListOfEvents; }
150  const std::vector<std::string> GetEventNames();
151 
152  void PrintListOfEvents(std::ostream &out, const std::string &evt="");
153  void PrintListOfEvents(const std::string &str="");
154 
155  void PrintListOfAllowedEvents(std::ostream &out);
157 
158  void PrintListOfStates(std::ostream &out) const;
159  void PrintListOfStates() const;
160 
161 
162  int GetStateIndex(const std::string &name) const;
163  bool HasState(int index) const;
164 
165  const std::string GetStateName(int state) const;
166  const std::string GetStateName() const { return GetStateName(fCurrentState); }
167 
168  const std::string GetStateDesc(int state) const;
169  const std::string GetStateDesc() const { return GetStateDesc(fCurrentState); }
170 
171  const std::string GetStateDescription(int state) const;
172  const std::string GetStateDescription() const { return GetStateDescription(fCurrentState); }
173 };
174 
175 #endif
176 
177 // ***************************************************************************
197 // ***************************************************************************
227 // ***************************************************************************
259 // ***************************************************************************
int GetStateIndex(const std::string &name) const
int fCurrentState
Name of the state-machine / server (e.g. DRIVE)
void PrintListOfAllowedEvents()
EventImp & AddEvent(const std::string &name, const std::string &states, const std::string &fmt)
int fExitRequested
Machine is in main-loop.
void EnableBuffer(bool b=true)
Used to enable or disable buffering of events outside of the main loop.
virtual void Stop(int code=0)
Request to stop the mainloop.
Mainloop running, state machine in operation.
int GetCurrentState() const
return the current state of the machine
A general base-class describing events issues in a state machine.
Definition: EventImp.h:11
void PrintListOfStates() const
Print a list of all states with descriptions.
Base class for a state machine implementation.
std::list< std::shared_ptr< Event > > fEventQueue
List of available commands as setup by user.
bool PostEvent(std::ostream &lout, const std::string &str)
Post an event to the event queue.
The base implementation of a distributed messaging system.
Definition: MessageImp.h:10
const std::string & GetName() const
Fatal error: stop program.
char str[80]
Definition: test_client.c:7
Definition: MainImp.h:4
bool HandleEvent(const EventImp &evt)
EventImp * FindEvent(const std::string &evt)
virtual void UnLock()
bool HandleNewState(int newstate, const EventImp *evt, const char *txt)
bool HasEvent(const EventImp *cmd)
bool fRunning
Flag if events should be buffered outside the event loop.
const std::string GetStateDesc() const
First user defined mode (to be used in derived classes&#39; enums)
virtual EventImp * CreateEvent(const std::string &name, const std::string &fmt)=0
Is called when a configuration event is to be processed (no transition of state)
Mainloop not running, state machine stopped.
bool HasState(int index) const
int Wrapper(const std::function< int(const EventImp &)> &f, const EventImp &imp)
bool PostEvent(const std::string &evt)
Warning states
Definition: smartfact.txt:92
std::vector< EventImp * > fListOfEvents
const std::vector< std::string > GetEventNames()
EventImp & Subscribe(const std::string &name)
std::map< const int, std::pair< std::string, std::string > > StateNames
Current state of the state machine.
virtual void PushEvent(Event *cmd)
This is a flag which is set true if the main loop should stop.
const std::string GetStateDescription() const
StateNames fStateNames
Human readable names associated with the states.
Concerete implementation of an EventImp stroring name, format, data and time.
Definition: Event.h:6
virtual std::string SetCurrentState(int state, const char *txt="", const std::string &cmd="")
void PrintListOfEvents(std::ostream &out, const std::string &evt="")
Error states should be between 0x100 and 0xffff.
Possible return value for GetStateIndex.
virtual void Lock()
void Unsubscribe(EventImp *evt)
bool IsQueueEmpty() const
std::string fName
virtual bool AddStateName(const int state, const std::string &name, const std::string &doc="")
std::condition_variable fCond
Mutex to ensure thread-safe access to the command fifo.
const std::string GetStateName() const
std::mutex fMutexEvt
Mutex to ensure thread-safe access to the command fifo.
std::shared_ptr< Event > PopEvent()
Pop a command from the fifo.
bool IsRunning() const
Used to check if the main loop is already running or still running.
bool fBufferEvents
Conditional to signal run the an event is waiting.
virtual int Execute()
Is called continously to execute actions in the current state.
~StateMachineImp()
delete all object stored in fListOfEvent and in fEventQueue
StateMachineImp(std::ostream &out=std::cout, const std::string &name="")
virtual EventImp * CreateService(const std::string &)
std::mutex fMutex
Event queue (fifo) for the received commands.
std::function< int(const EventImp &)> Wrap(const std::function< int(const EventImp &)> &func)