boost::threadpool::pool::wait() 不停

boost::threadpool::pool::wait() doesn't stop

我试图用 C++ boost::threadpoolcondition_variablemutex 编写一些任务管理 class。好像程序会停在boost::threadpool::pool::wait(),但我不知道为什么会这样。

#include <boost/threadpool.hpp>
#include <condition_variable>
#include <iostream>
#include <mutex>
using namespace std;

enum {
    Running,
    Stopped,
    Exiting
};

class C {
private:
    int                     m_iStatus; 
    mutex                   m_mtx;
    condition_variable      m_cond;
    boost::threadpool::pool m_tp;
public:
    C() : m_iStatus(Stopped), m_tp(8) {}
    void Start();
    void Exit();
private:
    bool Check();
    void Dispatcher();
};

bool C::Check()
{
    unique_lock<mutex> lk(m_mtx);
    if (m_iStatus == Stopped)
        m_cond.wait(lk);
    if (m_iStatus == Exiting)
        return false;
    else                
        return true;
}

void C::Dispatcher()
{
    if (!Check())
        return;

    unique_lock<mutex> lk(m_mtx);
    // do something...
    cout << "." << endl;

    m_tp.schedule(bind(&C::Dispatcher, this));
}

void C::Start()
{
    unique_lock<mutex> lk(m_mtx);
    m_iStatus = Running;
    m_tp.schedule(bind(&C::Dispatcher, this));
}

void C::Exit()
{
    unique_lock<mutex> lk(m_mtx);
    m_iStatus = Exiting;
    m_cond.notify_all(); /* notify those waiting on m_cond */
    m_tp.wait(); /* went wrong here */
}

int main()
{
    C c;
    c.Start();

    /* wait for a moment */
    Sleep(1000);

    /* then call Exit */
    c.Exit();
    
    return 0;
}

您在仍然持有互斥锁的情况下进入等待呼叫。这将阻止其他线程完成他们的工作。

在您的特定情况下,m_cond 条件变量正在等待同一个互斥锁,因此只要互斥锁仍在,对 m_cond.wait(lk); 的调用将无法 return被另一个线程占用。

一个解决方案是在通知条件变量和等待线程池完成之间放弃对互斥体的锁定:

{
    unique_lock<mutex> lk(m_mtx);
    m_iStatus = Exiting;
    m_cond.notify_all(); /* notify those waiting on m_cond */
} // lock on m_mtx gets released here
m_tp.wait(); /* this should run fine now */