I need to set up a producer-consumer scheme with two threads linked by a queue (the producer pushing tasks into the queue, the consumer executing them as they come).
Since the queue will be empty most of the time I must make it so that the consumer thread can sleep and be woken up as soon as something is pushed by the producer. However I must ensure that the producer is never blocked, not even shortly. In other words, I need some one-sided blocking queue.
There are lock free queues, but since those are by definition, well, lock free, it isn't possible for the consumer thread to be blocked by them.
I have thought of associating a lock free queue with a condition variable. When the consumer thread finds the queue empty it would sleep waiting for the condition to be notified. The producer thread would notify the condition when pushing a task into the queue waking up the consumer thread (if it was sleeping). However, condition variable must be protected by mutex, that mean there is still a small chance for the producer thread to be blocked when trying to acquire it to notify the condition.
I have yet to find a really good way to solve this problem so your ideas are more then welcome.
Note : I'm planning to use boost thread to implement this.
Note 2 : I'm not considering the case where the producer trys to push something and the queue is full. This is never going to happen.
Blocking vs Non-Blocking QueueThe producers will wait for available capacity before adding elements, while consumers will wait until the queue is empty. In those cases, the non-blocking queue will either throw an exception or return a special value, like null or false.
concurrent. BlockingQueue is a java Queue that support operations that wait for the queue to become non-empty when retrieving and removing an element, and wait for space to become available in the queue when adding an element.
Synchronous queues are similar to rendezvous channels used in CSP and Ada. They are well suited for handoff designs, in which an object running in one thread must sync up with an object running in another thread in order to hand it some information, event, or task.
ArrayBlockingQueue is bounded which means the size will never change after its creation. LinkedBlockingQueue is optionally bounded which means it can optionally have an upper bound if desired.
tbb library provides both blocking and non-blocking queues:
try_pop()
and push()
for unlimited growth.push()
which can block if capacity limit is specified and when it is reached; and pop()
which waits for items in empty queue. It also provides non-blocking try_push()
and try_pop()
alternatives for the same queue.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With