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{} }