From be0aa40965e2e85608e267caa0060b322f813861 Mon Sep 17 00:00:00 2001 From: MeijisIrlnd Date: Mon, 12 Aug 2024 04:40:48 +0100 Subject: [PATCH] Timer --- include/mostly_harmless/CMakeLists.txt | 1 + .../utils/mostlyharmless_TaskThread.h | 2 +- .../utils/mostlyharmless_Timer.h | 48 +++++++++++++++++++ source/CMakeLists.txt | 1 + source/utils/mostlyharmless_Timer.cpp | 42 ++++++++++++++++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 include/mostly_harmless/utils/mostlyharmless_Timer.h create mode 100644 source/utils/mostlyharmless_Timer.cpp diff --git a/include/mostly_harmless/CMakeLists.txt b/include/mostly_harmless/CMakeLists.txt index 4632d58..2654e85 100644 --- a/include/mostly_harmless/CMakeLists.txt +++ b/include/mostly_harmless/CMakeLists.txt @@ -12,5 +12,6 @@ set(MOSTLYHARMLESS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/gui/mostlyharmless_IEditor.h ${CMAKE_CURRENT_SOURCE_DIR}/gui/mostlyharmless_WebviewEditor.h ${CMAKE_CURRENT_SOURCE_DIR}/utils/mostlyharmless_TaskThread.h + ${CMAKE_CURRENT_SOURCE_DIR}/utils/mostlyharmless_Timer.h ${PLATFORM_HEADERS} PARENT_SCOPE) \ No newline at end of file diff --git a/include/mostly_harmless/utils/mostlyharmless_TaskThread.h b/include/mostly_harmless/utils/mostlyharmless_TaskThread.h index 0daf6e1..e5d6b19 100644 --- a/include/mostly_harmless/utils/mostlyharmless_TaskThread.h +++ b/include/mostly_harmless/utils/mostlyharmless_TaskThread.h @@ -22,7 +22,7 @@ namespace mostly_harmless::utils { void perform(); /** - * Sleeps the thread until `wake` is called. Only call this from the thread! + * Sleeps the thread until wake() is called. Only call this from the thread! */ void sleep(); diff --git a/include/mostly_harmless/utils/mostlyharmless_Timer.h b/include/mostly_harmless/utils/mostlyharmless_Timer.h new file mode 100644 index 0000000..a8ddbe0 --- /dev/null +++ b/include/mostly_harmless/utils/mostlyharmless_Timer.h @@ -0,0 +1,48 @@ +// +// Created by Syl on 12/08/2024. +// + +#ifndef MOSTLYHARMLESS_MOSTLYHARMLESS_TIMER_H +#define MOSTLYHARMLESS_MOSTLYHARMLESS_TIMER_H +#include +#include +namespace mostly_harmless::utils { + /** + * \brief Class to periodically perform a user defined action. + * + * Runs on its own thread - so thread safety concerns all apply here. + */ + class Timer { + public: + /** + * Attempts to stop the timer if its running - note that this won't be instanteous (see stop() ) + */ + ~Timer() noexcept; + /** + * Starts the timer if action is not null (returns otherwise) - the action will be performed every intervalMs milliseconds (the first call will be after intervalMs milliseconds - not immediate). + * \param intervalMs The interval between calls, in milliseconds. + */ + void run(int intervalMs); + /** + * Starts the timer if action is not null (returns otherwise) - the action will be performed at frequency hz (the first call is not immediate). + * \param frequency The interval between calls, in hz. + */ + void run(double frequency); + /** + * Signals the timer thread that it should stop. The thread checks the flag every millisecond, so account for a worst case delay of around that. + */ + void stop(); + + /** + * \return true if the timer is running, false otherwise. + */ + [[nodiscard]] bool isTimerRunning() const noexcept; + /** + * A user defined callback to be performed periodically by the timer thread. Again, remember that this is *not* happening on the caller thread, so be extremely careful to write thread safe code here. + */ + std::function action{ nullptr }; + private: + TaskThread m_thread; + }; +} +#endif // MOSTLYHARMLESS_MOSTLYHARMLESS_TIMER_H diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index e67dd1b..25f1fa1 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -11,6 +11,7 @@ set(MOSTLYHARMLESS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/mostlyharmless_EventContext.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gui/mostlyharmless_WebviewEditor.cpp ${CMAKE_CURRENT_SOURCE_DIR}/utils/mostlyharmless_TaskThread.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/mostlyharmless_Timer.cpp ${PLATFORM_SOURCES} PARENT_SCOPE) message(STATUS ${MOSTLYHARMLESS_PLATFORM_SOURCES}) \ No newline at end of file diff --git a/source/utils/mostlyharmless_Timer.cpp b/source/utils/mostlyharmless_Timer.cpp new file mode 100644 index 0000000..e810a88 --- /dev/null +++ b/source/utils/mostlyharmless_Timer.cpp @@ -0,0 +1,42 @@ +// +// Created by Syl on 12/08/2024. +// +#include +namespace mostly_harmless::utils { + Timer::~Timer() noexcept { + stop(); + } + + void Timer::run(int intervalMs) { + if(!action) return; + auto threadAction = [this, intervalMs]() -> void { + int elapsedTimeMs{ 0 }; + while(!m_thread.threadShouldExit()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + if(m_thread.threadShouldExit()) return; + ++elapsedTimeMs; + if(elapsedTimeMs < intervalMs) continue; + action(); + elapsedTimeMs = 0; + } + }; + m_thread.action = std::move(threadAction); + m_thread.perform(); + } + + void Timer::run(double frequency) { + const auto seconds = 1.0 / frequency; + const auto ms = static_cast(seconds * 1000.0); + run(ms); + } + + void Timer::stop() { + if(m_thread.isThreadRunning()) { + m_thread.signalThreadShouldExit(); + } + } + + bool Timer::isTimerRunning() const noexcept { + return m_thread.isThreadRunning(); + } +} \ No newline at end of file