vendredi 30 mars 2018

c++ 11 condition_variable wait spurious wake up is not working

I tried to write a simple producer/consumer by using condition_variable,

include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <queue>
#include <chrono>
using namespace std;

condition_variable cond_var;
mutex m;
int main()
{
    int c = 0;
    bool done = false;
    cout << boolalpha;
    queue<int> goods;

    thread producer([&](){
        for (int i = 0; i < 10; ++i) {
            m.lock();
            goods.push(i);
            c++;
            cout << "produce " << i << endl;
            m.unlock();
            cond_var.notify_one();
            this_thread::sleep_for(chrono::milliseconds(100));
        }
        done = true;
        cout << "producer done." << endl;
        cond_var.notify_one();
    });

    thread consumer([&](){
        unique_lock<mutex> lock(m);
        while(!done || !goods.empty()){
            /*
            cond_var.wait(lock, [&goods, &done](){
                        cout << "spurious wake check" << done <<endl;
                        return (!goods.empty() || done);
            });
            */  
            while(goods.empty())
            {
                cout<< "consumer wait" <<endl;
                cout<< "consumer owns lock " << lock.owns_lock() <<endl;
                cond_var.wait(lock);
            }
            if (!goods.empty()){
                cout << "consume " << goods.front()<<endl;
                goods.pop();
                c--;
            }
        }
    });

    producer.join();
    consumer.join();
    cout << "Net: " << c << endl;
}

The problem I have now is when the consumer consumes the last item before the product set done to true, the consumer thread will stuck in

 while(goods.empty())
            {
                cout<< "consumer wait" <<endl;
                cout<< "consumer owns lock " << lock.owns_lock() <<endl;
                cond_var.wait(lock);
            }

My understanding is cond_var.wait(lock) will wake up spuriously and thus exit the while(good.empty()) loop, but it seems not the case?

Aucun commentaire:

Enregistrer un commentaire