-
Notifications
You must be signed in to change notification settings - Fork 41
/
ringbuffer.go
54 lines (47 loc) · 1.09 KB
/
ringbuffer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package ringbuffer
import "fmt"
// RingBuffer implements a fixed capacity ringbuffer for items of type
// T
type RingBuffer[T any] struct {
start int
length int
buffer []T
}
func NewRingBuffer[T any](cap int) *RingBuffer[T] {
if cap <= 0 {
panic(fmt.Sprintf("NewRingBuffer: cap must be positive, got %d", cap))
}
return &RingBuffer[T]{
0,
0,
make([]T, cap),
}
}
func (rb *RingBuffer[T]) Length() int {
return rb.length
}
// Peek at the front item. Panics if there isn't one.
func (rb *RingBuffer[T]) Peek() T {
if rb.length == 0 {
panic("Peek: buffer empty")
}
return rb.buffer[rb.start]
}
// Pop front item. Panics if there isn't one.
func (rb *RingBuffer[T]) Pop() T {
result := rb.Peek()
var zero T
rb.buffer[rb.start] = zero
rb.start = (rb.start + 1) % len(rb.buffer)
rb.length--
return result
}
// Push new item to back. If the additional item would lead
// to the capacity being exceeded, remove the front item first
func (rb *RingBuffer[T]) Push(item T) {
if rb.length == len(rb.buffer) {
rb.Pop()
}
rb.buffer[(rb.start+rb.length)%len(rb.buffer)] = item
rb.length++
}