Pulse/internal/utils/buffer.go
2026-03-18 16:06:30 +00:00

117 lines
2.1 KiB
Go

package utils
import (
"sync"
)
const minQueueCapacity = 1
// Queue is a thread-safe bounded FIFO queue. When full, the oldest item is dropped.
type Queue[T any] struct {
mu sync.Mutex
data []T
capacity int
}
const minCapacity = 1
// New creates a new Queue with the specified capacity.
// Capacity must be greater than zero.
func New[T any](capacity int) *Queue[T] {
if capacity <= 0 {
capacity = minCapacity
}
return &Queue[T]{
data: make([]T, 0, capacity),
capacity: capacity,
}
}
// Push adds an item to the queue. If the queue is full, the oldest item is dropped.
func (q *Queue[T]) Push(item T) {
q.mu.Lock()
defer q.mu.Unlock()
// Non-positive capacity means the queue is effectively disabled.
if q.capacity <= 0 {
return
}
if len(q.data) >= q.capacity {
var zero T
q.data[0] = zero
q.data = q.data[1:]
}
q.data = append(q.data, item)
}
func normalizeCapacity(capacity int) int {
if capacity < minCapacity {
return minCapacity
}
return capacity
}
// Pop removes and returns the oldest item from the queue.
// Returns zero value and false if empty.
func (q *Queue[T]) Pop() (T, bool) {
q.mu.Lock()
defer q.mu.Unlock()
if len(q.data) == 0 {
var zero T
return zero, false
}
item := q.data[0]
var zero T
q.data[0] = zero
q.data = q.data[1:]
return item, true
}
// Peek returns the oldest item without removing it.
func (q *Queue[T]) Peek() (T, bool) {
q.mu.Lock()
defer q.mu.Unlock()
if len(q.data) == 0 {
var zero T
return zero, false
}
return q.data[0], true
}
// Len returns the current number of items.
func (q *Queue[T]) Len() int {
q.mu.Lock()
defer q.mu.Unlock()
return len(q.data)
}
// IsEmpty returns true if the queue is empty.
func (q *Queue[T]) IsEmpty() bool {
q.mu.Lock()
defer q.mu.Unlock()
return len(q.data) == 0
}
// Items returns a copy of all items in the queue in FIFO order.
func (q *Queue[T]) Items() []T {
q.mu.Lock()
defer q.mu.Unlock()
if len(q.data) == 0 {
return nil
}
cp := make([]T, len(q.data))
copy(cp, q.data)
return cp
}
func sanitizeCapacity(capacity int) int {
if capacity < minQueueCapacity {
return minQueueCapacity
}
return capacity
}