Documentation
¶
Overview ¶
Package provides fixed length FIFO ring buffer functionality.
You can use a generic data structure with methods, which is forced to use slices due to Go language limitations (no generic array lengths):
b := ringbuffer.New[int](5)
b.Push(1)
b.Push(2)
v1, _ := b.Pop()
v2, _ := b.Pop()
fmt.Printf("%d %d\n", v1, v2)
Or you can use generic functions with your own state variables. Here you can use plain arrays and integer types of arbitrary size:
var buf [5]int
var read int8
var write int8
ringbuffer.Push(buf[:], read, &write, 1)
ringbuffer.Push(buf[:], read, &write, 2)
v1, _ := ringbuffer.Pop(buf[:], &read, write)
v2, _ := ringbuffer.Pop(buf[:], &read, write)
fmt.Printf("%d %d\n", v1, v2)
The logic is the simplest implementation straight from wikipedia: https://en.wikipedia.org/wiki/Circular_buffer. In short: there are read and write pointers as integer indices and a buffer of capacity+1 space. An extra element is reserved to distinguish between full/empty state. When using plain generic functions with smaller integer types, be aware of integer overflows. No care taken to prevent these.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Cap ¶
How many elements a buffer can store?
Example ¶
package main
import (
"fmt"
"github.com/nsf/ringbuffer"
)
func main() {
var buf [10]int
fmt.Printf("%d\n", ringbuffer.Cap(buf[:]))
}
Output: 9
func Len ¶
func Len[T any, U constraints.Integer](slice []T, read, write U) int
How many elements are currently stored in the buffer?
Example ¶
package main
import (
"fmt"
"github.com/nsf/ringbuffer"
)
func main() {
var buf [10]int
var read int8
var write int8
l1 := ringbuffer.Len(buf[:], read, write)
ringbuffer.Push(buf[:], read, &write, 1)
l2 := ringbuffer.Len(buf[:], read, write)
fmt.Printf("%d %d\n", l1, l2)
}
Output: 0 1
func Pop ¶
func Pop[T any, U constraints.Integer](slice []T, read *U, write U) (T, bool)
Try to pop an element from the buffer.
Returns the popped element and true on success. Returns default value and false if there were no elements in the buffer.
Example ¶
package main
import (
"fmt"
"github.com/nsf/ringbuffer"
)
func main() {
var buf [5]int
var read int8
var write int8
ringbuffer.Push(buf[:], read, &write, 1)
ringbuffer.Push(buf[:], read, &write, 2)
v1, _ := ringbuffer.Pop(buf[:], &read, write)
v2, _ := ringbuffer.Pop(buf[:], &read, write)
fmt.Printf("%d %d\n", v1, v2)
}
Output: 1 2
func Push ¶
func Push[T any, U constraints.Integer](slice []T, read U, write *U, v T) bool
Push a new element to the buffer.
Returns true on success. Returns false if there is no free space and push failed.
Example ¶
package main
import (
"fmt"
"github.com/nsf/ringbuffer"
)
func main() {
var buf [5]int
var read int8
var write int8
ringbuffer.Push(buf[:], read, &write, 1)
ringbuffer.Push(buf[:], read, &write, 2)
v1, _ := ringbuffer.Pop(buf[:], &read, write)
v2, _ := ringbuffer.Pop(buf[:], &read, write)
fmt.Printf("%d %d\n", v1, v2)
}
Output: 1 2
Types ¶
type RingBuffer ¶
type RingBuffer[T any] struct { // contains filtered or unexported fields }
Fixed length FIFO ring buffer.
Example ¶
package main
import (
"fmt"
"github.com/nsf/ringbuffer"
)
func main() {
// Using ringbuffer structure alone without the "New" function is fairly useless, but it's valid.
var buf ringbuffer.RingBuffer[int]
fmt.Printf("cap: %d, len: %d, pushed: %v\n", buf.Cap(), buf.Len(), buf.Push(5))
}
Output: cap: 0, len: 0, pushed: false
func New ¶
func New[T any](capacity int) RingBuffer[T]
Create a new buffer which can store capacity elements. The buffer is fixed in length and will not grow. It is a FIFO buffer.
Implementation detail: the buffer is implemented as two integer pointers and a slice of capacity+1 elements. One extra element is reserved to avoid ambiguous state where read and write pointers point to the same location and it might mean full or empty buffer. A bit of extra space wasted is traded for logical simplicity.
Example ¶
package main
import (
"fmt"
"github.com/nsf/ringbuffer"
)
func main() {
b := ringbuffer.New[int](5)
b.Push(1)
b.Push(2)
v1, _ := b.Pop()
v2, _ := b.Pop()
fmt.Printf("%d %d\n", v1, v2)
}
Output: 1 2
func (RingBuffer[T]) Cap ¶
func (b RingBuffer[T]) Cap() int
How many elements a buffer can store?
Example ¶
package main
import (
"fmt"
"github.com/nsf/ringbuffer"
)
func main() {
b := ringbuffer.New[int](5)
fmt.Printf("%d\n", b.Cap())
}
Output: 5
func (RingBuffer[T]) Len ¶
func (b RingBuffer[T]) Len() int
How many elements are currently stored in the buffer?
Example ¶
package main
import (
"fmt"
"github.com/nsf/ringbuffer"
)
func main() {
b := ringbuffer.New[int](5)
l1 := b.Len()
b.Push(1)
l2 := b.Len()
fmt.Printf("%d %d\n", l1, l2)
}
Output: 0 1
func (*RingBuffer[T]) Pop ¶
func (b *RingBuffer[T]) Pop() (T, bool)
Try to pop an element from the buffer.
Returns the popped element and true on success. Returns default value and false if there were no elements in the buffer.
Example ¶
package main
import (
"fmt"
"github.com/nsf/ringbuffer"
)
func main() {
b := ringbuffer.New[int](5)
b.Push(1)
b.Push(2)
v1, _ := b.Pop()
v2, _ := b.Pop()
fmt.Printf("%d %d\n", v1, v2)
}
Output: 1 2
func (*RingBuffer[T]) Push ¶
func (b *RingBuffer[T]) Push(v T) bool
Push a new element to the buffer.
Returns true on success. Returns false if there is no free space and push failed.
Example ¶
package main
import (
"fmt"
"github.com/nsf/ringbuffer"
)
func main() {
b := ringbuffer.New[int](5)
b.Push(1)
b.Push(2)
v1, _ := b.Pop()
v2, _ := b.Pop()
fmt.Printf("%d %d\n", v1, v2)
}
Output: 1 2