-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e47ef37
commit be0aa40
Showing
5 changed files
with
93 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} |