如何用多态管理线程资源? (C++)

How to manage thread resource with polymorphism? (C++)

我正在尝试实现多态性,其中派生的 class 在单独的线程中实现了一个 运行 的方法:

#include <memory>
#include <thread>
#include <chrono>

class Base
{
public:
    std::thread m_jobThread;

    ~Base() { if (m_jobThread.joinable()) m_jobThread.join(); }

    virtual void doJob() = 0;
    void doJobInBackground() { m_jobThread = std::thread(&Base::doJob, this); }
};

class Drived : public Base
{
public:
    Drived() = default;
    virtual void doJob() final { std::this_thread::sleep_for(std::chrono::seconds(1)); }
};

int main(int argc, char const *argv[])
{
    Drived d;
    d.doJobInBackground();
    return 0;
}

如何在不出现 pure virtual method called 异常的情况下安全地实现此目的?

我希望能够销毁派生对象,可能是在作业进行时,并让基础 class 的析构函数处理管理线程。但是由于派生 class 的 vtable 在基 class 的析构函数是 运行 之前被销毁,我得到一个纯虚方法异常。

我想在派生的 class 的析构函数中添加一个 stop 方法,以确保线程已连接。但这违背了我的多态设计的目的,我希望派生 class 只负责定义 doJob 方法而不是直接或间接处理基础 class 的资源比如线程...

有什么想法可以吗?我需要更改设计吗?

正如 Sam Varshavchik 在他上面的评论中所指出的,你在这里触发纯虚函数调用的原因是 d 的析构函数在你的第二个线程开始之前就已经 运行执行。您只在 Base 析构函数中同步。但是,到 Base 析构函数 运行 时,对象的 Derived 部分已经被销毁了。此时对象的动态类型只是 Base,因为这是仍然存在的所有类型,因此,虚函数调用分派到纯基础版本。严格来说,你实际上在这里有未定义的行为,因为对象在一个线程中被销毁而另一个线程可能正在调用它的方法违反了 [basic.life]/7.2. The lifetime of your object ends when the destructor call starts [basic.life]/1.3, the method call in the second thread does not inter-thread happen before 第一个线程中的析构函数调用......

刚刚

#include <thread>
#include <chrono>

class Base
{
    std::thread m_jobThread;

public:
    void join() { if (m_jobThread.joinable()) m_jobThread.join(); }

    virtual void doJob() = 0;
    void doJobInBackground() { join(); m_jobThread = std::thread(&Base::doJob, this); }
};

class Derived : public Base
{
public:
    virtual void doJob() final { std::this_thread::sleep_for(std::chrono::seconds(1)); }
};

int main(int argc, char const* argv[])
{
    Derived d;
    d.doJobInBackground();
    d.join();
    return 0;
}

工作正常…