mercredi 7 juillet 2021

Cleanup resources of base class before destructing derived class

I implemented an own Runnable to call threads:

#include <iostream>
#include <memory>
#include <thread>

class Runnable {
public:
    Runnable(): running_thread_(nullptr) {}

    void run() {
        if(running_thread_)
            return;

        running_thread_ = std::unique_ptr<std::thread>(new std::thread(&Runnable::run_thread, this));

    }

    virtual ~Runnable() {
        stop();
    }

    void stop() {
        if (running_thread_ && running_thread_->joinable()) {
            running_thread_->join();
        }
        running_thread_ = nullptr;
    }

protected:
    void run_thread()
    {
        std::cout << "a" << std::endl;
        start();
        std::cout << "b" << std::endl;
    }

    virtual bool start() = 0;

private:
    std::unique_ptr<std::thread> running_thread_;
};

class TestRunner : public Runnable {
public:
    virtual ~TestRunner() {
    };

protected:
    bool start() override {
        return true;
    }
};

int main() {
    auto testRunner = std::make_shared<TestRunner>();
    testRunner->run();
}

If I run the code I get following output:

/home/vagrant/tmp/clionTestProject/cmake-build-debug/clionTestProject 
a 
pure virtual method called 
terminate called without an active exception

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

It seems that start() is called after the destructor of TestRunner. The call of stop() on the destructor of Runnable() does not help as the destructor of TestRunner is executed before. At least I found that I can repair it by calling stop in the destructor of TestRunner:

    virtual ~TestRunner() {
        stop();
    };

Using this destructor everything works as expected. But I would not like to care in the derived classes about calling the stop() methods, all the thread handling shall be covered in Runnable. Do you have an idea how to solve this?

Aucun commentaire:

Enregistrer un commentaire