-
Notifications
You must be signed in to change notification settings - Fork 6
/
ring.go
59 lines (46 loc) · 1.05 KB
/
ring.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
package mybench
import (
"container/ring"
"sync"
)
// A terrible implementation of a ring, based on the Golang ring which is not
// thread-safe nor offers a nice API.
//
// I can't believe there are no simple ring buffer data structure in Golang,
// with generics.
type Ring[T any] struct {
mut *sync.Mutex
capacity int
ring *ring.Ring
}
func NewRing[T any](capacity int) *Ring[T] {
return &Ring[T]{
mut: &sync.Mutex{},
capacity: capacity,
ring: ring.New(capacity),
}
}
func (r *Ring[T]) Push(data T) {
r.mut.Lock()
defer r.mut.Unlock()
r.ring = r.ring.Next()
r.ring.Value = data
}
func (r *Ring[T]) ReadAllOrdered() []T {
arr := make([]T, 0, r.capacity)
r.mut.Lock()
defer r.mut.Unlock()
earliest := r.ring
for earliest.Prev() != nil && earliest.Prev() != r.ring && earliest.Prev().Value != nil {
earliest = earliest.Prev()
}
for earliest != r.ring {
arr = append(arr, earliest.Value.(T))
earliest = earliest.Next()
}
if earliest.Value == nil {
return arr
}
arr = append(arr, earliest.Value.(T))
return arr
}