我试图在C ++ 11中实现一个小型看门狗定时器类,它应该在过期时调用一些代码。
Watchdog.h:
Dim questionNumber As Integer = Random.Next(1, (File.ReadLines("<yourQuestions.txt").Count() / 6) + 1)
Dim blockLines = File.ReadLines("<yourQuestions.txt").Skip((questionNumber - 1) * 6).Take(6)
Dim currentQuestion As New Question(blockLines(0), blockLines(1), blockLines(2), blockLines(3), blockLines(4), blockLines(blockLines(5)))
Watchdog.cpp:
#pragma once
#include <thread>
#include <atomic>
class Watchdog
{
public:
Watchdog();
Watchdog(unsigned int milliseconds, std::function<void()> callback);
~Watchdog();
void Start(unsigned int milliseconds, std::function<void()> callback);
void Stop();
void Pet();
private:
unsigned int _interval;
std::atomic<unsigned int> _timer;
std::atomic<bool> _running;
std::thread _thread;
std::function<void()> _callback;
void Loop();
};
然而,这个线程循环对我来说似乎有点脏,而且#include "Watchdog.h"
Watchdog::Watchdog() :
_interval(0),
_timer(0),
_running(false)
{
}
Watchdog::Watchdog(unsigned int milliseconds, std::function<void()> callback)
{
Start(milliseconds, callback);
}
Watchdog::~Watchdog()
{
}
void Watchdog::Start(unsigned int milliseconds, std::function<void()> callback)
{
_interval = milliseconds;
_timer = 0;
_callback = callback;
_running = true;
_thread = std::thread(&Watchdog::Loop, this);
}
void Watchdog::Stop()
{
_running = false;
_thread.join();
}
void Watchdog::Pet()
{
_timer = 0;
}
void Watchdog::Loop()
{
while (_running)
{
_timer++;
if (_timer >= _interval)
{
_running = false;
_callback();
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
不准确(它睡觉时至少指定的数量,这意味着它可能超过1毫秒) ,有没有更好的方法来实现这个功能?
答案 0 :(得分:0)
似乎很有趣,我可以想出这段代码。 它没有编译,你必须在它上面做很多工作,但它显示了一个关于如何做的想法。
std::mutex cmutex; // needed for the condition_variable
std::condition_variable stop_condition;
std::chrono::time_point last_pet_time;
void Watchdog::Start(unsigned int milliseconds, std::function<void()> callback)
{
// somewhere in this method:
last_pet_time = now();
timeout = milliseconds;
}
void Watchdog::Stop()
{
if (_running) {
std::unique_lock<std::mutex> lock(cmutex);
_running = false;
stop_condition.notify_all(); // tell Loop() to stop
_thread.join();
}
}
void Watchdog::Pet()
{
std::unique_lock<std::mutex> lock(cmutex);
last_pet_time = now();
}
void Watchdog::Loop()
{
std::unique_lock<std::mutex> lock(cmutex);
while (_running // was Stop() called?
and (now() - last_pet_time) < timeout) // was Pet() ( or Start() ) called recently?
{
// here the threads waits until:
// 1. the condition_variable is notified in ::Stop()
// 2. or the timeout expires
// 3. or until spurious wakeup
stop_condition.wait_for(lock, timeout);
}
if (_running) {
_running = false;
callback();
}
}
检查:http://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
答案 1 :(得分:0)
这应该有效。真的有两节课。一个用于处理通知(AutoResetEvent)和Watchdog类本身。
AutoResetEvent.h
#pragma once
#include <mutex>
class AutoResetEvent
{
private:
bool m_ready = true;
std::condition_variable m_condition;
std::mutex m_mutex;
public:
AutoResetEvent();
~AutoResetEvent();
void WaitOne();
void WaitFor(unsigned __int32 milli_secs);
void Notify();
};
AutoResetEvent.cpp
AutoResetEvent::AutoResetEvent()
{
}
AutoResetEvent::~AutoResetEvent()
{
Notify();
}
void AutoResetEvent::Notify()
{
if (!m_ready)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_ready = true;
m_condition.notify_all();
}
}
void AutoResetEvent::WaitOne()
{
std::unique_lock<std::mutex> locker(m_mutex);
m_ready = false;
m_condition.wait(locker, [&ready = m_ready]() {return ready; });
}
void AutoResetEvent::WaitFor(unsigned __int32 milli_secs)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_ready = false;
m_condition.wait_for(locker, std::chrono::milliseconds(milli_secs), [&ready = m_ready]() {return ready; });
}
Watchdog.h
#pragma once
#include "AutoResetEvent.h"
#include <functional>
class Watchdog
{
private:
const unsigned __int32 WATCHDOG_BEEP_MS = 5*60*1000;
bool m_active_status = false;
bool m_new_pet = false;
bool m_cancelled = false;
AutoResetEvent m_reset_event;
std::function<void(void)> m_call_back;
void Loop();
public:
Watchdog(std::function<void(void)> call_back);
~Watchdog();
bool Start();
void Pet();
void Stop();
bool IsActive() const;
};
Watchdog.cpp
#include "stdafx.h"
#include "Watchdog.h"
void Watchdog::Loop()
{
m_active_status = true;
m_cancelled = false;
while (true)
{
m_new_pet = false;
m_reset_event.WaitFor(WATCHDOG_BEEP_MS);
if (!m_new_pet && !m_cancelled)
{
m_call_back();
break;
}
if (m_cancelled)
{
break;
}
}
m_active_status = false;
}
Watchdog::Watchdog(std::function<void(void)> call_back): m_call_back(call_back)
{
}
Watchdog::~Watchdog()
{
Stop();
}
bool Watchdog::Start()
{
if (IsActive()) return false;
std::thread loop_thread(&Watchdog::Loop, this);
loop_thread.detach();
return true;
}
void Watchdog::Pet()
{
if (!IsActive()) return;
m_new_pet = true;
m_reset_event.Notify();
}
void Watchdog::Stop()
{
if (!IsActive()) return;
m_cancelled = true;
m_reset_event.Notify();
}
bool Watchdog::IsActive() const
{
return m_active_status;
}