Files
engine/ring.go
2021-07-16 16:13:10 +08:00

121 lines
2.3 KiB
Go

package engine
import (
"container/ring"
"reflect"
"sync"
// "time"
)
type RingItem struct {
Value interface{}
sync.WaitGroup
}
type RingBuffer struct {
*ring.Ring
}
// TODO: 池化,泛型
func NewRingBuffer(n int) (r *RingBuffer) {
r = new(RingBuffer)
r.Init(n)
return
}
func (r *RingBuffer) Init(n int) {
r.Ring = ring.New(n)
for x := r.Ring; x.Value == nil; x = x.Next() {
x.Value = new(RingItem)
}
r.Current().Add(1)
}
func (rb RingBuffer) Clone() *RingBuffer {
return &rb
}
func (r RingBuffer) SubRing(rr *ring.Ring) *RingBuffer {
r.Ring = rr
return &r
}
func (r *RingBuffer) Write(value interface{}) {
last := r.Current()
last.Value = value
r.GetNext().Add(1)
last.Done()
}
func (r *RingBuffer) read() reflect.Value {
current := r.Current()
current.Wait()
return reflect.ValueOf(current.Value)
}
func (r *RingBuffer) nextRead() reflect.Value {
r.MoveNext()
return r.read()
}
func (r *RingBuffer) CurrentValue() interface{} {
return r.Current().Value
}
func (r *RingBuffer) NextValue() interface{} {
return r.Next().Value.(*RingItem).Value
}
func (r *RingBuffer) Current() *RingItem {
return r.Ring.Value.(*RingItem)
}
func (r *RingBuffer) MoveNext() {
r.Ring = r.Next()
}
func (r *RingBuffer) NextRead() interface{} {
r.MoveNext()
return r.Read()
}
func (r *RingBuffer) GetNext() *RingItem {
r.MoveNext()
return r.Current()
}
func (r *RingBuffer) Read() interface{} {
current := r.Current()
current.Wait()
return current.Value
}
// ReadLoop 循环读取,采用了反射机制,不适用高性能场景
// handler入参可以传入回调函数或者channel
func (r *RingBuffer) ReadLoop(handler interface{}) {
switch t := reflect.ValueOf(handler); t.Kind() {
case reflect.Chan:
for v := r.read(); ; v = r.nextRead() {
t.Send(v)
}
case reflect.Func:
for args := []reflect.Value{r.read()}; ; args[0] = r.nextRead() {
t.Call(args)
}
}
}
// goon判断函数用来判断是否继续读取,返回false将终止循环
func (r *RingBuffer) ReadLoopConditional(handler interface{}, goon func() bool) {
switch t := reflect.ValueOf(handler); t.Kind() {
case reflect.Chan:
for v := r.read(); goon(); v = r.nextRead() {
t.Send(v)
}
case reflect.Func:
for args := []reflect.Value{r.read()}; goon(); args[0] = r.nextRead() {
t.Call(args)
}
}
}