forked from nictuku/dht
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharena.go
45 lines (40 loc) · 1.32 KB
/
arena.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
package dht
import "sync"
// arena is a free list that provides quick access to pre-allocated byte
// slices, greatly reducing memory churn and effectively disabling GC for these
// allocations. After the arena is created, a slice of bytes can be requested by
// calling Pop(). The caller is responsible for calling Push(), which puts the
// blocks back in the queue for later usage. The bytes given by Pop() are *not*
// zeroed, so the caller should only read positions that it knows to have been
// overwitten. That can be done by shortening the slice at the right place,
// based on the count of bytes returned by Write() and similar functions.
type arena struct {
// I could have used a buffered channel to implement the freelist, but
// this is probably faster.
sync.Mutex
blocks [][]byte
bsize int
}
func newArena(blockSize int, numBlocks int) *arena {
b := make([][]byte, numBlocks)
for i, _ := range b {
b[i] = make([]byte, blockSize)
}
return &arena{blocks: b, bsize: blockSize}
}
func (a *arena) Pop() (x []byte) {
a.Lock()
defer a.Unlock()
if len(a.blocks) == 0 {
// panic("arena out of space")
return make([]byte, a.bsize)
}
x, a.blocks = a.blocks[len(a.blocks)-1], a.blocks[:len(a.blocks)-1]
return x
}
func (a *arena) Push(x []byte) {
a.Lock()
x = x[:cap(x)]
a.blocks = append(a.blocks, x)
a.Unlock()
}