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

Last change on this file since 16732 was 16728, checked in by tbretz, 12 years ago
Gets the CPU consumption to basically 0 by a more intelligent event management.
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(T::Execute(), 0, "by Trigger"))
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 dispatch(boost::bind(&StateMachineAsio::Handler, this));
37 }
38
39 int Run(bool)
40 {
41 fTrigger.expires_from_now(boost::posix_time::microseconds(0));
42 fTrigger.async_wait(boost::bind(&StateMachineAsio::HandleTrigger,
43 this, boost::asio::placeholders::error));
44
45 T::SetCurrentState(StateMachineImp::kSM_Ready, "by Run()");
46
47 T::fRunning = true;
48
49 while (1)
50 {
51 if (run_one()==0)
52 break;
53
54 if (!HandleNewState(T::Execute(), 0, "by Trigger"))
55 Stop(-1);
56 }
57 reset();
58
59 T::fRunning = false;
60
61 if (T::fExitRequested==-1)
62 {
63 T::Fatal("Fatal Error occured... shutting down.");
64 return -1;
65 }
66
67 T::SetCurrentState(StateMachineImp::kSM_NotReady, "due to return from Run().");
68
69 const int exitcode = T::fExitRequested-1;
70 T::fExitRequested = 0;
71 return exitcode;
72 }
73
74
75public:
76 StateMachineAsio(std::ostream &out, const std::string &server) :
77 T(out, server), boost::asio::io_service::work(static_cast<boost::asio::io_service&>(*this)),
78 fTrigger(static_cast<boost::asio::io_service&>(*this))
79 {
80 // ba::io_service::work is a kind of keep_alive for the loop.
81 // It prevents the io_service to go to stopped state, which
82 // would prevent any consecutive calls to run()
83 // or poll() to do nothing. reset() could also revoke to the
84 // previous state but this might introduce some overhead of
85 // deletion and creation of threads and more.
86 }
87
88 void Stop(int code=0)
89 {
90 T::Stop(code);
91 stop();
92 }
93};
94
95#endif
Note: See TracBrowser for help on using the repository browser.