#ifndef TIMER_H #define TIMER_H #include "TimerHelpers.h" #include #include #include #include #include #include namespace Timer { class Timer { public: Timer(); ~Timer(); Timer(const Timer&) = delete; Timer& operator= (const Timer&) = delete; bool operator==(const Timer& other) const; public: std::string Identifier() const; template void StartSingle(int milliSeconds, std::function const & function, Arguments && ...arguments) { Start(TimerType::Single, milliSeconds, function, std::forward(arguments)...); } template void StartContinuous(int milliSeconds, std::function const & function, Arguments && ...arguments) { Start(TimerType::Continuous, milliSeconds, function, std::forward(arguments)...); } void Stop(); void Abort(); bool IsRunning() const noexcept; void Wait(); private: class TimerType { public: enum type { Unknown, Single, Continuous }; }; private: template void Start(TimerType::type type, int milliSeconds, 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, milliSeconds, function, &arguments...]() { auto argumentsCopy = std::make_tuple(std::forward(arguments)...); m_run.store(true, std::memory_order_release); m_aborted = false; while (m_run.load(std::memory_order_acquire)) { std::unique_lock lock(m_mutex); if (!m_conditionVariable.wait_for(lock, std::chrono::milliseconds(milliSeconds), [&]{return m_aborted;})) { Helpers::execute(function, argumentsCopy); if (type == TimerType::Single) m_run.store(false, std::memory_order_release); } } }); #ifdef __linux__ pthread_setname_np(m_thread.native_handle(), "Timer"); #endif while (!IsRunning()) { } } private: std::atomic m_run; bool m_aborted; std::mutex m_mutex; std::condition_variable m_conditionVariable; std::string m_identifier; std::thread m_thread; }; typedef std::unique_ptr TimerPointer; } // namespace Timer #endif // TIMER_H