-
Notifications
You must be signed in to change notification settings - Fork 3
/
window.go
98 lines (86 loc) · 1.85 KB
/
window.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
94
95
96
97
98
package steps
import "github.com/bitflow-stream/go-bitflow/bitflow"
type MetricWindow struct {
data []bitflow.Value
first int
next int
full bool
}
func NewMetricWindow(size int) *MetricWindow {
if size == 0 { // Empty window is not valid
size = 1
}
return &MetricWindow{
data: make([]bitflow.Value, size),
}
}
func (w *MetricWindow) inc(i int) int {
return (i + 1) % len(w.data)
}
func (w *MetricWindow) Push(val bitflow.Value) {
w.data[w.next] = val
w.next = w.inc(w.next)
if w.full {
w.first = w.inc(w.first)
} else if w.first == w.next {
w.full = true
}
}
func (w *MetricWindow) Size() int {
switch {
case w.full:
return len(w.data)
case w.first <= w.next:
return w.next - w.first
default: // w.first > w.next
return len(w.data) - w.first + w.next
}
}
func (w *MetricWindow) Empty() bool {
return w.first == w.next && !w.full
}
func (w *MetricWindow) Full() bool {
return w.full
}
// Remove and return the oldest value. The oldest value is also deleted by
// Push() when the window is full.
func (w *MetricWindow) Pop() bitflow.Value {
if w.Empty() {
return 0
}
val := w.data[w.first]
w.first = w.inc(w.first)
w.full = false
return val
}
// Avoid copying if possible. Dangerous.
func (w *MetricWindow) FastData() []bitflow.Value {
if w.Empty() {
return nil
}
if w.first < w.next {
return w.data[w.first:w.next]
} else {
return w.Data()
}
}
func (w *MetricWindow) Data() []bitflow.Value {
res := make([]bitflow.Value, len(w.data))
res = w.FillData(res)
return res
}
func (w *MetricWindow) FillData(target []bitflow.Value) []bitflow.Value {
if w.Empty() {
return nil
}
var length int
if w.first < w.next {
length = copy(target, w.data[w.first:w.next])
} else {
length = copy(target, w.data[w.first:])
if len(target) > length {
length += copy(target[length:], w.data[:w.next])
}
}
return target[:length]
}