A producer thread hands items to a consumer thread through a fixed-size circular buffer. When the buffer is full the producer has to wait (back-pressure); when it's empty the consumer has to wait.
Implement RingBuffer(capacity):
- Store the items in
self.buf, a list of lengthcapacitycreated once in__init__. Track the read position and the number of items yourself, wrapping around with% capacity. Nodeque,queue.Queue,pop(0)or growing the list. put(item): block while the buffer is full, then additemat the back.get(): block while the buffer is empty, then remove and return the item at the front.__len__(): the number of items currently stored.
Items come out in the order they went in. Any value can be an item, including 0 and None.
rb = RingBuffer(2)
rb.put("a"); rb.put("b") # full: a third put() would block
rb.get() # "a", frees a slot
rb.put("c") # goes into slot 0 (wrap-around)
rb.get(), rb.get() # "b", "c"; now empty, so the next get() blocks
Constraints: capacity >= 1. Several producers and consumers may use it at once. Don't sleep or busy-wait.
Show hint
Write to buf[(head + size) % capacity], read from buf[head] and advance head = (head + 1) % capacity; keep size so full (size == capacity) and empty (size == 0) can't be confused, and guard it all with one Condition using wait_for + notify_all.