Timer.h 2.5 KB

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