diff --git a/container/gring/gring.go b/container/gring/gring.go index ac308f56c..9114558c4 100644 --- a/container/gring/gring.go +++ b/container/gring/gring.go @@ -23,6 +23,11 @@ type Ring struct { dirty *gtype.Bool // Dirty, which means the len and cap should be recalculated. It's marked dirty when the size of ring changes. } +// internalRingItem stores the ring element value. +type internalRingItem struct { + Value interface{} +} + // New creates and returns a Ring structure of elements. // The optional parameter specifies whether using this structure in concurrent safety, // which is false in default. @@ -38,10 +43,13 @@ func New(cap int, safe ...bool) *Ring { // Val returns the item's value of current position. func (r *Ring) Val() interface{} { + var value interface{} r.mu.RLock() - v := r.ring.Value + if r.ring.Value != nil { + value = r.ring.Value.(internalRingItem).Value + } r.mu.RUnlock() - return v + return value } // Len returns the size of ring. @@ -61,17 +69,21 @@ func (r *Ring) checkAndUpdateLenAndCap() { if !r.dirty.Val() { return } + r.mu.RLock() + defer r.mu.RUnlock() totalLen := 0 emptyLen := 0 if r.ring != nil { - r.mu.RLock() + if r.ring.Value == nil { + emptyLen++ + } + totalLen++ for p := r.ring.Next(); p != r.ring; p = p.Next() { if p.Value == nil { emptyLen++ } totalLen++ } - r.mu.RUnlock() } r.cap.Set(totalLen) r.len.Set(totalLen - emptyLen) @@ -84,18 +96,18 @@ func (r *Ring) Set(value interface{}) *Ring { if r.ring.Value == nil { r.len.Add(1) } - r.ring.Value = value + r.ring.Value = internalRingItem{Value: value} r.mu.Unlock() return r } -// Put sets to current item of ring and moves position to next item. +// Put sets `value` to current item of ring and moves position to next item. func (r *Ring) Put(value interface{}) *Ring { r.mu.Lock() if r.ring.Value == nil { r.len.Add(1) } - r.ring.Value = value + r.ring.Value = internalRingItem{Value: value} r.ring = r.ring.Next() r.mu.Unlock() return r @@ -132,8 +144,8 @@ func (r *Ring) Next() *Ring { // // If r and s point to the same ring, linking // them removes the elements between r and s from the ring. -// The removed elements form a subring and the result is a -// reference to that subring (if no elements were removed, +// The removed elements form a sub-ring and the result is a +// reference to that sub-ring (if no elements were removed, // the result is still the original value for r.Next(), // and not nil). // @@ -155,7 +167,7 @@ func (r *Ring) Link(s *Ring) *Ring { // Unlink removes n % r.Len() elements from the ring r, starting // at r.Next(). If n % r.Len() == 0, r remains unchanged. -// The result is the removed subring. r must not be empty. +// The result is the removed sub-ring. r must not be empty. // func (r *Ring) Unlink(n int) *Ring { r.mu.Lock() @@ -166,56 +178,24 @@ func (r *Ring) Unlink(n int) *Ring { } // RLockIteratorNext iterates and locks reading forward -// with given callback function within RWMutex.RLock. -// If returns true, then it continues iterating; or false to stop. +// with given callback function `f` within RWMutex.RLock. +// If `f` returns true, then it continues iterating; or false to stop. func (r *Ring) RLockIteratorNext(f func(value interface{}) bool) { r.mu.RLock() defer r.mu.RUnlock() - if !f(r.ring.Value) { + if r.ring.Value != nil && !f(r.ring.Value.(internalRingItem).Value) { return } for p := r.ring.Next(); p != r.ring; p = p.Next() { - if !f(p.Value) { - break - } - } -} - -// RLockIteratorPrev iterates and locks reading backward -// with given callback function within RWMutex.RLock. -// If returns true, then it continues iterating; or false to stop. -func (r *Ring) RLockIteratorPrev(f func(value interface{}) bool) { - r.mu.RLock() - defer r.mu.RUnlock() - if !f(r.ring.Value) { - return - } - for p := r.ring.Prev(); p != r.ring; p = p.Prev() { - if !f(p.Value) { - break - } - } -} - -// LockIteratorNext iterates and locks writing forward -// with given callback function within RWMutex.RLock. -// If returns true, then it continues iterating; or false to stop. -func (r *Ring) LockIteratorNext(f func(item *ring.Ring) bool) { - r.mu.RLock() - defer r.mu.RUnlock() - if !f(r.ring) { - return - } - for p := r.ring.Next(); p != r.ring; p = p.Next() { - if !f(p) { + if p.Value == nil || !f(p.Value.(internalRingItem).Value) { break } } } // LockIteratorPrev iterates and locks writing backward -// with given callback function within RWMutex.RLock. -// If returns true, then it continues iterating; or false to stop. +// with given callback function `f` within RWMutex.RLock. +// If `f` returns true, then it continues iterating; or false to stop. func (r *Ring) LockIteratorPrev(f func(item *ring.Ring) bool) { r.mu.RLock() defer r.mu.RUnlock() @@ -234,12 +214,13 @@ func (r *Ring) SliceNext() []interface{} { s := make([]interface{}, 0) r.mu.RLock() if r.ring.Value != nil { - s = append(s, r.ring.Value) + s = append(s, r.ring.Value.(internalRingItem).Value) } for p := r.ring.Next(); p != r.ring; p = p.Next() { - if p.Value != nil { - s = append(s, p.Value) + if p.Value == nil { + break } + s = append(s, p.Value.(internalRingItem).Value) } r.mu.RUnlock() return s @@ -250,12 +231,13 @@ func (r *Ring) SlicePrev() []interface{} { s := make([]interface{}, 0) r.mu.RLock() if r.ring.Value != nil { - s = append(s, r.ring.Value) + s = append(s, r.ring.Value.(internalRingItem).Value) } for p := r.ring.Prev(); p != r.ring; p = p.Prev() { - if p.Value != nil { - s = append(s, p.Value) + if p.Value == nil { + break } + s = append(s, p.Value.(internalRingItem).Value) } r.mu.RUnlock() return s diff --git a/container/gring/gring_unit_test.go b/container/gring/gring_unit_test.go index 706f273a3..a226b10d2 100644 --- a/container/gring/gring_unit_test.go +++ b/container/gring/gring_unit_test.go @@ -7,7 +7,6 @@ package gring_test import ( - "container/ring" "testing" "github.com/gogf/gf/container/gring" @@ -44,6 +43,11 @@ func TestRing_Val(t *testing.T) { }) } func TestRing_CapLen(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + r := gring.New(10) + t.Assert(r.Cap(), 10) + t.Assert(r.Len(), 0) + }) gtest.C(t, func(t *gtest.T) { r := gring.New(10) r.Put("goframe") @@ -81,22 +85,22 @@ func TestRing_Link(t *testing.T) { rs := r.Link(s) t.Assert(rs.Move(2).Val(), "b") - }) } func TestRing_Unlink(t *testing.T) { gtest.C(t, func(t *gtest.T) { r := gring.New(5) - for i := 0; i < 5; i++ { - r.Put(i + 1) + for i := 1; i <= 5; i++ { + r.Put(i) } + t.Assert(r.Val(), 1) // 1 2 3 4 // 删除当前位置往后的2个数据,返回被删除的数据 // 重新计算s len s := r.Unlink(2) // 2 3 t.Assert(s.Val(), 2) - t.Assert(s.Len(), 1) + t.Assert(s.Len(), 2) }) } @@ -120,10 +124,10 @@ func TestRing_Slice(t *testing.T) { r.Set(nil) array2 := r.SliceNext() //[4 5 1 2] //返回当前位置往后不为空的元素数组,长度为4 - t.Assert(array2, g.Slice{4, 5, 1, 2}) + t.Assert(array2, g.Slice{nil, 4, 5, 1, 2}) array3 := r.SlicePrev() //[2 1 5 4] - t.Assert(array3, g.Slice{2, 1, 5, 4}) + t.Assert(array3, g.Slice{nil, 2, 1, 5, 4}) s := gring.New(ringLen) for i := 0; i < ringLen; i++ { @@ -131,106 +135,5 @@ func TestRing_Slice(t *testing.T) { } array4 := s.SlicePrev() // [] t.Assert(array4, g.Slice{1, 5, 4, 3, 2}) - - }) -} - -func TestRing_RLockIterator(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - ringLen := 5 - r := gring.New(ringLen) - - //ring不存在有值元素 - r.RLockIteratorNext(func(v interface{}) bool { - t.Assert(v, nil) - return false - }) - r.RLockIteratorNext(func(v interface{}) bool { - t.Assert(v, nil) - return true - }) - - r.RLockIteratorPrev(func(v interface{}) bool { - t.Assert(v, nil) - return true - }) - - for i := 0; i < ringLen; i++ { - r.Put(i + 1) - } - - //回调函数返回true,RLockIteratorNext遍历5次,期望值分别是1、2、3、4、5 - i := 0 - r.RLockIteratorNext(func(v interface{}) bool { - t.Assert(v, i+1) - i++ - return true - }) - - //RLockIteratorPrev遍历1次返回 false,退出遍历 - r.RLockIteratorPrev(func(v interface{}) bool { - t.Assert(v, 1) - return false - }) - - }) -} - -func TestRing_LockIterator(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - ringLen := 5 - r := gring.New(ringLen) - - //不存在有值元素 - r.LockIteratorNext(func(item *ring.Ring) bool { - t.Assert(item.Value, nil) - return false - }) - r.LockIteratorNext(func(item *ring.Ring) bool { - t.Assert(item.Value, nil) - return false - }) - r.LockIteratorNext(func(item *ring.Ring) bool { - t.Assert(item.Value, nil) - return true - }) - - r.LockIteratorPrev(func(item *ring.Ring) bool { - t.Assert(item.Value, nil) - return false - }) - r.LockIteratorPrev(func(item *ring.Ring) bool { - t.Assert(item.Value, nil) - return true - }) - - //ring初始化元素值 - for i := 0; i < ringLen; i++ { - r.Put(i + 1) - } - - //往后遍历组成数据 [1,2,3,4,5] - array1 := g.Slice{1, 2, 3, 4, 5} - ii := 0 - r.LockIteratorNext(func(item *ring.Ring) bool { - //校验每一次遍历取值是否是期望值 - t.Assert(item.Value, array1[ii]) - ii++ - return true - }) - - //往后取3个元素组成数组 - //获得 [1,5,4] - i := 0 - a := g.Slice{1, 5, 4} - r.LockIteratorPrev(func(item *ring.Ring) bool { - if i > 2 { - return false - } - t.Assert(item.Value, a[i]) - i++ - return true - }) - }) }