Repository navigation
Expand file tree
/
Copy pathringbuffer.go
More file actions
92 lines (80 loc) · 1.64 KB
/
Copy pathringbuffer.go
File metadata and controls
92 lines (80 loc) · 1.64 KB
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
package crux
import (
"sync"
)
type RingBuffer struct {
mu sync.RWMutex
items []string
cap int
head int
count int
total uint64
}
const defaultRingCapacity = 500
func NewRingBuffer(capacity int) *RingBuffer {
if capacity <= 0 {
capacity = defaultRingCapacity
}
return &RingBuffer{
items: make([]string, capacity),
cap: capacity,
}
}
func (r *RingBuffer) Write(s string) {
r.mu.Lock()
r.items[r.head] = s
r.head = (r.head + 1) % r.cap
if r.count < r.cap {
r.count++
}
r.total++
r.mu.Unlock()
}
func (r *RingBuffer) Last(n int) []string {
r.mu.RLock()
defer r.mu.RUnlock()
if n > r.count {
n = r.count
}
if n <= 0 {
return nil
}
result := make([]string, n)
start := (r.head - n + r.cap) % r.cap
for i := range n {
result[i] = r.items[(start+i)%r.cap]
}
return result
}
func (r *RingBuffer) Count() int {
r.mu.RLock()
defer r.mu.RUnlock()
return r.count
}
// Total returns how many lines were ever written, a monotonic position that
// keeps growing after old lines are overwritten.
func (r *RingBuffer) Total() uint64 {
r.mu.RLock()
defer r.mu.RUnlock()
return r.total
}
// Since returns the lines written at positions seq and later, and the
// position to pass next time. Lines already overwritten are skipped.
func (r *RingBuffer) Since(seq uint64) ([]string, uint64) {
r.mu.RLock()
defer r.mu.RUnlock()
oldest := r.total - uint64(r.count)
if seq < oldest {
seq = oldest
}
if seq >= r.total {
return nil, r.total
}
n := int(r.total - seq)
result := make([]string, n)
start := (r.head - n + r.cap) % r.cap
for i := range n {
result[i] = r.items[(start+i)%r.cap]
}
return result, r.total
}