92
include/stdex/watchdog.hpp
Normal file
92
include/stdex/watchdog.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright © 2023 Amebis
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "compat.hpp"
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
namespace stdex
|
||||
{
|
||||
///
|
||||
/// Triggers callback if not reset frequently enough
|
||||
///
|
||||
template <class _Clock, class _Duration = typename _Clock::duration>
|
||||
class watchdog
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Starts the watchdog
|
||||
///
|
||||
/// \param[in] timeout How long the watchdog is waiting for a reset
|
||||
/// \param[in] callback The function watchdog calls on timeout
|
||||
///
|
||||
watchdog(_In_ _Duration timeout, _In_ std::function<void()> callback) :
|
||||
m_phase(0),
|
||||
m_quit(false),
|
||||
m_timeout(timeout),
|
||||
m_callback(callback),
|
||||
m_thread(run, std::ref(*this))
|
||||
{}
|
||||
|
||||
///
|
||||
/// Stops the watchdog
|
||||
///
|
||||
~watchdog()
|
||||
{
|
||||
{
|
||||
const std::lock_guard<std::mutex> lk(m_mutex);
|
||||
m_quit = true;
|
||||
}
|
||||
m_cv.notify_one();
|
||||
if (m_thread.joinable())
|
||||
m_thread.join();
|
||||
}
|
||||
|
||||
///
|
||||
/// Resets the watchdog
|
||||
///
|
||||
/// Must be called frequently enough not to timeout the watchdog
|
||||
///
|
||||
void reset()
|
||||
{
|
||||
{
|
||||
const std::lock_guard<std::mutex> lk(m_mutex);
|
||||
m_phase++;
|
||||
}
|
||||
m_cv.notify_one();
|
||||
}
|
||||
|
||||
protected:
|
||||
static void run(_Inout_ watchdog& wd)
|
||||
{
|
||||
for (;;) {
|
||||
std::unique_lock<std::mutex> lk(wd.m_mutex);
|
||||
auto phase = wd.m_phase;
|
||||
if (wd.m_cv.wait_for(lk, wd.m_timeout, [&] {return wd.m_quit || phase != wd.m_phase; })) {
|
||||
if (wd.m_quit)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
wd.m_callback();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t m_phase; ///< A counter we are incrementing to keep the watchdog happy
|
||||
bool m_quit; ///< Quit the watchdog
|
||||
_Duration m_timeout; ///< How long the watchdog is waiting for a reset
|
||||
std::function<void()> m_callback; ///< The function watchdog calls on timeout
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_cv;
|
||||
std::thread m_thread;
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user