Files
engine/ring.go
李宇翔 a69039bc98 重构
2021-07-03 19:35:46 +08:00

143 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package engine
import (
"container/ring"
"sync"
"sync/atomic"
// "time"
)
type RingItem struct {
Value interface{}
sync.WaitGroup
}
type RingBuffer struct {
*ring.Ring
// UpdateTime time.Time //更新时间,用于计算是否超时
}
// 可释放的Ring用于音视频
type RingDisposable struct {
RingBuffer
Flag int32 // 0:不在写入1正在写入2已销毁
}
// 带锁的Ring用于Hook
// type RingLock struct {
// RingBuffer
// sync.Mutex
// }
// func (r *RingLock) Write(value interface{}) {
// r.Lock()
// r.RingBuffer.Write(value)
// r.Unlock()
// }
// 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)
// r.UpdateTime = time.Now()
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 = r.Clone()
r.Ring = rr
return r
}
func (r *RingBuffer) Write(value interface{}) {
// r.UpdateTime = time.Now()
last := r.Current()
last.Value = value
r.GetNext().Add(1)
last.Done()
}
func (r *RingDisposable) Write(value interface{}) {
// r.UpdateTime = time.Now()
last := r.Current()
last.Value = value
if atomic.CompareAndSwapInt32(&r.Flag, 0, 1) {
current := r.GetNext()
current.Add(1)
last.Done()
//Flag不为1代表被Dispose了但尚未处理Done
if !atomic.CompareAndSwapInt32(&r.Flag, 1, 0) {
current.Done()
}
}
}
func (r *RingDisposable) Step() {
// r.UpdateTime = time.Now()
last := r.Current()
if atomic.CompareAndSwapInt32(&r.Flag, 0, 1) {
current := r.GetNext()
current.Add(1)
last.Done()
//Flag不为1代表被Dispose了但尚未处理Done
if !atomic.CompareAndSwapInt32(&r.Flag, 1, 0) {
current.Done()
}
}
}
func (r *RingBuffer) Read() interface{} {
current := r.Current()
current.Wait()
return current.Value
}
func (r *RingBuffer) CurrentValue() interface{} {
return r.Current().Value
}
func (r *RingBuffer) Current() *RingItem {
return r.Ring.Value.(*RingItem)
}
func (r *RingBuffer) MoveNext() {
r.Ring = r.Next()
}
func (r *RingBuffer) GetNext() *RingItem {
r.Ring = r.Next()
return r.Current()
}
func (r *RingDisposable) Dispose() {
current := r.Current()
if atomic.CompareAndSwapInt32(&r.Flag, 0, 2) {
current.Done()
} else if atomic.CompareAndSwapInt32(&r.Flag, 1, 2) {
//当前是1代表正在写入此时变成2但是Done的任务得交给NextW来处理
} else if atomic.CompareAndSwapInt32(&r.Flag, 0, 2) {
current.Done()
}
}
// // Timeout 发布者是否超时了
// func (r *RingBuffer) Timeout(t time.Duration) bool {
// // 如果设置为0则表示永不超时
// if t == 0 {
// return false
// }
// return time.Since(r.UpdateTime) > t
// }