samedi 11 mars 2017

C++11 Watchdog class, test application doesn't want to exit

I am using an online C++11 compiler, link found here: cpp.sh (C++ Shell).

In my current project, I would like to have a watchdog class, to be able to check somehow the status of a thread or FSM (for example).

After some work (I'm not a C++11 guru), I finally got the code below, that compiles ok.
I also did some basic/trivial tests, but it seems the test program doesn't want to exit.
It says "Program running" and the only way to (force) exit is to hit the "Stop" button... :(

Well, my question : What am I doing wrong?
Any ideas, suggestions you can provide are highly appreciated.

Here is the full code, including my test app:

Watchdog (as 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[])
{
    int i = 0;
    Watchdog wdog;

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

-

Aucun commentaire:

Enregistrer un commentaire