diff --git a/core/collection/ring.go b/core/collection/ring.go index 0690fd8f..1c2ab763 100644 --- a/core/collection/ring.go +++ b/core/collection/ring.go @@ -1,8 +1,11 @@ package collection +import "sync" + type Ring struct { elements []interface{} index int + lock sync.Mutex } func NewRing(n int) *Ring { @@ -16,11 +19,16 @@ func NewRing(n int) *Ring { } func (r *Ring) Add(v interface{}) { + r.lock.Lock() + defer r.lock.Unlock() r.elements[r.index%len(r.elements)] = v r.index++ } func (r *Ring) Take() []interface{} { + r.lock.Lock() + defer r.lock.Unlock() + var size int var start int if r.index > len(r.elements) { diff --git a/core/collection/ring_test.go b/core/collection/ring_test.go index 110170e0..8f44c1fd 100644 --- a/core/collection/ring_test.go +++ b/core/collection/ring_test.go @@ -1,6 +1,7 @@ package collection import ( + "sync" "testing" "github.com/stretchr/testify/assert" @@ -29,3 +30,30 @@ func TestRingMore(t *testing.T) { elements := ring.Take() assert.ElementsMatch(t, []interface{}{6, 7, 8, 9, 10}, elements) } + +func BenchmarkRingAdd(b *testing.B) { + ring := NewRing(500) + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + for i := 0; i < b.N; i++ { + ring.Add(i) + } + } + }) +} + +func TestRingAdd(t *testing.T) { + ring := NewRing(5051) + wg := sync.WaitGroup{} + for i := 1; i <= 100; i++ { + wg.Add(1) + go func(i int) { + defer wg.Done() + for j := 1; j <= i; j++ { + ring.Add(i) + } + }(i) + } + wg.Wait() + assert.Equal(t, 5050, len(ring.Take())) +}