2017-03-11 1 views
1

Ich verwende einen Online-Compiler C++11, Link hier gefunden: cpp.sh (C++ Shell).C++ 11 Watchdog-Klasse, Testanwendung möchte nicht beenden

In meinem aktuellen Projekt hätte ich gerne eine Watchdog-Klasse, um irgendwie den Status eines Threads oder FSM (zum Beispiel) überprüfen zu können.

Nach einiger Arbeit (ich bin kein C++11 Guru), habe ich endlich den Code unten, der kompiliert ok.
Ich habe auch einige grundlegende/triviale Tests, aber es scheint das Testprogramm möchte nicht beenden.
Er sagt, und der einzige Weg, um (Kraft) Ausfahrt „Programm läuft“ ist die „Stopp“ Knopf drücken ... :(

Nun, meine Frage: Was soll ich tun ? falsch
Irgendwelche Ideen, Anregungen Sie zur Verfügung stellen können sehr geschätzt

Hier die full code ist, auch meinen Test-App.

Watchdog (als MCVE):

#include <thread> 
#include <atomic> 
#include <chrono> 
#include <condition_variable> 
#include <mutex> 
#include <iostream> 

using namespace std::chrono; 

class Watchdog 
{ 
public: 
    Watchdog(); 
    ~Watchdog(); 
    void Start(unsigned int milliseconds, std::function<void()> callback = 0); 
    void Stop(); 
    void Pet(); 

private: 
    unsigned int m_interval; 
    std::atomic<bool> m_running; 
    std::thread m_thread; 
    std::function<void()> m_callback; 
    std::mutex m_mutex; 
    steady_clock::time_point m_lastPetTime; 
    std::condition_variable m_stopCondition; 
    void Loop(); 
}; 

Watchdog::Watchdog() 
{ 
    m_running = false; 
} 

Watchdog::~Watchdog() 
{ 
    Stop(); 
} 

void Watchdog::Start(unsigned int milliseconds, std::function<void()> callback) 
{ 
    std::unique_lock<std::mutex> locker(m_mutex); 
    if(m_running == false) 
    { 
     m_lastPetTime = steady_clock::now(); 
     m_interval = milliseconds; 
     m_callback = callback; 
     m_running = true; 
     m_thread = std::thread(&Watchdog::Loop, this); 
    } 
} 

void Watchdog::Stop() 
{ 
    std::unique_lock<std::mutex> locker(m_mutex); 
    if(m_running == true) 
    { 
     m_running = false; 
     m_stopCondition.notify_all(); 
     m_thread.join(); 
    } 
} 

void Watchdog::Pet() 
{ 
    std::unique_lock<std::mutex> locker(m_mutex); 
    m_lastPetTime = steady_clock::now(); 
    m_stopCondition.notify_all(); 
} 

void Watchdog::Loop() 
{ 
    std::unique_lock<std::mutex> locker(m_mutex); 
    while(m_running == true) 
    { 
     if(m_stopCondition.wait_for(locker, milliseconds(m_interval)) == std::cv_status::timeout) 
     { 
      if(m_callback != nullptr) 
       m_callback(); 
     } 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    Watchdog wdog; 

    wdog.Start(3000, [] { std::cout << " WDOG TRIGGERED!!! "; }); 
    for(auto i = 0; i < 10; i++) 
    { 
     std::cout << "[+]"; 
     wdog.Pet(); 
     std::this_thread::sleep_for(std::chrono::milliseconds(500)); 
    } 
} 

-

Antwort

2

Sie hier eine Sackgasse zu tun.

void Watchdog::Stop() 
{ 
    std::unique_lock<std::mutex> locker(m_mutex); 
    if(m_running == true) 
    { 
     m_running = false; 
     m_stopCondition.notify_all(); 
     m_thread.join(); 
     ^~~~~~~~~~~~~~~ 
      m_mutex is locked; m_thread cannot continue execution 
    } 
} 

Einige weiterer Vorschlag: Verwenden Sie einfach if Bedingungen nicht mit true oder false zu vergleichen.

+0

_Question_: Aus welchem ​​Grund sollte man einen Vergleich mit 'true/false' vermeiden? Danke im Voraus :) –

+0

@groenhen einfach weil sie schwer zu lesen sind. es speichert auch einige Zeichen;) –

+0

Also, die Idee ist nur zu entsperren 'm_mutex' rechts ** vor **' join() ', richtig? –