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