MIRA
DispatcherThread.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
48 #ifndef _MIRA_DISPATCHERTHREAD_H_
49 #define _MIRA_DISPATCHERTHREAD_H_
50 
51 #include <set>
52 #include <deque>
53 
54 #ifndef Q_MOC_RUN
55 #include <boost/function.hpp>
56 #include <boost/thread/condition_variable.hpp>
57 #endif
58 
59 #include <error/LoggingAux.h>
60 #include <utils/Time.h>
61 #include <utils/StringAlgorithms.h>
62 #include <thread/Thread.h>
63 #include <fw/FrameworkExports.h>
64 #include <fw/Status.h>
65 #include <fw/Runnable.h>
66 
67 namespace mira {
68 
69 
70 template<typename T, typename Sequence = std::vector<T>,
71  typename Compare = std::less<typename Sequence::value_type> >
72 class IteratablePriorityQueue : public std::priority_queue<T,Sequence,Compare>
73 {
74  typedef std::priority_queue<T,Sequence,Compare> Base;
75 public:
76 
77  // types
78  typedef typename Sequence::iterator iterator;
79  typedef typename Sequence::const_iterator const_iterator;
80 
81 public:
82  explicit IteratablePriorityQueue(const Compare& x, const Sequence& s) :
83  Base(x,s) {}
84 
85  explicit IteratablePriorityQueue(const Compare& x = Compare(), Sequence&& s = Sequence()) :
86  Base(x,std::move(s)) {}
87 
88 
89  template<typename InputIterator>
90  IteratablePriorityQueue(InputIterator first, InputIterator last, const Compare& x, const Sequence& s) :
91  Base(first,last,x,s) {}
92 
93  template<typename InputIterator>
94  IteratablePriorityQueue(InputIterator first, InputIterator last, const Compare& x, Sequence&& s) :
95  Base(first,last,x,std::move(s)) {}
96 
97 public:
98 
99  iterator begin() { return this->c.begin(); }
100  iterator end() { return this->c.end(); }
101 
102  const_iterator begin() const { return this->c.begin(); }
103  const_iterator end() const { return this->c.end(); }
104 
105 
106 };
107 
108 
109 
110 
111 
113 
132 {
133 public:
134 
136  class Timer;
138  typedef boost::function<void(const Timer&)> TimerCallback;
139 
147  MIRA_FRAMEWORK_EXPORT class Timer : public IRunnable, boost::noncopyable
148  {
149  protected:
151  friend class DispatcherThread;
152 
158  Timer(TimerCallback callback, Duration period,
159  Duration tolerance = Duration::invalid());
160 
166  Timer(TimerCallback callback, Time invokationTime);
167 
168  protected:
169 
174  currentExpected += mPeriod;
175  }
176 
177  void run(DispatcherThread* dispatcher) override;
178 
179  public:
180 
184  bool isActive() const { return mActive; }
185 
190  void setPeriod(Duration period) { mPeriod = period; }
191 
195  Duration getPeriod() const { return mPeriod; }
196 
202  void setTolerance(Duration tolerance) { mTolerance = tolerance; }
203 
208  Duration getTolerance() const { return mTolerance; }
209 
217  {
218  if (mPeriod > Duration::seconds(0))
219  {
220  Duration dt = current - currentExpected;
221  if (dt > mTolerance)
222  return dt;
223  }
224  return Duration::seconds(0);
225  }
226 
227 
228  public:
229 
233  void start();
234 
239  void stop();
244  return currentExpected;
245  }
246 
247  public:
248 
251 
254 
257 
260 
261  private:
262 
263  TimerCallback mCallback;
264  Duration mPeriod;
265  Duration mTolerance;
266  bool mOneShot;
267  bool mActive;
268  };
269 
270  typedef boost::shared_ptr<Timer> TimerPtr;
271 
272 public:
273 
278  DispatcherThread(const std::string& name = "");
279 
280  virtual ~DispatcherThread();
281 
282  void setName(const std::string& name);
283 
284  bool insertRunnable(IRunnablePtr runnable, bool singleton = false, Time time=Time::now());
285  void removeRunnable(IRunnablePtr runnable);
286 
287 
295  void addImmediateHandler(IRunnablePtr runnable);
296 
304  template <typename F>
305  void addImmediateHandlerFunction(F&& fn, DiagnosticsModulePtr errorModule=nullptr) {
306  IRunnablePtr r(new FunctionRunnable<F>(static_cast<F&&>(fn),errorModule));
307  addImmediateHandler(r);
308  }
309 
313  void addFinalizeHandler(IRunnablePtr runnable);
314 
320  template <typename F>
321  void addFinalizeHandlerFunction(F&& fn, DiagnosticsModulePtr errorModule=nullptr) {
322  IRunnablePtr r(new FunctionRunnable<F>(static_cast<F&&>(fn),errorModule));
323  addFinalizeHandler(r);
324  }
325 
332  TimerPtr createTimer(Duration period, Duration periodTolerance,
333  TimerCallback callback, bool oneshot=false);
334 
340  TimerPtr createTimer(Duration period, TimerCallback callback,
341  bool oneshot=false);
342 
347  TimerPtr createTimer(Time time, TimerCallback callback);
348 
354  void removeTimer(TimerPtr timer);
355 
359  bool hasTimer(TimerPtr timer);
360 
378  void start(bool startThread = true);
379 
384  void stop();
385 
392  bool hasUnrecoverableFailure() const;
393 
399 
401  bool isRunning() const;
402 
417  bool spin(Duration maxWait = Duration::infinity());
418 
426  boost::thread::id getThreadID() const {
427  return mThreadId;
428  }
429 
441  [[nodiscard]] bool hasWork(Time horizon = Time::now()) const;
442 
443 protected:
451  void run();
452 
453 private:
454 
455  void runThread();
456 
457 private:
458 
460  bool processImmediateHandlers();
461  bool processFinalizeHandlers();
462  bool processSpin(const Duration& maxWait);
463 
464 private:
465 
466  bool isInterruptionRequested();
467 
468 protected:
469 
471  struct QueueItem
472  {
474  QueueItem(IRunnablePtr r, Time t) : runnable(r), time(t), toBeRemoved(false) {}
475 
476 
480 
481  bool operator<(const QueueItem& other) const { return time>other.time; }
482  };
483 
485 
486 
488  std::set<IRunnablePtr> mPendingRunnables;
489 
490  mutable boost::mutex mConditionMutex;
491  boost::condition_variable mCondition;
492 
494 
495  void postProcessTimer(TimerPtr timer);
496 
498  std::string mName;
499 
500  std::list<IRunnablePtr> mImmediateHandlers;
501  mutable boost::mutex mImmediateHandlerMutex;
502 
503  std::list<IRunnablePtr> mFinalizeHandlers;
504  boost::mutex mFinalizeHandlerMutex;
505 
506  std::set<TimerPtr> mTimers;
507  boost::mutex mTimerMutex; // protects above handler sets
508 
511 
512  // unfortunatelly, we need our own interruption requested flag, since
513  // boost::this_thread::interruption_requested() is cleared after a
514  // boost::thread_interrupted exception is thrown, however, we need this
515  // flag to be true, until we really have terminated
517 
518  boost::thread mThread;
519  boost::thread::id mThreadId;
521 
522 };
523 
527 
529 
530 } // namespace
531 
532 #endif /* _MIRA_DISPATCHERTHREAD_H_ */
bool toBeRemoved
Definition: DispatcherThread.h:479
boost::mutex mConditionMutex
Definition: DispatcherThread.h:490
std::set< TimerPtr > mTimers
Definition: DispatcherThread.h:506
static Duration invalid()
Returns an invalid duration.
Definition: Time.h:249
Time currentExpected
time the current callback should be happening
Definition: DispatcherThread.h:253
Sequence::iterator iterator
Definition: DispatcherThread.h:78
bool mInterruptionRequested
Definition: DispatcherThread.h:516
boost::condition_variable mCondition
Definition: DispatcherThread.h:491
PropertyHint spin(const T &min, const T &max, const T &s)
Sets the attribute "type" to the value "spinbox" and sets the "minimum", "maximum" and "step" attribu...
Definition: PropertyHint.h:328
DispatcherThread::Timer Timer
Definition: DispatcherThread.h:524
DispatcherThread::TimerPtr TimerPtr
Definition: DispatcherThread.h:525
bool mUnrecoverableFailure
Definition: DispatcherThread.h:509
Class representing timers and tasks that can be registered and executed by the dispatcher thread...
Definition: DispatcherThread.h:147
TODO Add description.
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
boost::function< void(const Timer &)> TimerCallback
Signature of a timer/task callback function.
Definition: DispatcherThread.h:136
boost::mutex mFinalizeHandlerMutex
Definition: DispatcherThread.h:504
bool mIsRunning
Definition: DispatcherThread.h:510
IteratablePriorityQueue(const Compare &x, const Sequence &s)
Definition: DispatcherThread.h:82
Time and Duration wrapper class.
STL namespace.
void addImmediateHandlerFunction(F &&fn, DiagnosticsModulePtr errorModule=nullptr)
Adds a function that is executed once as soon as possible within the DispatcherThreads main thread...
Definition: DispatcherThread.h:305
Runnable that wraps any function pointer.
Definition: Runnable.h:115
QueueItem(IRunnablePtr r, Time t)
Definition: DispatcherThread.h:474
Framework export macro declaration.
bool operator<(const QueueItem &other) const
Definition: DispatcherThread.h:481
IteratablePriorityQueue(InputIterator first, InputIterator last, const Compare &x, Sequence &&s)
Definition: DispatcherThread.h:94
Wrapper class for boost::posix_time::ptime for adding more functionality to it.
Definition: Time.h:418
IteratablePriorityQueue(InputIterator first, InputIterator last, const Compare &x, const Sequence &s)
Definition: DispatcherThread.h:90
IteratablePriorityQueue< QueueItem, std::deque< QueueItem > > Queue
Definition: DispatcherThread.h:484
boost::mutex mTimerMutex
Definition: DispatcherThread.h:507
void setTolerance(Duration tolerance)
Set the tolerance that is allowed to exceed the next invocation time before issuing a warning and res...
Definition: DispatcherThread.h:202
boost::shared_ptr< Timer > TimerPtr
Definition: DispatcherThread.h:270
std::list< IRunnablePtr > mImmediateHandlers
Definition: DispatcherThread.h:500
Base for all runnable classes that can be signaled when they need to run again.
Definition: Runnable.h:72
Auxiliary logging macros for special entities like exceptions, etc.
Includes, defines and functions for threads.
Definition: DispatcherThread.h:72
Duration getExceedance() const
Checks and returns the amount of time the timer has exceeded the expected invocation time...
Definition: DispatcherThread.h:216
DispatcherThread::TimerCallback TimerCallback
Definition: DispatcherThread.h:526
Time getNextInvocationTime() const
Return next time of execution.
Definition: DispatcherThread.h:243
void setPeriod(Duration period)
Changes the period of the timer.
Definition: DispatcherThread.h:190
#define MIRA_FRAMEWORK_EXPORT
Definition: FrameworkExports.h:61
sec_type seconds() const
Returns normalized number of seconds (0..59)
Definition: Time.h:280
Time last
time the last callback happened
Definition: DispatcherThread.h:250
Use this class to represent time durations.
Definition: Time.h:106
iterator end()
Definition: DispatcherThread.h:100
boost::thread::id getThreadID() const
Returns the thread id of the thread that is used to process the dispatcher.
Definition: DispatcherThread.h:426
boost::shared_ptr< IRunnable > IRunnablePtr
a runnable pointer
Definition: Runnable.h:63
XXX.
Definition: DispatcherThread.h:471
Class that can be used whenever you want to have ONE thread where several handlers are assigned to...
Definition: DispatcherThread.h:131
boost::mutex mImmediateHandlerMutex
Definition: DispatcherThread.h:501
void updateInvocationTime()
Called by dispatcher when timer is rescheduled.
Definition: DispatcherThread.h:173
static Duration infinity()
Returns a special duration time representing positive infinity.
Definition: Time.h:242
Duration getTolerance() const
Get the tolerance for exceed the next invocation time.
Definition: DispatcherThread.h:208
bool isActive() const
Returns if the timer is active.
Definition: DispatcherThread.h:184
IteratablePriorityQueue(const Compare &x=Compare(), Sequence &&s=Sequence())
Definition: DispatcherThread.h:85
Duration getPeriod() const
Returns the current period of the timer.
Definition: DispatcherThread.h:195
QueueItem()
Definition: DispatcherThread.h:473
Sequence::const_iterator const_iterator
Definition: DispatcherThread.h:79
static Time now() static Time eternity()
Returns the current utc based time.
Definition: Time.h:481
Time time
Definition: DispatcherThread.h:478
boost::thread mThread
Definition: DispatcherThread.h:518
std::set< IRunnablePtr > mPendingRunnables
Definition: DispatcherThread.h:488
Queue mQueue
Definition: DispatcherThread.h:487
bool mPendingSignal
Definition: DispatcherThread.h:520
IRunnablePtr runnable
Definition: DispatcherThread.h:477
std::string mName
Definition: DispatcherThread.h:498
Exception that can be thrown in every handler to indicate an unrecoverable failure.
Definition: DispatcherThread.h:398
const_iterator end() const
Definition: DispatcherThread.h:103
const_iterator begin() const
Definition: DispatcherThread.h:102
Include file for including all string algorithm headers.
boost::thread::id mThreadId
Definition: DispatcherThread.h:519
iterator begin()
Definition: DispatcherThread.h:99
Base class for modules that want to use diagnostics and set the current status.
Definition: Status.h:138
void addFinalizeHandlerFunction(F &&fn, DiagnosticsModulePtr errorModule=nullptr)
Adds a function that is executed once just before the thread terminates.
Definition: DispatcherThread.h:321
std::list< IRunnablePtr > mFinalizeHandlers
Definition: DispatcherThread.h:503
Status and status management classes used for diagnostics.
Duration lastDuration
How long the last callback ran for.
Definition: DispatcherThread.h:259
Time current
time the current callback was actually called (Time::now() as of the beginning of the callback) ...
Definition: DispatcherThread.h:256