FACT++  1.0
StateMachineAsio.h
Go to the documentation of this file.
1 #ifndef FACT_StateMachineAsio
2 #define FACT_StateMachineAsio
3 
4 #include <boost/asio.hpp>
5 #include <boost/bind.hpp>
6 
7 template <class T>
8 class StateMachineAsio : public T, public boost::asio::io_service, public boost::asio::io_service::work
9 {
10  boost::asio::deadline_timer fTrigger;
11 
12  void HandleTrigger(const boost::system::error_code &error)
13  {
14  // 125: Operation canceled (bs::error_code(125, bs::system_category))
15  if (error && error!=boost::asio::error::basic_errors::operation_aborted)
16  return;
17 
18  fTrigger.expires_from_now(boost::posix_time::microseconds(10000));
19  fTrigger.async_wait(boost::bind(&StateMachineAsio::HandleTrigger,
20  this, boost::asio::placeholders::error));
21 
22  if (!T::HandleNewState(Execute(), 0, "by HandleTrigger()"))
23  Stop(-1);
24  }
25 
26  void Handler()
27  {
28  const auto ptr = T::PopEvent();
29  if (!T::HandleEvent(*ptr))
30  Stop(-1);
31  }
32 
33  void PushEvent(Event *cmd)
34  {
35  T::PushEvent(cmd);
36  post(boost::bind(&StateMachineAsio::Handler, this));
37  }
38 
39  int Execute()=0;
40 
41  int Run(bool)
42  {
43  fTrigger.expires_from_now(boost::posix_time::microseconds(0));
44  fTrigger.async_wait(boost::bind(&StateMachineAsio::HandleTrigger,
45  this, boost::asio::placeholders::error));
46 
47  T::SetCurrentState(StateMachineImp::kSM_Ready, "by Run()");
48 
49  T::fRunning = true;
50 
51  while (run_one())
52  {
53  if (!T::HandleNewState(Execute(), 0, "by Run()"))
54  Stop(-1);
55  }
56  reset();
57 
58  T::fRunning = false;
59 
60  if (T::fExitRequested==-1)
61  {
62  T::Fatal("Fatal Error occured... shutting down.");
63  return -1;
64  }
65 
66  T::SetCurrentState(StateMachineImp::kSM_NotReady, "due to return from Run().");
67 
68  const int exitcode = T::fExitRequested-1;
69  T::fExitRequested = 0;
70  return exitcode;
71  }
72 
73 
74 public:
75  StateMachineAsio(std::ostream &out, const std::string &server) :
76  T(out, server), boost::asio::io_service::work(static_cast<boost::asio::io_service&>(*this)),
77  fTrigger(static_cast<boost::asio::io_service&>(*this))
78  {
79  // ba::io_service::work is a kind of keep_alive for the loop.
80  // It prevents the io_service to go to stopped state, which
81  // would prevent any consecutive calls to run()
82  // or poll() to do nothing. reset() could also revoke to the
83  // previous state but this might introduce some overhead of
84  // deletion and creation of threads and more.
85  }
86 
87  void Stop(int code=0)
88  {
89  T::Stop(code);
90  stop();
91  }
92 };
93 
94 #endif
Mainloop running, state machine in operation.
boost::asio::deadline_timer fTrigger
void HandleTrigger(const boost::system::error_code &error)
Mainloop not running, state machine stopped.
StateMachineAsio(std::ostream &out, const std::string &server)
Concerete implementation of an EventImp stroring name, format, data and time.
Definition: Event.h:6
void PushEvent(Event *cmd)
void Stop(int code=0)
void reset(S &s)
Definition: ByteOrder.h:13