Skip to main content
WaitableQueue is a concurrency-safe, unbounded FIFO queue designed for producer-consumer patterns where Go channels are inconvenient — for example, when you need flow control without the hard capacity limits of a buffered channel, or when the number of producers and consumers is dynamic.

When to use WaitableQueue vs Queue

Installation

Constructor

int
required
Pre-allocates internal storage for this many elements. Must be ≥ 0.
int
required
The queue depth below which Dequeue reports QueueIsBelowLowWatermark. Must be ≥ 0.
int
required
The queue depth at or above which Enqueue and Dequeue report QueueIsAboveHighWatermark. Must be ≥ lowWatermark.

Error cases

The constructor returns an error for invalid arguments:

Interface

Enqueue

Appends an element to the back of the queue and returns the current WaitableQueueState. Panics if called after Close().
Most callers can ignore the return value. The most common reason to check it is to detect QueueIsNearSaturation and throttle the producer.

Dequeue

Removes and returns the front element. If the queue is empty, ok is false, e is the zero value, and result is QueueIsBelowLowWatermark.

WaitChan

Returns a channel that receives a signal when an item may be available or when the queue has been closed. Use this in a select statement to avoid busy-polling. After receiving on this channel, always call Dequeue in a loop until ok is false — a single signal may correspond to multiple enqueued items.

Close

Marks the queue as closed and permanently unblocks every goroutine waiting on WaitChan. Once closed, calling Enqueue panics. You should drain any remaining items with Dequeue after Close returns. In most cases, Close should be called only by the producer.

Queue states

WaitableQueueState is returned by Enqueue and Dequeue to describe the current depth of the queue relative to the watermarks you configured.

Producer-consumer pattern

The typical pattern is one or more producer goroutines calling Enqueue, and one or more consumer goroutines selecting on WaitChan and then draining with Dequeue.

Flow control with WaitChan

Use the state returned by Dequeue to scale consumers dynamically:
Do not use QueueIsBelowLowWatermark from Enqueue as a resume signal for a throttled producer. If the producer has stopped enqueuing entirely, it will never observe that state, and it will never unthrottle. Use the Dequeue/WaitChan side for flow control instead.
WaitableQueue is concurrency-safe. Its Len() method (if called) is not atomic with respect to Enqueue/Dequeue and should only be used for observability or debugging, not for control flow decisions.