Timer.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #ifndef UTIL_TIMER_H
  2. #define UTIL_TIMER_H
  3. #include <atomic>
  4. #include <condition_variable>
  5. #include <functional>
  6. #include <memory>
  7. #include <mutex>
  8. #include <thread>
  9. #include "Helpers.h"
  10. namespace PresenceDetection {
  11. namespace Util {
  12. class Timer
  13. {
  14. public:
  15. Timer();
  16. ~Timer();
  17. Timer(const Timer&) = delete;
  18. Timer& operator= (const Timer&) = delete;
  19. bool operator==(const Timer& other) const;
  20. public:
  21. std::string Identifier() const;
  22. template <typename ...FunctionArguments, typename ...Arguments>
  23. void StartSingle(int milliSeconds, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
  24. {
  25. Start(TimerType::Single, milliSeconds, function, std::forward<Arguments>(arguments)...);
  26. }
  27. template <typename ...FunctionArguments, typename ...Arguments>
  28. void StartContinuous(int milliSeconds, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
  29. {
  30. Start(TimerType::Continuous, milliSeconds, function, std::forward<Arguments>(arguments)...);
  31. }
  32. void Stop();
  33. void Abort();
  34. bool IsRunning() const noexcept;
  35. void Wait();
  36. private:
  37. class TimerType
  38. {
  39. public:
  40. enum type
  41. {
  42. Unknown,
  43. Single,
  44. Continuous
  45. };
  46. };
  47. private:
  48. template <typename ...FunctionArguments, typename ...Arguments>
  49. void Start(TimerType::type type, int milliSeconds, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
  50. {
  51. if (type == TimerType::Unknown)
  52. return;
  53. if (m_run.load(std::memory_order_acquire))
  54. Stop();
  55. m_thread = std::thread([this, type, milliSeconds, function, &arguments...]()
  56. {
  57. auto argumentsCopy = std::make_tuple(std::forward<Arguments>(arguments)...);
  58. m_run.store(true, std::memory_order_release);
  59. m_aborted = false;
  60. while (m_run.load(std::memory_order_acquire))
  61. {
  62. std::unique_lock<std::mutex> lock(m_mutex);
  63. if (!m_conditionVariable.wait_for(lock, std::chrono::milliseconds(milliSeconds), [&]{return m_aborted;}))
  64. {
  65. Helpers::execute(function, argumentsCopy);
  66. if (type == TimerType::Single)
  67. m_run.store(false, std::memory_order_release);
  68. }
  69. }
  70. });
  71. while (!IsRunning())
  72. {
  73. }
  74. }
  75. private:
  76. std::atomic<bool> m_run;
  77. bool m_aborted;
  78. std::mutex m_mutex;
  79. std::condition_variable m_conditionVariable;
  80. std::string m_identifier;
  81. std::thread m_thread;
  82. };
  83. typedef std::unique_ptr<Timer> TimerPointer;
  84. } // namespace Util
  85. } // namespace PresenceDetection
  86. #endif // UTIL_TIMER_H