go-ringbuf
go-ringbuf copied to clipboard
Lock-free MPMC Ring Buffer (Generic) for SMP, in golang. Some posts in chinese:
go-ringbuf [V2]
go-ringbuf
provides a high-performance, lock-free circular queue (ring buffer) implementation in golang.
MPMC (multiple-producers and multiple consumers) enabled.
History
v2.1.0
- remove extras deps
- use 'log/slog' instead 'hedzr/log', 'errors' instead 'hedzr/errors.v3'
- 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.+
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).
- ~~we have two deps: hedzr/errors and hedzr/log, and both them have no 3rd-party deps.~~
Getting Start
go get -v github.com/hedzr/go-ringbuf/v2
Samples
package main
import (
"fmt"
"github.com/hedzr/go-ringbuf/v2"
"log"
)
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 fast.RingBuffer
func initFunc() (err error) {
const maxSize = 16
if rb = fast.New(uint32(maxSize)); rb == nil {
err = errors.New("cannot create fast.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)
}
}
}
Contrib
Welcome
LICENSE
Apache 2.0