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