Skip to content

Commit

Permalink
Timer
Browse files Browse the repository at this point in the history
  • Loading branch information
MeijisIrlnd committed Aug 12, 2024
1 parent e47ef37 commit be0aa40
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/mostly_harmless/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion include/mostly_harmless/utils/mostlyharmless_TaskThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace mostly_harmless::utils {
void perform();

/**
* Sleeps the thread until `wake` is called. <b>Only call this from the thread!</b>
* Sleeps the thread until wake() is called. <b>Only call this from the thread!</b>
*/
void sleep();

Expand Down
48 changes: 48 additions & 0 deletions include/mostly_harmless/utils/mostlyharmless_Timer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// Created by Syl on 12/08/2024.
//

#ifndef MOSTLYHARMLESS_MOSTLYHARMLESS_TIMER_H
#define MOSTLYHARMLESS_MOSTLYHARMLESS_TIMER_H
#include <mostly_harmless/utils/mostlyharmless_TaskThread.h>
#include <chrono>
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<void(void)> action{ nullptr };
private:
TaskThread m_thread;
};
}
#endif // MOSTLYHARMLESS_MOSTLYHARMLESS_TIMER_H
1 change: 1 addition & 0 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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})
42 changes: 42 additions & 0 deletions source/utils/mostlyharmless_Timer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// Created by Syl on 12/08/2024.
//
#include <mostly_harmless/utils/mostlyharmless_Timer.h>
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<int>(seconds * 1000.0);
run(ms);
}

void Timer::stop() {
if(m_thread.isThreadRunning()) {
m_thread.signalThreadShouldExit();
}
}

bool Timer::isTimerRunning() const noexcept {
return m_thread.isThreadRunning();
}
}

0 comments on commit be0aa40

Please sign in to comment.