Sam Fredrickson
b00fe25128
* Expand README.md, provide benchmark results. * Add docs, benchmarks for binheap and circ packages. * Add methods Len() and Capacity(). * Change *sync.Cond to sync.Cond. * TryRecv() and TrySend() distinguish empty and closed errors. * Improve test coverage. * Add basic Makefile. * Fix documentation mistakes.
71 lines
1.3 KiB
Go
71 lines
1.3 KiB
Go
// Package circ implements a circular FIFO buffer.
|
|
package circ
|
|
|
|
// B is a circular FIFO buffer.
|
|
type B[T any] struct {
|
|
buf []T
|
|
len int
|
|
head int
|
|
tail int
|
|
}
|
|
|
|
// Make creates a new buffer.
|
|
func Make[T any](cap int) B[T] {
|
|
buf := make([]T, cap)
|
|
return B[T]{buf: buf}
|
|
}
|
|
|
|
// Capacity returns the total capacity of the buffer.
|
|
func (b *B[T]) Capacity() int {
|
|
return cap(b.buf)
|
|
}
|
|
|
|
// Len returns the number of items in the buffer.
|
|
func (b *B[T]) Len() int {
|
|
return b.len
|
|
}
|
|
|
|
// CanPush returns true if the buffer has space for new items.
|
|
func (b *B[T]) CanPush() bool {
|
|
return cap(b.buf)-b.len != 0
|
|
}
|
|
|
|
// CanPop returns true if the buffer has one or more items.
|
|
func (b *B[T]) CanPop() bool {
|
|
return b.len != 0
|
|
}
|
|
|
|
// PopFront returns the front-most item from the buffer.
|
|
//
|
|
// If the buffer is empty, it panics.
|
|
func (b *B[T]) PopFront() T {
|
|
if !b.CanPop() {
|
|
panic("cannot pop from empty buffer")
|
|
}
|
|
item := b.buf[b.head]
|
|
// clear buffer slot so as not to hold on to garbage
|
|
var empty T
|
|
b.buf[b.head] = empty
|
|
b.len--
|
|
b.head++
|
|
if b.head == cap(b.buf) {
|
|
b.head = 0
|
|
}
|
|
return item
|
|
}
|
|
|
|
// PushBack adds an item to the end of the buffer.
|
|
//
|
|
// If the buffer is full, it panics.
|
|
func (b *B[T]) PushBack(value T) {
|
|
if !b.CanPush() {
|
|
panic("cannot push back to full buffer")
|
|
}
|
|
b.buf[b.tail] = value
|
|
b.len++
|
|
b.tail++
|
|
if b.tail == cap(b.buf) {
|
|
b.tail = 0
|
|
}
|
|
}
|