88 lines
1.4 KiB
Go
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{}
|
|
}
|