fw4spl
WorkerAsio.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2017.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwThread/Timer.hpp"
8 #include "fwThread/Worker.hpp"
9 
10 #include <fwCore/TimeStamp.hpp>
11 
12 #include <boost/asio/deadline_timer.hpp>
13 #include <boost/asio/io_service.hpp>
14 
15 namespace fwThread
16 {
17 
18 //------------------------------------------------------------------------------
19 
20 std::size_t WorkerThread( ::boost::asio::io_service& io_service )
21 {
22  OSLM_TRACE("Thread " << getCurrentThreadId() <<" Start");
23  std::size_t res = io_service.run();
24  OSLM_TRACE("Thread " << getCurrentThreadId() <<" Finish");
25  return res;
26 }
27 
32 {
33 public:
34  typedef ::boost::asio::io_service IOServiceType;
35  typedef ::boost::asio::io_service::work WorkType;
36  typedef std::shared_ptr< WorkType > WorkPtrType;
37  typedef std::thread ThreadType;
38 
39  WorkerAsio();
40 
41  virtual ~WorkerAsio();
42 
43  void stop();
44 
45  void post(TaskType handler);
46 
47  ThreadIdType getThreadId() const;
48 
50 
51  virtual void processTasks();
52 
53  virtual void processTasks(PeriodType maxtime);
54 
55 protected:
56 
58  WorkerAsio( const WorkerAsio& );
59 
61  WorkerAsio& operator=( const WorkerAsio& );
62 
64  IOServiceType m_ioService;
65 
67  WorkPtrType m_work;
68 
70  SPTR(ThreadType) m_thread;
71 };
72 
73 //------------------------------------------------------------------------------
74 
78 class TimerAsio : public ::fwThread::Timer
79 {
80 public:
84  TimerAsio(::boost::asio::io_service& ioSrv);
85 
86  ~TimerAsio();
87 
89  void start();
90 
92  void stop();
93 
95  void setDuration(TimeDurationType duration);
96 
98  bool isOneShot() const
99  {
100  ::fwCore::mt::ScopedLock lock(m_mutex);
101  return m_oneShot;
102  }
103 
105  void setOneShot(bool oneShot)
106  {
107  ::fwCore::mt::ScopedLock lock(m_mutex);
108  m_oneShot = oneShot;
109  }
110 
112  bool isRunning() const
113  {
114  ::fwCore::mt::ScopedLock lock(m_mutex);
115  return m_running;
116  }
117 
118 protected:
119 
120  void cancelNoLock();
121  void rearmNoLock(TimeDurationType duration);
122 
123  void call(const ::boost::system::error_code& code);
124 
126  TimerAsio( const TimerAsio& );
127 
129  TimerAsio& operator=( const TimerAsio& );
130 
132  ::boost::asio::deadline_timer m_timer;
133 
135  TimeDurationType m_duration;
136 
138  bool m_oneShot;
139 
141  bool m_running;
142 };
143 
144 //------------------------------------------------------------------------------
145 
146 // ---------- WorkerAsio private implementation ----------
147 
148 WorkerAsio::WorkerAsio() :
149  m_ioService(),
150  m_work( std::make_shared< WorkType >(std::ref(m_ioService)) )
151 {
152  std::packaged_task< ::fwThread::Worker::ExitReturnType() > task( std::bind(&WorkerThread, std::ref(m_ioService)) );
153  std::future< ::fwThread::Worker::ExitReturnType > ufuture = task.get_future();
154 
155  m_thread = std::make_shared< ThreadType >( std::move( task ) );
156 
157  m_future = std::move(ufuture);
158 }
159 
160 WorkerAsio::~WorkerAsio()
161 {
162  if(!m_ioService.stopped())
163  {
164  this->stop();
165  }
166 }
167 
168 //------------------------------------------------------------------------------
169 
171 {
172  m_work.reset();
173  m_thread->join();
174 }
175 
176 SPTR(::fwThread::Timer) WorkerAsio::createTimer()
177 {
178  return std::make_shared< TimerAsio >(std::ref(m_ioService));
179 }
180 
181 //------------------------------------------------------------------------------
182 
183 void WorkerAsio::post(TaskType handler)
184 {
185  m_ioService.post(handler);
186 }
187 
188 //------------------------------------------------------------------------------
189 
190 ThreadIdType WorkerAsio::getThreadId() const
191 {
192  return m_thread->get_id();
193 }
194 
195 //------------------------------------------------------------------------------
196 
198 {
199  m_ioService.poll();
200 }
201 
202 //------------------------------------------------------------------------------
203 
204 void WorkerAsio::processTasks(PeriodType maxtime)
205 {
206  ::fwCore::TimeStamp timeStamp;
207  timeStamp.setLifePeriod(maxtime);
208  timeStamp.modified();
209  while(timeStamp.periodExpired())
210  {
211  m_ioService.poll_one();
212  }
213 }
214 
215 // ---------- Worker ----------
216 SPTR(Worker) Worker::defaultFactory()
217 {
218  return std::make_shared< WorkerAsio >();
219 }
220 
221 // ---------- Timer private implementation ----------
222 
223 TimerAsio::TimerAsio(::boost::asio::io_service& ioSrv) :
224  m_timer(ioSrv),
225  m_duration(std::chrono::seconds(1)),
226  m_oneShot(false),
227  m_running(false)
228 {
229 }
230 
231 TimerAsio::~TimerAsio()
232 {
233 }
234 
235 //------------------------------------------------------------------------------
236 
237 void TimerAsio::setDuration(TimeDurationType duration)
238 {
239  ::fwCore::mt::ScopedLock lock(m_mutex);
240  m_duration = duration;
241 }
242 
243 //------------------------------------------------------------------------------
244 
246 {
247  ::fwCore::mt::ScopedLock lock(m_mutex);
248  this->rearmNoLock(m_duration);
249  m_running = true;
250 }
251 
252 //------------------------------------------------------------------------------
253 
255 {
256  ::fwCore::mt::ScopedLock lock(m_mutex);
257  if (m_running )
258  {
259  m_running = false;
260  this->cancelNoLock();
261  }
262 }
263 
264 //------------------------------------------------------------------------------
265 
266 void TimerAsio::rearmNoLock(TimeDurationType duration)
267 {
268  this->cancelNoLock();
269  ::boost::posix_time::time_duration d =
270  ::boost::posix_time::microseconds(std::chrono::duration_cast<std::chrono::microseconds>(duration).count());
271  m_timer.expires_from_now( d );
272  m_timer.async_wait( std::bind(&TimerAsio::call, this, std::placeholders::_1));
273 }
274 
275 //------------------------------------------------------------------------------
276 
277 void TimerAsio::call(const ::boost::system::error_code& error)
278 {
279  if(!error)
280  {
281  // We keep a reference to prevent a deletion of the Timer before the call back is over
282  // This means the timer may delete itself, this is not awesome but that seems to be enough for now
283  TimerAsio::sptr deleteLater = std::dynamic_pointer_cast<TimerAsio>(shared_from_this());
284 
285  TimeDurationType duration;
286  bool oneShot;
287  {
288  ::fwCore::mt::ScopedLock lock(m_mutex);
289  oneShot = m_oneShot;
290  duration = m_duration;
291  }
292 
293  if (!oneShot)
294  {
295  this->rearmNoLock(duration);
296  m_function();
297  }
298  else
299  {
300  m_function();
301  ::fwCore::mt::ScopedLock lock(m_mutex);
302  m_running = false;
303  }
304  }
305 
306 }
307 
308 //------------------------------------------------------------------------------
309 
310 void TimerAsio::cancelNoLock()
311 {
312  m_timer.cancel();
313 }
314 
315 } //namespace fwThread
316 
#define SPTR(_cls_)
bool isOneShot() const
Returns if the timer mode is &#39;one shot&#39;.
Definition: WorkerAsio.cpp:98
bool isRunning() const
Returns true if the timer is currently running.
Definition: WorkerAsio.cpp:112
FWCORE_API void modified()
Update the timestamp to the current EPOCH time.
Definition: TimeStamp.cpp:14
ThreadIdType getThreadId() const
Returns the worker&#39;s thread id.
Definition: WorkerAsio.cpp:190
bool m_running
Timer&#39;s state.
Definition: WorkerAsio.cpp:141
bool m_oneShot
Timer&#39;s mode.
Definition: WorkerAsio.cpp:138
STL namespace.
TimeDurationType m_duration
Time to wait until timer&#39;s expiration.
Definition: WorkerAsio.cpp:135
std::shared_ptr< ::fwThread::Timer > createTimer()
Creates and returns a fwThread::Timer running in this Worker.
Definition: WorkerAsio.cpp:176
FWTHREAD_API ThreadIdType getCurrentThreadId()
Returns the current thread id.
Definition: Worker.cpp:14
void setOneShot(bool oneShot)
Sets timer mode.
Definition: WorkerAsio.cpp:105
#define OSLM_TRACE(message)
Definition: spyLog.hpp:230
void stop()
Stops the timer and cancel all pending operations.
Definition: WorkerAsio.cpp:254
virtual void processTasks()
Processes all worker pending tasks for the calling thread until there are no more tasks to process...
Definition: WorkerAsio.cpp:197
TimerAsio(::boost::asio::io_service &ioSrv)
Constructs a TimerAsio from given io_service.
Definition: WorkerAsio.cpp:223
void post(TaskType handler)
Requests invocation of the given task handler and returns immediately.
Definition: WorkerAsio.cpp:183
FunctionType m_function
Function object to execute each time the timer expires.
Definition: Timer.hpp:89
void start()
Starts or restarts the timer.
Definition: WorkerAsio.cpp:245
void stop()
Waits for the last task to be processed and stops the loop.
Definition: WorkerAsio.cpp:170
FWCORE_API void setLifePeriod(TimeStampType period)
Setter for the life period.
Definition: TimeStamp.hpp:96
Provides a timestamp and a expiracy system.
Definition: TimeStamp.hpp:20
IOServiceType m_ioService
Class provides functionality to manipulate asynchronous tasks.
Definition: WorkerAsio.cpp:64
The Timer class provides single-shot or repetitive timers. A Timer triggers a function once after a d...
Definition: Timer.hpp:27
FWCORE_API bool periodExpired() const
Check TimeStamp expiracy status.
Definition: TimeStamp.hpp:118
WorkPtrType m_work
Class to inform the io_service when it has work to do.
Definition: WorkerAsio.cpp:67
::boost::asio::deadline_timer m_timer
Timer object.
Definition: WorkerAsio.cpp:132
Private implementation of fwThread::Worker using boost::asio.
Definition: WorkerAsio.cpp:31
std::shared_ptr< ThreadType > m_thread
Thread created and managed by the worker.
Definition: WorkerAsio.cpp:70
This class creates and manages a task loop. The default implementation create a loop in a new thread...
Definition: Worker.hpp:32
This namespace fwThread provides few tools to execute asynchronous tasks on different threads...
Private Timer implementation using boost::asio.
Definition: WorkerAsio.cpp:78
WorkerAsio & operator=(const WorkerAsio &)
Copy operator forbidden.
void setDuration(TimeDurationType duration)
Sets time duration.
Definition: WorkerAsio.cpp:237