Timer.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. //
  2. // Timer.h
  3. //
  4. // $Id: //poco/1.4/Foundation/include/Poco/Timer.h#2 $
  5. //
  6. // Library: Foundation
  7. // Package: Threading
  8. // Module: Timer
  9. //
  10. // Definition of the Timer and related classes.
  11. //
  12. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  13. // and Contributors.
  14. //
  15. // SPDX-License-Identifier: BSL-1.0
  16. //
  17. #ifndef Foundation_Timer_INCLUDED
  18. #define Foundation_Timer_INCLUDED
  19. #include "Poco/Foundation.h"
  20. #include "Poco/Runnable.h"
  21. #include "Poco/Mutex.h"
  22. #include "Poco/Event.h"
  23. #include "Poco/Thread.h"
  24. #include "Poco/Clock.h"
  25. namespace Poco {
  26. class AbstractTimerCallback;
  27. class ThreadPool;
  28. class Foundation_API Timer: protected Runnable
  29. /// This class implements a thread-based timer.
  30. /// A timer starts a thread that first waits for a given start interval.
  31. /// Once that interval expires, the timer callback is called repeatedly
  32. /// in the given periodic interval. If the interval is 0, the timer is only
  33. /// called once.
  34. /// The timer callback method can stop the timer by setting the
  35. /// timer's periodic interval to 0.
  36. ///
  37. /// The timer callback runs in its own thread, so multithreading
  38. /// issues (proper synchronization) have to be considered when writing
  39. /// the callback method.
  40. ///
  41. /// The exact interval at which the callback is called depends on many
  42. /// factors like operating system, CPU performance and system load and
  43. /// may differ from the specified interval.
  44. ///
  45. /// The time needed to execute the timer callback is not included
  46. /// in the interval between invocations. For example, if the interval
  47. /// is 500 milliseconds, and the callback needs 400 milliseconds to
  48. /// execute, the callback function is nevertheless called every 500
  49. /// milliseconds. If the callback takes longer to execute than the
  50. /// interval, the callback function will not be called until the next
  51. /// proper interval. The number of skipped invocations since the last
  52. /// invocation will be recorded and can be obtained by the callback
  53. /// by calling skipped().
  54. ///
  55. /// The timer thread is taken from a thread pool, so
  56. /// there is a limit to the number of available concurrent timers.
  57. {
  58. public:
  59. Timer(long startInterval = 0, long periodicInterval = 0);
  60. /// Creates a new timer object. StartInterval and periodicInterval
  61. /// are given in milliseconds. If a periodicInterval of zero is
  62. /// specified, the callback will only be called once, after the
  63. /// startInterval expires.
  64. /// To start the timer, call the Start() method.
  65. virtual ~Timer();
  66. /// Stops and destroys the timer.
  67. void start(const AbstractTimerCallback& method);
  68. /// Starts the timer.
  69. /// Create the TimerCallback as follows:
  70. /// TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
  71. /// timer.start(callback);
  72. ///
  73. /// The timer thread is taken from the global default thread pool.
  74. void start(const AbstractTimerCallback& method, Thread::Priority priority);
  75. /// Starts the timer in a thread with the given priority.
  76. /// Create the TimerCallback as follows:
  77. /// TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
  78. /// timer.start(callback);
  79. ///
  80. /// The timer thread is taken from the global default thread pool.
  81. void start(const AbstractTimerCallback& method, ThreadPool& threadPool);
  82. /// Starts the timer.
  83. /// Create the TimerCallback as follows:
  84. /// TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
  85. /// timer.start(callback);
  86. void start(const AbstractTimerCallback& method, Thread::Priority priority, ThreadPool& threadPool);
  87. /// Starts the timer in a thread with the given priority.
  88. /// Create the TimerCallback as follows:
  89. /// TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
  90. /// timer.start(callback);
  91. void stop();
  92. /// Stops the timer. If the callback method is currently running
  93. /// it will be allowed to finish first.
  94. /// WARNING: Never call this method from within the callback method,
  95. /// as a deadlock would result. To stop the timer from within the
  96. /// callback method, call restart(0).
  97. void restart();
  98. /// Restarts the periodic interval. If the callback method is already running,
  99. /// nothing will happen.
  100. void restart(long milliseconds);
  101. /// Sets a new periodic interval and restarts the timer.
  102. /// An interval of 0 will stop the timer.
  103. long getStartInterval() const;
  104. /// Returns the start interval.
  105. void setStartInterval(long milliseconds);
  106. /// Sets the start interval. Will only be
  107. /// effective before start() is called.
  108. long getPeriodicInterval() const;
  109. /// Returns the periodic interval.
  110. void setPeriodicInterval(long milliseconds);
  111. /// Sets the periodic interval. If the timer is already running
  112. /// the new interval will be effective when the current interval
  113. /// expires.
  114. long skipped() const;
  115. /// Returns the number of skipped invocations since the last invocation.
  116. /// Skipped invocations happen if the timer callback function takes
  117. /// longer to execute than the timer interval.
  118. protected:
  119. void run();
  120. private:
  121. volatile long _startInterval;
  122. volatile long _periodicInterval;
  123. Event _wakeUp;
  124. Event _done;
  125. long _skipped;
  126. AbstractTimerCallback* _pCallback;
  127. Clock _nextInvocation;
  128. mutable FastMutex _mutex;
  129. Timer(const Timer&);
  130. Timer& operator = (const Timer&);
  131. };
  132. class Foundation_API AbstractTimerCallback
  133. /// This is the base class for all instantiations of
  134. /// the TimerCallback template.
  135. {
  136. public:
  137. AbstractTimerCallback();
  138. AbstractTimerCallback(const AbstractTimerCallback& callback);
  139. virtual ~AbstractTimerCallback();
  140. AbstractTimerCallback& operator = (const AbstractTimerCallback& callback);
  141. virtual void invoke(Timer& timer) const = 0;
  142. virtual AbstractTimerCallback* clone() const = 0;
  143. };
  144. template <class C>
  145. class TimerCallback: public AbstractTimerCallback
  146. /// This template class implements an adapter that sits between
  147. /// a Timer and an object's method invoked by the timer.
  148. /// It is quite similar in concept to the RunnableAdapter, but provides
  149. /// some Timer specific additional methods.
  150. /// See the Timer class for information on how
  151. /// to use this template class.
  152. {
  153. public:
  154. typedef void (C::*Callback)(Timer&);
  155. TimerCallback(C& object, Callback method): _pObject(&object), _method(method)
  156. {
  157. }
  158. TimerCallback(const TimerCallback& callback): _pObject(callback._pObject), _method(callback._method)
  159. {
  160. }
  161. ~TimerCallback()
  162. {
  163. }
  164. TimerCallback& operator = (const TimerCallback& callback)
  165. {
  166. if (&callback != this)
  167. {
  168. _pObject = callback._pObject;
  169. _method = callback._method;
  170. }
  171. return *this;
  172. }
  173. void invoke(Timer& timer) const
  174. {
  175. (_pObject->*_method)(timer);
  176. }
  177. AbstractTimerCallback* clone() const
  178. {
  179. return new TimerCallback(*this);
  180. }
  181. private:
  182. TimerCallback();
  183. C* _pObject;
  184. Callback _method;
  185. };
  186. } // namespace Poco
  187. #endif // Foundation_Timer_INCLUDED