We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Concurrency with Threads and asyncio step 11 of 56
Build a Blocking Queue with a Condition
Build the buffer that sits between a producer thread and its consumers. The
producer puts items in, and the consumers take them out, oldest first. The
buffer holds at most capacity items, so the producer waits while it is
full, and the consumers wait while it is empty. You are building a small
queue.Queue on top of one threading.Condition.
buffer: BoundedBuffer[int] = BoundedBuffer(2)
buffer.put(1)
buffer.put(2)
buffer.put(3, timeout=0.1) # waits 0.1 s for room, then raises TimeoutError
buffer.get() # returns 1, the oldest item
What to write
Fill in BoundedBuffer[T]:
BoundedBuffer(capacity)raisesValueErrorifcapacityis less than 1.put(item, timeout=None)addsitemat the back. If the buffer is full, it waits for room.get(timeout=None)removes and returns the item at the front. If the buffer is empty, it waits for an item.timeoutis in seconds, andNonemeans wait as long as it takes. If time runs out, raiseTimeoutErrorand leave the buffer as it was.
Follow these rules:
- Create one
threading.Conditionand store it asself._cond. Put every read and change of the buffer insidewith self._cond:. - Wait on the condition. Don't call
time.sleep, and don't usequeue.Queue. - Call
notify_all()after every successfulputandget. Producers and consumers wait for different things, so all of them need a chance to check again. - Annotate the storage, for example
self._items: list[T] = [], so the type checker knows thatgeton aBoundedBuffer[int]returns anint.
Edge cases
- A timeout of zero or less doesn't wait. If
puthas no room right now, orgethas no item, raiseTimeoutError. - With
items=0, only the-1markers pass through, and the consumers must still finish.
What the driver checks
Keep solve as it is. It starts one producer and consumers consumer
threads. The producer puts range(items) into the buffer, then one -1 for
each consumer. A -1 tells a consumer to stop, and your buffer stores it
like any other item. Afterwards, the driver fills the buffer and tries one
more put. Then it empties the buffer and tries one more get. Both extra
calls use a 0.05-second timeout. The report has these keys:
countandchecksumare the number and the sum of the items the consumers received. They must equalitemsandsum(range(items)).in_orderisTruewhen each consumer received its items in increasing order, as a first-in, first-out buffer hands them out.put_timeoutandget_timeoutareTruewhen those two extra calls raisedTimeoutError.sleepscounts calls totime.sleep. It must be 0.uses_conditionisTruewhenself._condis athreading.Condition.
The tests can pass with notify() in place of notify_all(), because the
stall needs unlucky timing. Use notify_all() anyway.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.