Home > Back-end >  boost::threadpool::pool::wait() doesn't stop
boost::threadpool::pool::wait() doesn't stop

Time:02-26

I was trying to write some Task-Management class with C boost::threadpool, condition_variable and mutex. It seems the program will stop at boost::threadpool::pool::wait(), but I don't know why this happens.

#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;
}

CodePudding user response:

You enter the wait call while still holding the mutex. This will prevent other thread's from completing their work.

In your particular case, the m_cond condition variable is waiting on that same mutex, so the call to m_cond.wait(lk); will be unable to return as long as the mutex is still being held by the other thread.

One solution to this would be to relinquish the lock on the mutex between notifying the condition variable and waiting for the thread pool to complete:

{
    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 */
  • Related