priorityq/circ/lib.go
Sam Fredrickson b00fe25128 Various improvements.
* 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.
2023-03-03 15:35:49 -08:00

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
}
}