1
1
package git
2
2
3
+ /*
4
+ #include <stdlib.h>
5
+ */
6
+ import "C"
3
7
import (
4
8
"fmt"
5
9
"sync"
@@ -9,75 +13,45 @@ import (
9
13
type HandleList struct {
10
14
sync.RWMutex
11
15
// stores the Go pointers
12
- handles []interface {}
13
- // Indicates which indices are in use.
14
- set map [int ]bool
16
+ handles map [unsafe.Pointer ]interface {}
15
17
}
16
18
17
19
func NewHandleList () * HandleList {
18
20
return & HandleList {
19
- handles : make ([]interface {}, 5 ),
20
- set : make (map [int ]bool ),
21
+ handles : make (map [unsafe.Pointer ]interface {}),
21
22
}
22
23
}
23
24
24
- // findUnusedSlot finds the smallest-index empty space in our
25
- // list. You must only run this function while holding a write lock.
26
- func (v * HandleList ) findUnusedSlot () int {
27
- for i := 1 ; i < len (v .handles ); i ++ {
28
- if ! v .set [i ] {
29
- return i
30
- }
31
- }
32
-
33
- // reaching here means we've run out of entries so append and
34
- // return the new index, which is equal to the old length.
35
- slot := len (v .handles )
36
- v .handles = append (v .handles , nil )
37
-
38
- return slot
39
- }
40
-
41
25
// Track adds the given pointer to the list of pointers to track and
42
26
// returns a pointer value which can be passed to C as an opaque
43
27
// pointer.
44
28
func (v * HandleList ) Track (pointer interface {}) unsafe.Pointer {
45
- v .Lock ()
46
-
47
- slot := v .findUnusedSlot ()
48
- v .handles [slot ] = pointer
49
- v .set [slot ] = true
29
+ handle := C .malloc (1 )
50
30
31
+ v .Lock ()
32
+ v .handles [handle ] = pointer
51
33
v .Unlock ()
52
34
53
- return unsafe . Pointer ( uintptr ( slot ))
35
+ return handle
54
36
}
55
37
56
38
// Untrack stops tracking the pointer given by the handle
57
39
func (v * HandleList ) Untrack (handle unsafe.Pointer ) {
58
- slot := int (uintptr (handle ))
59
-
60
40
v .Lock ()
61
-
62
- v .handles [slot ] = nil
63
- delete (v .set , slot )
64
-
41
+ delete (v .handles , handle )
42
+ C .free (handle )
65
43
v .Unlock ()
66
44
}
67
45
68
46
// Get retrieves the pointer from the given handle
69
47
func (v * HandleList ) Get (handle unsafe.Pointer ) interface {} {
70
- slot := int (uintptr (handle ))
71
-
72
48
v .RLock ()
49
+ defer v .RUnlock ()
73
50
74
- if ! v .set [slot ] {
51
+ ptr , ok := v .handles [handle ]
52
+ if ! ok {
75
53
panic (fmt .Sprintf ("invalid pointer handle: %p" , handle ))
76
54
}
77
55
78
- ptr := v .handles [slot ]
79
-
80
- v .RUnlock ()
81
-
82
56
return ptr
83
57
}
0 commit comments