/
buffer_list.go
67 lines (52 loc) · 1.21 KB
/
buffer_list.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
package minitrace
import (
"sync"
)
const POW = 8
type buffer struct {
array [1 << POW]Span
next *buffer
}
type bufferList struct {
head *buffer
tail *buffer
len int
}
var bufferPool = &sync.Pool{New: func() interface{} { return &buffer{} }}
func newBufferList() *bufferList {
n := bufferPool.Get().(*buffer)
return &bufferList{n, n, 0}
}
func (bl *bufferList) slot() *Span {
idx := bl.len & ((1 << POW) - 1)
if idx == 0 {
n := bufferPool.Get().(*buffer)
bl.tail.next = n
bl.tail = n
}
bl.len += 1
return &bl.tail.array[idx]
}
func (bl *bufferList) collect() []Span {
if bl.len == 0 {
return nil
}
h := bl.head.next
bufferPool.Put(bl.head)
bl.head = nil
res := make([]Span, bl.len, bl.len)
remainingLen := bl.len
sizePerBuffer := 1 << POW
for remainingLen > sizePerBuffer {
cursor := bl.len - remainingLen
copy(res[cursor:cursor+sizePerBuffer], h.array[:])
remainingLen -= sizePerBuffer
n := h.next
bufferPool.Put(h)
h = n
}
cursor := bl.len - remainingLen
copy(res[cursor:], h.array[:remainingLen])
bufferPool.Put(h)
return res
}