CppServer  1.0.4.0
C++ Server Library
timer.cpp
Go to the documentation of this file.
1 
9 #include "server/asio/timer.h"
10 
11 namespace CppServer {
12 namespace Asio {
13 
14 Timer::Timer(const std::shared_ptr<Service>& service)
15  : _service(service),
16  _io_service(_service->GetAsioService()),
17  _strand(*_io_service),
18  _strand_required(_service->IsStrandRequired()),
19  _timer(*_io_service)
20 {
21  assert((service != nullptr) && "Asio service is invalid!");
22  if (service == nullptr)
23  throw CppCommon::ArgumentException("Asio service is invalid!");
24 }
25 
26 Timer::Timer(const std::shared_ptr<Service>& service, const CppCommon::UtcTime& time)
27  : _service(service),
28  _io_service(_service->GetAsioService()),
29  _strand(*_io_service),
30  _strand_required(_service->IsStrandRequired()),
31  _timer(*_io_service, time.chrono())
32 {
33  assert((service != nullptr) && "Asio service is invalid!");
34  if (service == nullptr)
35  throw CppCommon::ArgumentException("Asio service is invalid!");
36 }
37 
38 Timer::Timer(const std::shared_ptr<Service>& service, const CppCommon::Timespan& timespan)
39  : _service(service),
40  _io_service(_service->GetAsioService()),
41  _strand(*_io_service),
42  _strand_required(_service->IsStrandRequired()),
43  _timer(*_io_service, timespan.chrono())
44 {
45  assert((service != nullptr) && "Asio service is invalid!");
46  if (service == nullptr)
47  throw CppCommon::ArgumentException("Asio service is invalid!");
48 }
49 
50 Timer::Timer(const std::shared_ptr<Service>& service, const std::function<void(bool)>& action)
51  : _service(service),
52  _io_service(_service->GetAsioService()),
53  _strand(*_io_service),
54  _strand_required(_service->IsStrandRequired()),
55  _timer(*_io_service),
56  _action(action)
57 {
58  assert((service != nullptr) && "Asio service is invalid!");
59  if (service == nullptr)
60  throw CppCommon::ArgumentException("Asio service is invalid!");
61  assert((action) && "Action function is invalid!");
62  if (!action)
63  throw CppCommon::ArgumentException("Action function is invalid!");
64 }
65 
66 Timer::Timer(const std::shared_ptr<Service>& service, const std::function<void(bool)>& action, const CppCommon::UtcTime& time)
67  : _service(service),
68  _io_service(_service->GetAsioService()),
69  _strand(*_io_service),
70  _strand_required(_service->IsStrandRequired()),
71  _timer(*_io_service, time.chrono()),
72  _action(action)
73 {
74  assert((service != nullptr) && "Asio service is invalid!");
75  if (service == nullptr)
76  throw CppCommon::ArgumentException("Asio service is invalid!");
77  assert((action) && "Action function is invalid!");
78  if (!action)
79  throw CppCommon::ArgumentException("Action function is invalid!");
80 }
81 
82 Timer::Timer(const std::shared_ptr<Service>& service, const std::function<void(bool)>& action, const CppCommon::Timespan& timespan)
83  : _service(service),
84  _io_service(_service->GetAsioService()),
85  _strand(*_io_service),
86  _strand_required(_service->IsStrandRequired()),
87  _timer(*_io_service, timespan.chrono()),
88  _action(action)
89 {
90  assert((service != nullptr) && "Asio service is invalid!");
91  if (service == nullptr)
92  throw CppCommon::ArgumentException("Asio service is invalid!");
93  assert((action) && "Action function is invalid!");
94  if (!action)
95  throw CppCommon::ArgumentException("Action function is invalid!");
96 }
97 
98 CppCommon::UtcTime Timer::expire_time() const
99 {
100  return CppCommon::UtcTime(_timer.expires_at());
101 }
102 
103 CppCommon::Timespan Timer::expire_timespan() const
104 {
105  return CppCommon::Timespan(_timer.expires_from_now());
106 }
107 
108 bool Timer::Setup(const CppCommon::UtcTime& time)
109 {
110  asio::error_code ec;
111  _timer.expires_at(time.chrono(), ec);
112 
113  // Check for error
114  if (ec)
115  {
116  SendError(ec);
117  return false;
118  }
119 
120  return true;
121 }
122 
123 bool Timer::Setup(const CppCommon::Timespan& timespan)
124 {
125  asio::error_code ec;
126  _timer.expires_from_now(timespan.chrono(), ec);
127 
128  // Check for error
129  if (ec)
130  {
131  SendError(ec);
132  return false;
133  }
134 
135  return true;
136 }
137 
138 bool Timer::Setup(const std::function<void(bool)>& action)
139 {
140  assert((action) && "Action function is invalid!");
141  if (!action)
142  return false;
143 
144  _action = action;
145  return true;
146 }
147 
148 bool Timer::Setup(const std::function<void(bool)>& action, const CppCommon::UtcTime& time)
149 {
150  assert((action) && "Action function is invalid!");
151  if (!action)
152  return false;
153 
154  _action = action;
155  return Setup(time);
156 }
157 
158 bool Timer::Setup(const std::function<void(bool)>& action, const CppCommon::Timespan& timespan)
159 {
160  assert((action) && "Action function is invalid!");
161  if (!action)
162  return false;
163 
164  _action = action;
165  return Setup(timespan);
166 }
167 
169 {
170  auto self(this->shared_from_this());
171  auto async_wait_handler = [this, self](const std::error_code& ec)
172  {
173  // Call the timer aborted handler
174  if (ec == asio::error::operation_aborted)
175  SendTimer(true);
176 
177  // Check for error
178  if (ec)
179  {
180  SendError(ec);
181  return;
182  }
183 
184  // Call the timer expired handler
185  SendTimer(false);
186  };
187  if (_strand_required)
188  _timer.async_wait(bind_executor(_strand, async_wait_handler));
189  else
190  _timer.async_wait(async_wait_handler);
191 
192  return true;
193 }
194 
196 {
197  asio::error_code ec;
198  _timer.wait(ec);
199 
200  // Call the timer aborted handler
201  if (ec == asio::error::operation_aborted)
202  SendTimer(true);
203 
204  // Check for error
205  if (ec)
206  {
207  SendError(ec);
208  return false;
209  }
210 
211  // Call the timer expired handler
212  SendTimer(false);
213 
214  return true;
215 }
216 
218 {
219  asio::error_code ec;
220  _timer.cancel(ec);
221 
222  // Check for error
223  if (ec)
224  {
225  SendError(ec);
226  return false;
227  }
228 
229  return true;
230 }
231 
232 void Timer::SendError(std::error_code ec)
233 {
234  // Skip Asio abort error
235  if (ec == asio::error::operation_aborted)
236  return;
237 
238  onError(ec.value(), ec.category().name(), ec.message());
239 }
240 
241 void Timer::SendTimer(bool canceled)
242 {
243  // Call the timer handler
244  onTimer(canceled);
245 
246  // Call the timer action
247  if (_action)
248  _action(canceled);
249 }
250 
251 } // namespace Asio
252 } // namespace CppServer
virtual bool Cancel()
Cancel any wait operation on the timer.
Definition: timer.cpp:217
std::shared_ptr< Service > & service() noexcept
Get the Asio service.
Definition: timer.h:77
virtual bool WaitSync()
Wait for the timer (synchronous)
Definition: timer.cpp:195
CppCommon::UtcTime expire_time() const
Get the timer's expiry time as an absolute time.
Definition: timer.cpp:98
Timer(const std::shared_ptr< Service > &service)
Initialize timer with a given Asio service.
Definition: timer.cpp:14
virtual void onTimer(bool canceled)
Handle timer notification.
Definition: timer.h:140
CppCommon::Timespan expire_timespan() const
Get the timer's expiry time relative to now.
Definition: timer.cpp:103
virtual bool Setup(const CppCommon::UtcTime &time)
Setup the timer with absolute expiry time.
Definition: timer.cpp:108
virtual bool WaitAsync()
Wait for the timer (asynchronous)
Definition: timer.cpp:168
virtual void onError(int error, const std::string &category, const std::string &message)
Handle error notification.
Definition: timer.h:148
C++ Server project definitions.
Definition: asio.h:56
Timer definition.