diff --git a/queue/ring.go b/queue/ring.go index ed1de3c..4431773 100644 --- a/queue/ring.go +++ b/queue/ring.go @@ -61,6 +61,14 @@ type RingBuffer struct { } func (rb *RingBuffer) init(size uint64) { + if size == 1 { + // The mask must be a value containing only 1s (left padded with zeros) in its binary + // format (e.g. 0001, 0011, 0111, 1111, and etc.) + // With a size of 1 the mask would be 0 which then in case of having a full queue the + // single item in the ring buffer gets replaced with every insert operation which also makes + // rb.Get() to block since the ring buffer's state becomes invalid despite having a full queue. + size = 2 + } size = roundUp(size) rb.nodes = make(nodes, size) for i := uint64(0); i < size; i++ { diff --git a/queue/ring_test.go b/queue/ring_test.go index 21b020c..5b40728 100644 --- a/queue/ring_test.go +++ b/queue/ring_test.go @@ -25,6 +25,36 @@ import ( "github.com/stretchr/testify/assert" ) +func TestRingInsertWithCapOne(t *testing.T) { + rb := NewRingBuffer(1) + assert.Equal(t, uint64(2), rb.Cap()) + + err := rb.Put("Hello") + if !assert.Nil(t, err) { + return + } + + err = rb.Put("World") + if !assert.Nil(t, err) { + return + } + + ok, err := rb.Offer("Hello, Again.") + assert.Nil(t, err) + assert.False(t, ok) + + result, err := rb.Get() + if !assert.Nil(t, err) { + return + } + if !assert.NotNil(t, result) { + return + } + assert.Equal(t, result, "Hello") + + assert.Equal(t, uint64(1), rb.Len()) +} + func TestRingInsert(t *testing.T) { rb := NewRingBuffer(5) assert.Equal(t, uint64(8), rb.Cap())