Skip to content

hedzr/go-ringbuf

Repository files navigation

go-ringbuf [V2]

Go GitHub tag (latest SemVer) go.dev GoDoc FOSSA Status Go Report Card Coverage Status

go-ringbuf provides a high-performance, lock-free circular queue (ring buffer) implementation in golang.

MPMC (multiple producers and multiple consumers) enabled.

History

v2.2.2

  • [resp for #7] NewOverlappedRingBuffer returns RichOverlappedRingBuffer[T] now, which gives some new alternatives apis of Enqueue so that you can collect overwrites and size from the returning data.

    The legacy codes keep its stable with the original Enqueue. For a normal ringbuf, non-overlapped, nothing's changed since the current capacity (size) is not a very important value for measuring. If not, issue me.

v2.2.1

  • security updates

v2.2.0

  • added new impl to support overlapped ringbuf
  • security updates

v2.1.0

  • remove extras deps
    • replaced 'hedzr/log' with 'log/slog', 'hedzr/errors.v3' with 'errors'
  • remove WithLogger()

v2.0.+

security updates

v2.0.0 @20220408 - go 1.18+

generic version for MPMC Ring Buffer.

  • rewritten with go generics

v1.0.+ [archived]

security updates

v1.0.0 @20220408

Last release for classical version.

Next release (v2) will move to go 1.18+ with generic enabled.

v0.9.1 @2022

  • review all codes
  • updated deps
  • review and solve uncertain misreport failed licenses
    • we have two deps: hedzr/errors and hedzr/log, and both them have no 3rd-party deps.
      • since 2.1.0, any deps removed.
    • we have no more 3rd-party deps.
    • we assumed a free license under MIT (unified).

Getting Start

go get -v github.com/hedzr/go-ringbuf/v2

Samples

package main

import (
 "fmt"
 "log"

 "github.com/hedzr/go-ringbuf/v2"
)

func main() {
 testIntRB()
 testStringRB()
}

func testStringRB() {
 var err error
 var rb = ringbuf.New[string](80)
 err = rb.Enqueue("abcde")
 errChk(err)

 var item string
 item, err = rb.Dequeue()
 errChk(err)
 fmt.Printf("dequeue ok: %v\n", item)
}

func testIntRB() {
 var err error
 var rb = ringbuf.New[int](80)
 err = rb.Enqueue(3)
 errChk(err)

 var item int
 item, err = rb.Dequeue()
 errChk(err)
 fmt.Printf("dequeue ok: %v\n", item)
}

func errChk(err error) {
 if err != nil {
  log.Fatal(err)
 }
}

Using Ring-Buffer as a fixed resource pool

The following codes is for v1, needed for rewriting

func newRes() *Res{...}

var rb mpmc.RingBuffer

func initFunc() (err error) {
  const maxSize = 16
  
  if rb = mpmc.New(uint32(maxSize)); rb == nil {
    err = errors.New("cannot create mpmc.RingBuffer")
    return
  }

  // CapReal() will be available since v0.8.8, or replace it with Cap() - 1
  for i := uint32(0); i < rb.CapReal(); i++ {
    if err = rb.Enqueue(newRes()); err != nil {
      return
    }
  }
}

func loopFor() {
  var err error
  for {
    it, err := rb.Dequeue()
    checkErr(err)
    if res, ok := it.(*Res); ok {
      // do stuff with `res`, and put it back into ring-buffer
      err = rb.Enqueue(it)
    }
  }
}

Using Overlapped Ring Buffer

Since v2.2.0, NewOverlappedRingBuffer() can initiate a different ring buffer, which allows us to overwrite the head element if putting new element into a full ring buffer.

func testStringRB() {
  var err error
  var rb = ringbuf.NewOverlappedRingBuffer[string](80)
  err = rb.Enqueue("abcde")
  errChk(err)

  var item string
  item, err = rb.Dequeue()
  errChk(err)
  fmt.Printf("dequeue ok: %v\n", item)
}

Contrib

Welcome

LICENSE

Apache 2.0

Sponsor this project

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages