~/problems / Pools & pipelines / Ring buffers and producer/consumer pipelines

Producer-consumer with backpressure

On a phone? Coding is easier on a laptop: email this problem to yourself . Meanwhile: quiz this topic or fight a boss.

medium assessment 4 levels ~50 min

Level 1 Workers on a shared queue

A photo service gets uploads faster than it can resize them. Uploads go into a queue, and a few worker threads take them off and do the slow work.

class Pipeline:
    def __init__(self, n_workers: int, handler): ...
    def submit(self, item: int) -> None: ...
    def wait_idle(self) -> None: ...
  • The constructor starts n_workers worker threads (make them daemon threads).
  • submit(item) puts item at the back of a FIFO queue and returns at once. Many threads may call it at the same time.
  • Each worker repeatedly takes the item at the front of the queue and calls handler(item). Up to n_workers items are handled at the same time, and every item is handled exactly once.
  • wait_idle() blocks until the queue is empty and no worker is in the middle of an item.
  • Don't hold your lock while calling handler: it's slow, and the other workers must keep going.

Build the queue yourself from a collections.deque and a threading.Condition (no queue.Queue). Idle workers sleep in wait(); no polling or sleeping in a loop.

done = []
p = Pipeline(1, done.append)
for x in [3, 1, 2]:
    p.submit(x)
p.wait_idle()
done   # [3, 1, 2]: one worker takes the items in order

1 <= n_workers <= 16. The tests submit a few thousand items from several threads at once.

Show hint

a worker holds the lock only to pop an item and count itself busy, then lets go before calling handler. Keep a busy count next to the deque so wait_idle knows about items that have left the queue but aren't finished.

Level 2 unlocks when level 1 passes.

Level 3 unlocks when level 2 passes.

Level 4 unlocks when level 3 passes.

Topic: Ring buffers and producer/consumer pipelines. Fixed-size circular buffers, head/tail indexes, back-pressure.

Read the visual guide
0:00
Ctrl ' run · Ctrl ↵ submit
esc