watchdog: add
Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
06a896ccf6
commit
67d328a550
@ -128,6 +128,7 @@
|
|||||||
<ClCompile Include="sgml.cpp" />
|
<ClCompile Include="sgml.cpp" />
|
||||||
<ClCompile Include="stream.cpp" />
|
<ClCompile Include="stream.cpp" />
|
||||||
<ClCompile Include="unicode.cpp" />
|
<ClCompile Include="unicode.cpp" />
|
||||||
|
<ClCompile Include="watchdog.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="compat.hpp" />
|
<ClInclude Include="compat.hpp" />
|
||||||
|
@ -39,6 +39,9 @@
|
|||||||
<ClCompile Include="hash.cpp">
|
<ClCompile Include="hash.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="watchdog.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="pch.hpp">
|
<ClInclude Include="pch.hpp">
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "sgml.cpp"
|
#include "sgml.cpp"
|
||||||
#include "stream.cpp"
|
#include "stream.cpp"
|
||||||
#include "unicode.cpp"
|
#include "unicode.cpp"
|
||||||
|
#include "watchdog.cpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main(int argc, const char * argv[])
|
int main(int argc, const char * argv[])
|
||||||
@ -34,6 +35,7 @@ int main(int argc, const char * argv[])
|
|||||||
UnitTests::unicode::str2wstr();
|
UnitTests::unicode::str2wstr();
|
||||||
UnitTests::unicode::wstr2str();
|
UnitTests::unicode::wstr2str();
|
||||||
UnitTests::unicode::charset_encoder();
|
UnitTests::unicode::charset_encoder();
|
||||||
|
UnitTests::watchdog::test();
|
||||||
std::cout << "PASS\n";
|
std::cout << "PASS\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
SPDX-License-Identifier: MIT
|
SPDX-License-Identifier: MIT
|
||||||
Copyright © 2023 Amebis
|
Copyright © 2023 Amebis
|
||||||
*/
|
*/
|
||||||
@ -23,6 +23,7 @@
|
|||||||
#include <stdex/system.hpp>
|
#include <stdex/system.hpp>
|
||||||
#include <stdex/unicode.hpp>
|
#include <stdex/unicode.hpp>
|
||||||
#include <stdex/vector_queue.hpp>
|
#include <stdex/vector_queue.hpp>
|
||||||
|
#include <stdex/watchdog.hpp>
|
||||||
|
|
||||||
#include "compat.hpp"
|
#include "compat.hpp"
|
||||||
|
|
||||||
|
32
UnitTests/watchdog.cpp
Normal file
32
UnitTests/watchdog.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
Copyright © 2023 Amebis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pch.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
#ifdef _WIN32
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace UnitTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(watchdog)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TEST_METHOD(test)
|
||||||
|
{
|
||||||
|
volatile bool wd_called = false;
|
||||||
|
stdex::watchdog<std::chrono::steady_clock> wd(
|
||||||
|
std::chrono::milliseconds(100), [&] { wd_called = true; });
|
||||||
|
for (int i = 0; i < 100; ++i) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
Assert::IsFalse(wd_called);
|
||||||
|
wd.reset();
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
||||||
|
Assert::IsTrue(wd_called);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
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;
|
||||||
|
};
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user