删除boost :: thread后代

时间:2012-11-10 16:05:45

标签: c++ destructor boost-thread

我正在尝试编写一个在其对象创建时运行线程的类,并在对象被删除后停止该线程。

class MyThread : public boost::thread {

public:

    MyThread() : bAlive(true) { 
        boost::thread(&MyThread::ThreadFunction,this);
    }

    ~MyThread() {
        {
            boost::unique_lock<boost::mutex> lock(Mutex);
            bAlive=false;
        }
        ConditionVariable.notify_one();
        join();
    }

private:

    volatile bool bAlive;
    boost::mutex Mutex;
    boost::condition_variable ConditionVariable;

    void ThreadFunction() {
        boost::unique_lock<boost::mutex> lock(Mutex);
        while(bAlive) {
            ConditionVariable.timed_wait(lock,boost::get_system_time()+ boost::posix_time::milliseconds(MAX_IDLE));

            /*******************************************
            * Here goes some code executed by a thread * 
            *******************************************/

        }
    }

};

理论上,我想在需要完成后立即唤醒线程,所以我不得不使用timed_wait而不是Sleep。 这工作正常,直到我尝试删除此类的对象。在大多数情况下,它会正常删除,但偶尔会在condition_variable.hpp,thread_primitives.hpp或crtexe.c中导致错误。有时我会收到通知“自由堆块3da7a8在被释放后在3da804处被修改”,有时我不是。是的,我知道timed_wait的虚假唤醒,在这种情况下它并不重要。 你能指点我的问题来源吗?我做错了什么?

1 个答案:

答案 0 :(得分:1)

我看到你正在尝试做什么,但它没有像你期望的那样工作:

MyThread foo;

默认构造一个boost :: thread(因为MyThread是从boost :: thread派生的)。 默认构造函数创建一个引用非线程的boost :: thread实例。

MyThread() {
    boost::thread(&MyThread::ThreadFunction,this);
}

实际上是在创建一个不同的线程而你忽略了返回的对象(有效的线程)。

~MyThread() {
    // ...
    join();
}

然后尝试加入默认构造的线程(在析构函数中引发异常),你永远不会加入实际工作的线程。


首先,不要从boost :: thread派生。改为创建一个成员变量:

class MyThread {
// ...
private:
    // ...
    boost::thread _thread;
};

在构造函数中,创建并为该成员变量分配一个线程:

MyThread() {
    _thread = boost::thread(&MyThread::ThreadFunction,this);
}

并在析构函数中调用它的join()。

~MyThread() {
    // ...
    _thread.join();
}

那应该解决你的问题。


但是,如果您只想在销毁对象时退出线程(并且不必在其运行时将其唤醒),则可以使用其他方法。删除互斥锁和条件变量并改为使用中断。这将导致sleep()抛出异常,因此您必须捕获它:

void ThreadFunction() {
    try {
        for(;;) {
            boost::this_thread::sleep(boost::posix_time::milliseconds(MAX_IDLE));
            // Here goes some code executed by a thread
        }
    } catch( const boost::thread_interrupted& e ) {
        // ignore exception: thread interrupted, exit function
    }
}

当线程中断时,这将立即退出ThreadFunction。如果您不需要线程在每个周期休眠,则可以将其替换为boost::this_thread::interruption_point()。如果线程被中断,这只会抛出异常。

现在你可以简单地在析构函数中断线程:

MyThread::~MyThread() {
    _thread.interrupt();
    _thread.join();
}