1package pointer
2
3// #include <stdlib.h>
4import "C"
5import (
6	"sync"
7	"unsafe"
8)
9
10var (
11	mutex sync.Mutex
12	store = map[unsafe.Pointer]interface{}{}
13)
14
15func Save(v interface{}) unsafe.Pointer {
16	if v == nil {
17		return nil
18	}
19
20	// Generate real fake C pointer.
21	// This pointer will not store any data, but will bi used for indexing purposes.
22	// Since Go doest allow to cast dangling pointer to unsafe.Pointer, we do rally allocate one byte.
23	// Why we need indexing, because Go doest allow C code to store pointers to Go data.
24	var ptr unsafe.Pointer = C.malloc(C.size_t(1))
25	if ptr == nil {
26		panic("can't allocate 'cgo-pointer hack index pointer': ptr == nil")
27	}
28
29	mutex.Lock()
30	store[ptr] = v
31	mutex.Unlock()
32
33	return ptr
34}
35
36func Restore(ptr unsafe.Pointer) (v interface{}) {
37	if ptr == nil {
38		return nil
39	}
40
41	mutex.Lock()
42	v = store[ptr]
43	mutex.Unlock()
44	return
45}
46
47func Unref(ptr unsafe.Pointer) {
48	if ptr == nil {
49		return
50	}
51
52	mutex.Lock()
53	delete(store, ptr)
54	mutex.Unlock()
55
56	C.free(ptr)
57}
58