How do I use a boost condition variable to wait for a thread to complete processing?

后端 未结 2 1716
我在风中等你
我在风中等你 2020-12-07 15:10

I am using a conditional variable to stop a thread until another thread has completed processing it\'s task queue (long story). So, on one thread I lock and wait:

         


        
相关标签:
2条回答
  • 2020-12-07 15:37

    Yes, you are misusing the condition variable. "Condition variables" are really just the signaling mechanism. You also need to be testing a condition. In your case what might be happening is that the thread that is calling notify_one() actually completes before the thread that calls wait() even starts. (Or at least, the notify_one() call is happening before the wait() call.) This is called a "missed wakeup."

    The solution is to actually have a variable which contains the condition you care about:

    bool worker_is_done=false;
    
    boost::mutex::scoped_lock lock(m_mutex);
    while (!worker_is_done) m_condition.wait(lock);
    

    and

    boost::mutex::scoped_lock lock(m_mutex);
    worker_is_done = true;
    m_condition.notify_one();
    

    If worker_is_done==true before the other thread even starts waiting then you'll just fall right through the while loop without ever calling wait().

    This pattern is so common that I'd almost go so far as to say that if you don't have a while loop wrapping your condition_variable.wait() then you always have a bug. In fact, when C++11 adopted something similar to the boost::condtion_variable they added a new kind of wait() that takes a predicate lambda expression (essentially it does the while loop for you):

    std::condition_variable cv;
    std::mutex m;
    bool worker_is_done=false;
    
    
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []{return worker_is_done;});
    
    0 讨论(0)
  • 2020-12-07 15:38

    I had implemented an example that illustrates how to use boost condition, based in the discussion.

    #include <iostream>
    
    #include <boost/asio.hpp>
    #include <boost/thread/mutex.hpp>
    #include <boost/thread/thread.hpp>
    
    boost::mutex io_mutex;
    bool worker_is_done = false;
    boost::condition_variable condition;
    
    void workFunction()
    {
        std::cout << "Waiting a little..." << std::endl;
        boost::this_thread::sleep(boost::posix_time::seconds(1));
        worker_is_done = true;
        std::cout << "Notifying condition..." << std::endl;
        condition.notify_one();
        std::cout << "Waiting a little more..." << std::endl;
        boost::this_thread::sleep(boost::posix_time::seconds(1));
    }
    
    int main()
    {
        boost::mutex::scoped_lock lock(io_mutex);
        boost::thread workThread(&workFunction);
    
        while (!worker_is_done) condition.wait(lock);
        std::cout << "Condition notified." << std::endl;
        workThread.join();
        std::cout << "Thread finished." << std::endl;
    
        return 0;
    }
    

    Boost condition variable example

    0 讨论(0)
提交回复
热议问题