mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 11:18:02 +08:00
improve package gring; remove function LockIteratorNext/LockIteratorPrev from package gring
This commit is contained in:
parent
727f58a24b
commit
cc08ceb797
@ -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 <cap> elements.
|
||||
// The optional parameter <safe> 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 <value> 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 <f> within RWMutex.RLock.
|
||||
// If <f> 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 <f> within RWMutex.RLock.
|
||||
// If <f> 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 <f> within RWMutex.RLock.
|
||||
// If <f> 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 <f> within RWMutex.RLock.
|
||||
// If <f> 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
|
||||
|
@ -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
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user