81 lines
1.3 KiB
Go
81 lines
1.3 KiB
Go
package comet
|
|
|
|
import (
|
|
"gitlab.33.cn/chat/im/api/comet/grpc"
|
|
"gitlab.33.cn/chat/im/comet/errors"
|
|
)
|
|
|
|
// Ring ring proto buffer.
|
|
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 []grpc.Proto
|
|
}
|
|
|
|
// NewRing new a ring buffer.
|
|
func NewRing(num int) *Ring {
|
|
r := new(Ring)
|
|
r.init(uint64(num))
|
|
return r
|
|
}
|
|
|
|
// Init init ring.
|
|
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([]grpc.Proto, num)
|
|
r.num = num
|
|
r.mask = r.num - 1
|
|
}
|
|
|
|
// Get get a proto from ring.
|
|
func (r *Ring) Get() (proto *grpc.Proto, err error) {
|
|
if r.rp == r.wp {
|
|
return nil, errors.ErrRingEmpty
|
|
}
|
|
proto = &r.data[r.rp&r.mask]
|
|
return
|
|
}
|
|
|
|
// GetAdv incr read index.
|
|
func (r *Ring) GetAdv() {
|
|
r.rp++
|
|
}
|
|
|
|
// Set get a proto to write.
|
|
func (r *Ring) Set() (proto *grpc.Proto, err error) {
|
|
if r.wp-r.rp >= r.num {
|
|
return nil, errors.ErrRingFull
|
|
}
|
|
proto = &r.data[r.wp&r.mask]
|
|
return
|
|
}
|
|
|
|
// SetAdv incr write index.
|
|
func (r *Ring) SetAdv() {
|
|
r.wp++
|
|
}
|
|
|
|
// Reset reset ring.
|
|
func (r *Ring) Reset() {
|
|
r.rp = 0
|
|
r.wp = 0
|
|
// prevent pad compiler optimization
|
|
// r.pad = [40]byte{}
|
|
}
|