-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcbyte.go
More file actions
110 lines (94 loc) · 2.33 KB
/
cbyte.go
File metadata and controls
110 lines (94 loc) · 2.33 KB
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
99
100
101
102
103
104
105
106
107
108
109
110
package cbyte
/*
#include "cbyte.h"
*/
import "C"
import (
"unsafe"
)
const (
// Buffer size limit to use malloc to grow.
mallocGrowThreshold = 1024
)
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
type StringHeader struct {
Data uintptr
Len int
}
// Init makes byte array in C memory, outside of GC's eyes.
func Init(cap int) uint64 {
metricsHandler.Alloc(uint64(cap))
return uint64(C.cbyte_init(C.int(cap)))
}
// InitHeader makes slice header of byte array.
func InitHeader(len, cap int) SliceHeader {
return SliceHeader{
Data: uintptr(Init(cap)),
Len: len,
Cap: cap,
}
}
// InitBytes makes and return byte slice.
func InitBytes(len, cap int) []byte {
return Bytes(InitHeader(len, cap))
}
// Grow increases capacity of the byte array.
//
// All necessary copying/free will perform implicitly, don't worry about this.
func Grow(addr uint64, capOld, cap int) uint64 {
// Using combination of malloc()+memcpy()+free() to grow for short buffers is more efficient than simple using
// of realloc().
metricsHandler.Grow(uint64(capOld), uint64(cap))
if capOld > mallocGrowThreshold {
return uint64(C.cbyte_grow_r(C.uint64(addr), C.int(cap)))
} else {
return uint64(C.cbyte_grow_m(C.uint64(addr), C.int(capOld), C.int(cap)))
}
}
// GrowHeader increases capacity of the byte array using SliceHeader.
func GrowHeader(h SliceHeader) uint64 {
return Grow(uint64(h.Data), h.Len, h.Cap)
}
// Memcpy makes a copy of data directly to the addr+offset.
func Memcpy(addr, offset uint64, data []byte) (n int) {
n = len(data)
h := SliceHeader{
Data: uintptr(addr + offset),
Len: n,
Cap: n,
}
b := Bytes(h)
copy(b, data)
return n
}
// Release releases cbyte pointer.
func Release(addr uint64) {
if addr == 0 {
return
}
C.cbyte_release(C.uint64(addr))
}
// ReleaseHeader free byte array using SliceHeader.
func ReleaseHeader(h SliceHeader) {
metricsHandler.Free(uint64(h.Cap))
Release(uint64(h.Data))
}
// ReleaseBytes free underlying cbyte slice.
//
// Caution! Don't try to release non-cbyte slices.
func ReleaseBytes(p []byte) {
ReleaseHeader(Header(p))
}
// Header converts byte slice to SliceHeader.
func Header(p []byte) SliceHeader {
return *(*SliceHeader)(unsafe.Pointer(&p))
}
// Bytes composes byte slice from SliceHeader.
func Bytes(h SliceHeader) []byte {
return *(*[]byte)(unsafe.Pointer(&h))
}
var _ = GrowHeader