-
Notifications
You must be signed in to change notification settings - Fork 4
/
blockpool.go
57 lines (49 loc) · 1.17 KB
/
blockpool.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
package bubt
import "unsafe"
import "runtime"
import "sync/atomic"
import "github.com/bnclabs/gostore/lib"
type blockpool struct {
head unsafe.Pointer // *blockdata
n int64
max int64
}
func newblockpool(max int64) *blockpool {
return &blockpool{head: nil, n: 0, max: max}
}
type blockdata struct {
data []byte
next unsafe.Pointer // *blockdata
}
func (pool *blockpool) getblock(size int) *blockdata {
loop:
for {
oldptr := atomic.LoadPointer(&pool.head)
if oldptr == nil {
if atomic.AddInt64(&pool.n, 1) > pool.max {
atomic.AddInt64(&pool.n, -1)
runtime.Gosched()
continue loop
}
b := &blockdata{data: lib.Fixbuffer(nil, int64(size)), next: nil}
return b
}
old := (*blockdata)(oldptr)
nextptr := atomic.LoadPointer(&old.next)
if atomic.CompareAndSwapPointer(&pool.head, oldptr, nextptr) {
old.data = lib.Fixbuffer(old.data, int64(size))
return old
}
}
}
func (pool *blockpool) putblock(b *blockdata) {
var newptr unsafe.Pointer
for {
oldptr := atomic.LoadPointer(&pool.head)
atomic.StorePointer(&b.next, oldptr)
newptr = unsafe.Pointer(b)
if atomic.CompareAndSwapPointer(&pool.head, oldptr, newptr) {
return
}
}
}