samedi 24 janvier 2015

Should a lockfree queue use a condition variable?


Suppose I have a lockfree queue in a multithreaded setting. I already provide a try_dequeue() method which allows for an optional failure (communicated via the return type) if the queue is empty.


I've found it convenient to have an always-succeeding T dequeue() method which will not return while the queue is empty. As a consumer, I don't really care when I get my product, I just want to know as soon as one's available.


My implementation of dequeue() is pretty simple:



while (true) {
if (try_dequeue succeeded) return result;
std::unique_lock<std::mutex> lk(mtx_);
cond_.wait(lk, [this]{ return !empty(); });
}


Where cond_ is signalled by enqueuers and mtx_ guards cond_.


The excess serialization caused by lk seems to slow things down. empty() certainly doesn't need anything to be locked.


In any case, does cond_ seem out of place here? The only reason I'm hesitant to remove it is the case where there's a dequeuer (or multiple dequeuers) that are waiting for a new item to come in and are spinning idly on the CPU with no indication for the enqueuing thread to get priority.


It would seem that perhaps this_thread::yield() is more appropriate here, but the standard only guarantees that the method is a hint, so there is a possibility of starving here.





Aucun commentaire:

Enregistrer un commentaire