As per documentation, rb.Offer should return false only when the queue is full:
// Offer adds the provided item to the queue if there is space. If the queue
// is full, this call will return false. An error will be returned if the
// queue is disposed.
func (rb *RingBuffer) Offer(item interface{}) (bool, error) {
return rb.put(item, true)
}
But, when adding elements to queue by concurrently calling rb.Offer, It returns false even when there is enough space.
The following test file can reproduce the issue.
package test
import (
"sync"
"testing"
"github.com/Workiva/go-datastructures/queue"
)
func TestRingQueueOffer_parallel(t *testing.T) {
size := 256
parallelGoroutines := 8
rb := queue.NewRingBuffer(uint64(size * parallelGoroutines))
wg := new(sync.WaitGroup)
wg.Add(parallelGoroutines)
for i := 0; i < parallelGoroutines; i++ {
go func(id int) {
defer wg.Done()
for el := 1; el <= size; el++ {
ok, err := rb.Offer(el)
if err != nil {
t.Errorf("error in goroutine-%d: %v", id, err)
return
}
if !ok {
t.Errorf("queue full before expected on adding %d element, len: %d, cap: %d ", el, rb.Len(), rb.Cap())
}
}
}(i)
}
wg.Wait()
}
On running the above test file, I got:
--- FAIL: TestRingQueueOffer_parallel (0.00s)
ring_buffer_test.go:31: queue full before expected on adding 1 element, len: 49, cap: 2048
ring_buffer_test.go:31: queue full before expected on adding 256 element, len: 1391, cap: 2048
ring_buffer_test.go:31: queue full before expected on adding 1 element, len: 1730, cap: 2048
FAIL
FAIL command-line-arguments 0.028s
FAIL
As per documentation,
rb.Offer
should return false only when the queue is full:But, when adding elements to queue by concurrently calling
rb.Offer
, It returns false even when there is enough space. The following test file can reproduce the issue.On running the above test file, I got: