#ifndef UTIL_TIMER_H #define UTIL_TIMER_H #include #include #include #include "Helpers.h" namespace PresenceDetection { namespace Util { class Timer { public: Timer(); ~Timer(); Timer(const Timer&) = delete; Timer& operator= (const Timer&) = delete; Timer(Timer&& other); Timer& operator= (Timer&& other); bool operator==(const Timer& other) const; bool operator==(const std::string& identifier) const; bool operator==(bool running) const; public: std::string Identifier() const; template void StartSingle(int interval, std::function const & function, Arguments && ...arguments) { Start(TimerType::Single, interval, function, std::forward(arguments)...); } template void StartContinuous(int interval, std::function const & function, Arguments && ...arguments) { Start(TimerType::Continuous, interval, function, std::forward(arguments)...); } void Stop(); bool IsRunning() const noexcept; void Wait(); private: class TimerType { public: enum type { Unknown, Single, Continuous }; }; private: template void Start(TimerType::type type, int interval, std::function const & function, Arguments && ...arguments) { if (type == TimerType::Unknown) return; if (m_run.load(std::memory_order_acquire)) Stop(); m_thread = std::thread([this, type, interval, function, &arguments...]() { auto argumentsCopy = std::make_tuple(std::forward(arguments)...); m_run.store(true, std::memory_order_release); while (m_run.load(std::memory_order_acquire)) { std::this_thread::sleep_for(std::chrono::milliseconds(interval)); Helpers::execute(function, argumentsCopy); if (type == TimerType::Single) m_run.store(false, std::memory_order_release); } }); while (!IsRunning()) { } } private: std::atomic m_run; std::string m_identifier; std::thread m_thread; }; } // namespace Util } // namespace PresenceDetection #endif // UTIL_TIMER_H