// lesson: channel-semaphores
Backpressure by Construction
A buffered channel is a semaphore: capacity = permits, send = acquire, receive = release. That makes a bounded blocking queue the most honest data structure in concurrent programming โ when the consumer falls behind, the producer physically stops. No unbounded slices quietly eating your heap.
The hard part is never the happy path; it's shutdown. Three rules make a closeable queue coherent:
- Only the closer decides "no more input".
Putafter close is an error, and aPutblocked at close time must wake up and get that error too. - Items already accepted are owed to consumers: after close,
Getdrains whatever remains before reporting "done". - Every blocked party must be woken by
Close. Forget one waiter and you have a goroutine leak that only shows up in production.
You can build this on channels plus a done-channel, or on sync.Mutex +
sync.Cond (two conditions: "not full" and "not empty"; re-check the
predicate in a loop after every Wait; Broadcast on close). Both work.
Pick one and get the edge cases right.
โบ Bounded Blocking Queue
30 ptsImplement a generic FIFO queue:
var ErrClosed = errors.New("queue: closed") // keep this exported variable
func NewQueue[T any](capacity int) *Queue[T]
func (q *Queue[T]) Put(v T) error
func (q *Queue[T]) Get() (T, bool)
func (q *Queue[T]) Close()
Required semantics (capacity is always >= 1 in the tests; Close is called
at most once):
Putblocks while the queue holdscapacityitems. It returnsnilon success andErrClosedif the queue is closed โ including when the call was already blocked on a full queue whenClosehappened.Getblocks while the queue is empty and open. It returns(item, true)in FIFO order; afterCloseit keeps returning buffered items until the queue is drained, then returns(zero, false). AGetblocked on an empty queue whenClosehappens returns(zero, false).Closewakes every blockedPutandGet. Nothing stays parked.- Everything must be safe under many concurrent producers and consumers.
Log in to submit a solution and earn points.