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

发布于 2025-01-09 22:59:35 字数 1599 浏览 0 评论 0原文

我试图用 C++ boost::threadpoolcondition_variablemutex 编写一些任务管理类。看起来程序将停止在 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;
}

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

骷髅 2025-01-16 22:59:35

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

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

解决此问题的一种方法是在通知条件变量和等待线程池完成之间放弃互斥锁:

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

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 */
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文