123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- package backable_ringbuffer
- import (
- "errors"
- "unsafe"
- )
- var (
- ErrTooManyDataToWrite = errors.New("too many data to write")
- ErrIsFull = errors.New("ringbuffer is full")
- ErrIsEmpty = errors.New("ringbuffer is empty")
- ErrOutOfRange = errors.New("index out of range")
- ErrAccuqireLock = errors.New("no lock to accquire")
- )
- type BackableRingBuffer struct {
- buf []byte
- size int
- r int // next position to read
- w int // next position to write
- isFull bool
- mu Mutex
- }
- func NewBackableRingBuffer(size int) *BackableRingBuffer {
- b := &BackableRingBuffer{
- size: size,
- buf: make([]byte, size),
- }
- return b
- }
- func (r *BackableRingBuffer) Read(p []byte) (n int, err error) {
- if len(p) == 0 {
- return 0, nil
- }
- r.mu.Lock()
- n, err = r.read(p)
- r.mu.Unlock()
- return n, err
- }
- func (r *BackableRingBuffer) Peep(p []byte) (n int, err error) {
- if len(p) == 0 {
- return 0, nil
- }
- r.mu.Lock()
- n, err = r.peep(p)
- r.mu.Unlock()
- return n, err
- }
- func (r *BackableRingBuffer) TryRead(p []byte) (n int, err error) {
- if len(p) == 0 {
- return 0, nil
- }
- ok := r.mu.TryLock()
- if !ok {
- return 0, ErrAccuqireLock
- }
- n, err = r.read(p)
- r.mu.Unlock()
- return n, err
- }
- func (r *BackableRingBuffer) TryPeep(p []byte) (n int, err error) {
- if len(p) == 0 {
- return 0, nil
- }
- ok := r.mu.TryLock()
- if !ok {
- return 0, ErrAccuqireLock
- }
- n, err = r.peep(p)
- r.mu.Unlock()
- return n, err
- }
- func (r *BackableRingBuffer) read(p []byte) (n int, err error) {
- if r.w == r.r && !r.isFull {
- return 0, ErrIsEmpty
- }
- if r.w > r.r {
- n = r.w - r.r
- if n > len(p) {
- n = len(p)
- }
- copy(p, r.buf[r.r:r.r+n])
- r.r = (r.r + n) % r.size
- return
- }
- n = r.size - r.r + r.w
- if n > len(p) {
- n = len(p)
- }
- if r.r+n <= r.size {
- copy(p, r.buf[r.r:r.r+n])
- } else {
- c1 := r.size - r.r
- copy(p, r.buf[r.r:r.size])
- c2 := n - c1
- copy(p[c1:], r.buf[0:c2])
- }
- r.r = (r.r + n) % r.size
- r.isFull = false
- return n, err
- }
- func (r *BackableRingBuffer) peep(p []byte) (n int, err error) {
- if r.w == r.r && !r.isFull {
- return 0, ErrIsEmpty
- }
- if r.w > r.r {
- n = r.w - r.r
- if n > len(p) {
- n = len(p)
- }
- copy(p, r.buf[r.r:r.r+n])
- return
- }
- n = r.size - r.r + r.w
- if n > len(p) {
- n = len(p)
- }
- if r.r+n <= r.size {
- copy(p, r.buf[r.r:r.r+n])
- } else {
- c1 := r.size - r.r
- copy(p, r.buf[r.r:r.size])
- c2 := n - c1
- copy(p[c1:], r.buf[0:c2])
- }
- return n, err
- }
- func (r *BackableRingBuffer) ReadByte() (b byte, err error) {
- r.mu.Lock()
- if r.w == r.r && !r.isFull {
- r.mu.Unlock()
- return 0, ErrIsEmpty
- }
- b = r.buf[r.r]
- r.r++
- if r.r == r.size {
- r.r = 0
- }
- r.isFull = false
- r.mu.Unlock()
- return b, err
- }
- func (r *BackableRingBuffer) PeepByte() (b byte, err error) {
- r.mu.Lock()
- if r.w == r.r && !r.isFull {
- r.mu.Unlock()
- return 0, ErrIsEmpty
- }
- b = r.buf[r.r]
- r.mu.Unlock()
- return b, err
- }
- func (r *BackableRingBuffer) Write(p []byte) (n int, err error) {
- if len(p) == 0 {
- return 0, nil
- }
- r.mu.Lock()
- n, err = r.write(p)
- r.mu.Unlock()
- return n, err
- }
- func (r *BackableRingBuffer) WriteBack(p []byte) (n int, err error) {
- if len(p) == 0 {
- return 0, nil
- }
- r.mu.Lock()
- n, err = r.writeBack(p)
- r.mu.Unlock()
- return n, err
- }
- func (r *BackableRingBuffer) TryWrite(p []byte) (n int, err error) {
- if len(p) == 0 {
- return 0, nil
- }
- ok := r.mu.TryLock()
- if !ok {
- return 0, ErrAccuqireLock
- }
- n, err = r.write(p)
- r.mu.Unlock()
- return n, err
- }
- func (r *BackableRingBuffer) TryWriteBack(p []byte) (n int, err error) {
- if len(p) == 0 {
- return 0, nil
- }
- ok := r.mu.TryLock()
- if !ok {
- return 0, ErrAccuqireLock
- }
- n, err = r.writeBack(p)
- r.mu.Unlock()
- return n, err
- }
- func (r *BackableRingBuffer) write(p []byte) (n int, err error) {
- if r.isFull {
- return 0, ErrIsFull
- }
- var avail int
- if r.w >= r.r {
- avail = r.size - r.w + r.r
- } else {
- avail = r.r - r.w
- }
- if len(p) > avail {
- err = ErrTooManyDataToWrite
- p = p[:avail]
- }
- n = len(p)
- if r.w >= r.r {
- c1 := r.size - r.w
- if c1 >= n {
- copy(r.buf[r.w:], p)
- r.w += n
- } else {
- copy(r.buf[r.w:], p[:c1])
- c2 := n - c1
- copy(r.buf[0:], p[c1:])
- r.w = c2
- }
- } else {
- copy(r.buf[r.w:], p)
- r.w += n
- }
- if r.w == r.size {
- r.w = 0
- }
- if r.w == r.r {
- r.isFull = true
- }
- return n, err
- }
- func (r *BackableRingBuffer) writeBack(p []byte) (n int, err error) {
- if r.isFull {
- return 0, ErrIsFull
- }
- var avail int
- if r.w >= r.r {
- avail = r.size - r.w + r.r
- } else {
- avail = r.r - r.w
- }
- if len(p) > avail {
- err = ErrTooManyDataToWrite
- p = p[:avail]
- }
- n = len(p)
- if r.w >= r.r {
- if n <= r.r {
- stp := r.r - n
- copy(r.buf[stp:], p)
- r.r = r.r - n
- } else {
- lan := n - r.r
- stp1 := r.size - lan
- copy(r.buf[stp1:], p[:lan])
- copy(r.buf, p[lan:])
- r.r = stp1
- }
- } else {
- stp2 := r.r - n
- copy(r.buf[stp2:], p)
- r.r = stp2
- }
- if r.w == r.r {
- r.isFull = true
- }
- return n, err
- }
- func (r *BackableRingBuffer) WriteByte(c byte) error {
- r.mu.Lock()
- err := r.writeByte(c)
- r.mu.Unlock()
- return err
- }
- func (r *BackableRingBuffer) WriteByteBack(c byte) error {
- r.mu.Lock()
- err := r.writeByteBack(c)
- r.mu.Unlock()
- return err
- }
- func (r *BackableRingBuffer) TryWriteByte(c byte) error {
- ok := r.mu.TryLock()
- if !ok {
- return ErrAccuqireLock
- }
- err := r.writeByte(c)
- r.mu.Unlock()
- return err
- }
- func (r *BackableRingBuffer) TryWriteByteBack(c byte) error {
- ok := r.mu.TryLock()
- if !ok {
- return ErrAccuqireLock
- }
- err := r.writeByteBack(c)
- r.mu.Unlock()
- return err
- }
- func (r *BackableRingBuffer) writeByte(c byte) error {
- if r.w == r.r && r.isFull {
- return ErrIsFull
- }
- r.buf[r.w] = c
- r.w++
- if r.w == r.size {
- r.w = 0
- }
- if r.w == r.r {
- r.isFull = true
- }
- return nil
- }
- func (r *BackableRingBuffer) writeByteBack(c byte) error {
- if r.w == r.r && r.isFull {
- return ErrIsFull
- }
- pos := r.r - 1
- if pos < 0 {
- pos = r.size - 1
- }
- r.buf[pos] = c
- r.r = pos
- if r.w == r.r {
- r.isFull = true
- }
- return nil
- }
- func (r *BackableRingBuffer) Length() int {
- r.mu.Lock()
- defer r.mu.Unlock()
- if r.w == r.r {
- if r.isFull {
- return r.size
- }
- return 0
- }
- if r.w > r.r {
- return r.w - r.r
- }
- return r.size - r.r + r.w
- }
- func (r *BackableRingBuffer) Capacity() int {
- return r.size
- }
- func (r *BackableRingBuffer) Free() int {
- r.mu.Lock()
- defer r.mu.Unlock()
- if r.w == r.r {
- if r.isFull {
- return 0
- }
- return r.size
- }
- if r.w < r.r {
- return r.r - r.w
- }
- return r.size - r.w + r.r
- }
- func (r *BackableRingBuffer) WriteString(s string) (n int, err error) {
- x := (*[2]uintptr)(unsafe.Pointer(&s))
- h := [3]uintptr{x[0], x[1], x[1]}
- buf := *(*[]byte)(unsafe.Pointer(&h))
- return r.Write(buf)
- }
- func (r *BackableRingBuffer) Bytes() []byte {
- r.mu.Lock()
- defer r.mu.Unlock()
- if r.w == r.r {
- if r.isFull {
- buf := make([]byte, r.size)
- copy(buf, r.buf[r.r:])
- copy(buf[r.size-r.r:], r.buf[:r.w])
- return buf
- }
- return nil
- }
- if r.w > r.r {
- buf := make([]byte, r.w-r.r)
- copy(buf, r.buf[r.r:r.w])
- return buf
- }
- n := r.size - r.r + r.w
- buf := make([]byte, n)
- if r.r+n < r.size {
- copy(buf, r.buf[r.r:r.r+n])
- } else {
- c1 := r.size - r.r
- copy(buf, r.buf[r.r:r.size])
- c2 := n - c1
- copy(buf[c1:], r.buf[0:c2])
- }
- return buf
- }
- func (r *BackableRingBuffer) PeepByteAt(pos int) (b byte, err error) {
- defer r.mu.Unlock()
- r.mu.Lock()
- if r.w == r.r && !r.isFull {
- return 0, ErrIsEmpty
- }
- if r.r == r.w && pos > 0 {
- return 0, ErrOutOfRange
- }
- if r.r < r.w {
- rpos := r.r + pos
- b = r.buf[rpos]
- return
- } else {
- if r.r+pos >= r.size {
- rpos := r.r + pos - r.size
- if rpos >= r.w {
- return 0, ErrOutOfRange
- }
- b = r.buf[rpos]
- return
- } else {
- rpos := r.r + pos
- b = r.buf[rpos]
- return
- }
- }
- }
- func (r *BackableRingBuffer) IsFull() bool {
- r.mu.Lock()
- defer r.mu.Unlock()
- return r.isFull
- }
- func (r *BackableRingBuffer) IsEmpty() bool {
- r.mu.Lock()
- defer r.mu.Unlock()
- return !r.isFull && r.w == r.r
- }
- func (r *BackableRingBuffer) Reset() {
- r.mu.Lock()
- defer r.mu.Unlock()
- r.r = 0
- r.w = 0
- r.isFull = false
- }
|