jeudi 7 novembre 2019

stop a thread gracefully in c++

My main function loads a monitoring class. This class calls external services to periodically get some data and report health status.

These are the task_1 and task_2 in the class below, that can have sub tasks. The tasks accumulate some values that are stored to a shared "Data" class.

So each task_N is coupled with a thread that executes, sleeps for a while and does this forever until the program stops. My basic problem is that I cannot stop the threads in the Monitor class, since they might be waiting for the timer to expire (sleep)

#include <iostream>
#include <thread>
#include <utility>
#include "Settings.hpp"
#include "Data.hpp"

class Monitors {

public:

    Monitors(uint32_t timeout1, uint32_t timeout2, Settings settings, std::shared_ptr<Data> data)
            : timeout_1(timeout1), timeout_2(timeout2), settings_(std::move(settings)), data_(std::move(data)) {}


    void start() {
        thread_1 = std::thread(&Monitors::task_1, this);
        thread_2 = std::thread(&Monitors::task_2, this);
        started_ = true;
    }

    void stop() {
        started_ = false;
        thread_1.join();
        thread_2.join();
        std::cout << "stopping threads" << std::endl;

    }

    virtual ~Monitors() {

        std::cout << "Monitor stops" << std::endl;
    }

private:

    void subtask_1_1() {
        //std::cout << "subtask_1_1 reads " << settings_.getWeb1() << std::endl;
    }

    void subtask_1_2() {
        //std::cout << "subtask_1_2" << std::endl;
        data_->setValue1(21);
    }

    void task_1() {

        while(started_) {
            subtask_1_1();
            subtask_1_2();
            std::this_thread::sleep_for(std::chrono::milliseconds(timeout_1));
            std::cout << "task1 done" << std::endl;
        }

    }

    void subtask_2_1() {
        //std::cout << "subtask_2_1" << std::endl;
    }

    void subtask_2_2() {
        //std::cout << "subtask_2_2" << std::endl;
    }

    void task_2() {

        while(started_) {
            subtask_2_1();
            subtask_2_2();
            std::this_thread::sleep_for(std::chrono::milliseconds(timeout_2));
            std::cout << "task2 done" << std::endl;
        }

    }


private:

    bool started_ {false};
    std::thread thread_1;
    std::thread thread_2;
    uint32_t timeout_1;
    uint32_t timeout_2;
    Settings settings_;
    std::shared_ptr<Data> data_;

};

The main function is here:

        auto data = std::make_shared<Data>(10,20);
        Settings set("hello", "world");
        Monitors mon(1000, 24000,set,data);
        mon.start();

        int count = 1;
        while(true) {

            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            std::cout << data->getValue2() << " and count is " << count << std::endl;
            count++;
            if ( count == 10)
                break;
        }
        std::cout << "now I am here" << std::endl;
        mon.stop();
        return 0;

Now when I call mon.stop() the main thread stops only when the timer exprires. How can I gracefully call mon.stop() and interrupt and call the task_N?

Aucun commentaire:

Enregistrer un commentaire