pointer.go 1003 B

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