source: trunk/FACT++/src/StateMachineAsio.h@ 17689

Last change on this file since 17689 was 16770, checked in by tbretz, 11 years ago
We don't want to dispatch the event (blokcing) but to post the event (non-blocking).
File size: 2.7 KB
Line 
1#ifndef FACT_StateMachineAsio
2#define FACT_StateMachineAsio
3
4#include <boost/asio.hpp>
5#include <boost/bind.hpp>
6
7template <class T>
8class 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 (!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 (!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
74public:
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
Note: See TracBrowser for help on using the repository browser.