go-common/app/interface/main/broadcast/server/ring.go
2019-04-22 18:49:16 +08:00

88 lines
1.4 KiB
Go

package server
import (
"go-common/app/interface/main/broadcast/conf"
"go-common/app/service/main/broadcast/model"
"go-common/library/log"
)
// Ring .
type Ring struct {
// read
rp uint64
num uint64
mask uint64
// TODO split cacheline, many cpu cache line size is 64
// pad [40]byte
// write
wp uint64
data []model.Proto
}
// NewRing .
func NewRing(num int) *Ring {
r := new(Ring)
r.init(uint64(num))
return r
}
// Init .
func (r *Ring) Init(num int) {
r.init(uint64(num))
}
func (r *Ring) init(num uint64) {
// 2^N
if num&(num-1) != 0 {
for num&(num-1) != 0 {
num &= (num - 1)
}
num = num << 1
}
r.data = make([]model.Proto, num)
r.num = num
r.mask = r.num - 1
}
// Get .
func (r *Ring) Get() (proto *model.Proto, err error) {
if r.rp == r.wp {
return nil, ErrRingEmpty
}
proto = &r.data[r.rp&r.mask]
return
}
// GetAdv .
func (r *Ring) GetAdv() {
r.rp++
if conf.Conf.Broadcast.Debug {
log.Info("ring rp: %d, idx: %d", r.rp, r.rp&r.mask)
}
}
// Set .
func (r *Ring) Set() (proto *model.Proto, err error) {
if r.wp-r.rp >= r.num {
return nil, ErrRingFull
}
proto = &r.data[r.wp&r.mask]
return
}
// SetAdv .
func (r *Ring) SetAdv() {
r.wp++
if conf.Conf.Broadcast.Debug {
log.Info("ring wp: %d, idx: %d", r.wp, r.wp&r.mask)
}
}
// Reset .
func (r *Ring) Reset() {
r.rp = 0
r.wp = 0
// prevent pad compiler optimization
// r.pad = [40]byte{}
}