← All tasks Task 7 of 12 unsolved

7. Bounded Queue (Producer-Consumer)

Data Structures Backpressure ~20 min

Implement a fixed-capacity FIFO queue. Without a bound, a fast producer can fill heap before consumers keep up — that's how OOMs happen in pipelines. Bounded queues are the simplest backpressure primitive.

This non-blocking variant is the building block for the producer/consumer stages in a streaming masker — a real implementation adds await/signal, but the storage shape is the same.

Tests this task must pass

  1. FIFO order — three puts (1, 2, 3) then three takes return 1, 2, 3 in that order.
  2. Capacity enforced — third put on a 2-slot queue returns false rather than overflowing.
  3. Empty behaviour — fresh queue is isEmpty; take() on empty returns null (not throw).
  4. Size trackingsize reflects each put/take immediately.
  5. Fill and drain — full queue reports isFull; after draining all elements in order, queue is isEmpty.
//sampleStart class BoundedQueue<T>(private val capacity: Int) { // Implement a fixed-capacity FIFO queue // put(item): add to tail. If full → return false // take(): remove from head. If empty → return null // size, isEmpty, isFull properties fun put(item: T): Boolean { TODO() } fun take(): T? { TODO() } val size: Int get() = TODO() val isEmpty: Boolean get() = TODO() val isFull: Boolean get() = TODO() } //sampleEnd fun main() { // Test 1: Basic put/take val q = BoundedQueue<Int>(5) q.put(1); q.put(2); q.put(3) check(q.take() == 1) { "FAIL: FIFO — first in first out" } check(q.take() == 2) { "FAIL: FIFO" } check(q.take() == 3) { "FAIL: FIFO" } println("✅ Test 1: FIFO order") // Test 2: Capacity val q2 = BoundedQueue<String>(2) check(q2.put("a")) { "FAIL: should accept" } check(q2.put("b")) { "FAIL: should accept" } check(!q2.put("c")) { "FAIL: queue full, should reject" } println("✅ Test 2: Capacity enforced") // Test 3: Empty val q3 = BoundedQueue<Int>(3) check(q3.isEmpty) { "FAIL: new queue is empty" } check(q3.take() == null) { "FAIL: take from empty returns null" } println("✅ Test 3: Empty queue") // Test 4: Size tracking val q4 = BoundedQueue<Int>(10) q4.put(1); q4.put(2); q4.put(3) check(q4.size == 3) { "FAIL: size should be 3" } q4.take() check(q4.size == 2) { "FAIL: size should be 2 after take" } println("✅ Test 4: Size tracking") // Test 5: Fill and drain val q5 = BoundedQueue<Int>(3) q5.put(10); q5.put(20); q5.put(30) check(q5.isFull) { "FAIL: should be full" } check(q5.take() == 10 && q5.take() == 20 && q5.take() == 30) { "FAIL: drain order" } check(q5.isEmpty) { "FAIL: should be empty after drain" } println("✅ Test 5: Fill and drain") println("\n🎉 ALL TESTS PASSED!") }
← Previous Next: Transformer Registry →