-
Notifications
You must be signed in to change notification settings - Fork 19
/
ringbuffer.go
93 lines (81 loc) · 1.77 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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package goev
// RingBuffer using value array, only suitable for tiny struct
type RingBuffer[T any] struct {
size int
head int
tail int
len int
zero T
buffer []T
}
// NewRingBuffer return an instance
func NewRingBuffer[T any](initCap int) *RingBuffer[T] {
return &RingBuffer[T]{
buffer: make([]T, initCap),
size: initCap,
head: 0,
tail: 0,
len: 0,
}
}
// IsEmpty return is empty or not
func (rb *RingBuffer[T]) IsEmpty() bool {
return rb.len == 0
}
// IsFull return is full or not
func (rb *RingBuffer[T]) IsFull() bool {
return rb.len == rb.size
}
// Size return the latest buffer size
func (rb *RingBuffer[T]) Size() int {
return rb.size
}
// Len reutrn the current buffer length
func (rb *RingBuffer[T]) Len() int {
return rb.len
}
// PushBack an item
func (rb *RingBuffer[T]) PushBack(data T) {
if rb.len == rb.size {
rb.grow()
}
rb.buffer[rb.tail] = data
rb.tail = (rb.tail + 1) % rb.size // TODO optimize to & operator
rb.len++
}
// PopFront an item
func (rb *RingBuffer[T]) PopFront() (data T, ok bool) {
if rb.len == 0 {
return
}
data = rb.buffer[rb.head]
rb.buffer[rb.head] = rb.zero // Quickly release memory
rb.head = (rb.head + 1) % rb.size
rb.len--
ok = true
return
}
// PushFront an item
func (rb *RingBuffer[T]) PushFront(data T) {
if rb.len == rb.size {
rb.grow()
}
rb.head = (rb.size + rb.head - 1) % rb.size // prev
rb.buffer[rb.head] = data
rb.len++
}
func (rb *RingBuffer[T]) grow() {
newCapacity := rb.size * 2
newBuffer := make([]T, newCapacity)
var n int
if rb.tail > rb.head {
n = copy(newBuffer, rb.buffer[rb.head:rb.tail])
} else {
n = copy(newBuffer, rb.buffer[rb.head:])
n += copy(newBuffer[n:], rb.buffer[:rb.tail])
}
rb.buffer = newBuffer
rb.size = newCapacity
rb.head = 0
rb.tail = n
}