forked from hprose/hprose-golang
/
byte_pool.go
90 lines (80 loc) · 2.28 KB
/
byte_pool.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
/**********************************************************\
| |
| hprose |
| |
| Official WebSite: http://www.hprose.com/ |
| http://www.hprose.org/ |
| |
\**********************************************************/
/**********************************************************\
* *
* io/byte_pool.go *
* *
* byte pool for Go. *
* *
* LastModified: Oct 25, 2016 *
* Author: Ma Bingyao <andot@hprose.com> *
* *
\**********************************************************/
package io
import (
"sync"
)
const (
poolNum = 20
maxSize = 1 << (poolNum + 8)
)
var bytePool [poolNum]*sync.Pool
func pow2roundup(x int64) int64 {
x--
x |= x >> 1
x |= x >> 2
x |= x >> 4
x |= x >> 8
x |= x >> 16
x |= x >> 32
return x + 1
}
var debruijn = [...]int{
0, 1, 28, 2, 29, 14, 24, 3,
30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7,
26, 12, 18, 6, 11, 5, 10, 9,
}
func log2(x int64) int {
return debruijn[uint32(x*0x077CB531)>>27]
}
func init() {
for i := uint(0); i < poolNum; i++ {
bytePool[i] = &sync.Pool{
New: func(n int) func() interface{} {
return func() interface{} {
return make([]byte, n)
}
}(1 << (i + 9)),
}
}
}
// AcquireBytes from pool.
func AcquireBytes(size int) []byte {
if size < 1 {
return nil
}
capacity := pow2roundup(int64(size))
if capacity > maxSize {
return make([]byte, size, capacity)
}
if capacity < 512 {
capacity = 512
}
return bytePool[log2(capacity)-9].Get().([]byte)[:size]
}
// ReleaseBytes to pool.
func ReleaseBytes(bytes []byte) bool {
capacity := int64(cap(bytes))
if capacity < 512 || capacity > maxSize || capacity != pow2roundup(capacity) {
return false
}
bytePool[log2(capacity)-9].Put(bytes)
return true
}