diff options
| author | Calin Seciu <[email protected]> | 2016-02-20 14:52:57 +0200 |
|---|---|---|
| committer | Calin Seciu <[email protected]> | 2016-02-20 14:52:57 +0200 |
| commit | c6f394e407a8f119eea191e1321f61828921f164 (patch) | |
| tree | 6b4ab4bbd263388f0384b029b2a770189782b9d0 /handles.go | |
| parent | dc4409793db0205ce7c0783a10363d7d67aee674 (diff) | |
| parent | 251d89e1d41037185df0ea89e9aab208efc40d4e (diff) | |
Merge branch 'next' into stash-support
Diffstat (limited to 'handles.go')
| -rw-r--r-- | handles.go | 58 |
1 files changed, 15 insertions, 43 deletions
@@ -1,5 +1,9 @@ package git +/* +#include <stdlib.h> +*/ +import "C" import ( "fmt" "sync" @@ -9,77 +13,45 @@ import ( type HandleList struct { sync.RWMutex // stores the Go pointers - handles []interface{} - // Indicates which indices are in use, and keeps a pointer to slot int variable (the handle) - // in the Go world, so that the Go garbage collector does not free it. - set map[int]*int + handles map[unsafe.Pointer]interface{} } func NewHandleList() *HandleList { return &HandleList{ - handles: make([]interface{}, 5), - set: make(map[int]*int), + handles: make(map[unsafe.Pointer]interface{}), } } -// findUnusedSlot finds the smallest-index empty space in our -// list. You must only run this function while holding a write lock. -func (v *HandleList) findUnusedSlot() int { - for i := 1; i < len(v.handles); i++ { - _, isUsed := v.set[i] - if !isUsed { - return i - } - } - - // reaching here means we've run out of entries so append and - // return the new index, which is equal to the old length. - slot := len(v.handles) - v.handles = append(v.handles, nil) - - return slot -} - // Track adds the given pointer to the list of pointers to track and // returns a pointer value which can be passed to C as an opaque // pointer. func (v *HandleList) Track(pointer interface{}) unsafe.Pointer { - v.Lock() - - slot := v.findUnusedSlot() - v.handles[slot] = pointer - v.set[slot] = &slot // Keep a pointer to slot in Go world, so it's not freed by GC. + handle := C.malloc(1) + v.Lock() + v.handles[handle] = pointer v.Unlock() - return unsafe.Pointer(&slot) + return handle } // Untrack stops tracking the pointer given by the handle func (v *HandleList) Untrack(handle unsafe.Pointer) { - slot := *(*int)(handle) - v.Lock() - - v.handles[slot] = nil - delete(v.set, slot) - + delete(v.handles, handle) + C.free(handle) v.Unlock() } // Get retrieves the pointer from the given handle func (v *HandleList) Get(handle unsafe.Pointer) interface{} { - slot := *(*int)(handle) - v.RLock() + defer v.RUnlock() - if _, ok := v.set[slot]; !ok { + ptr, ok := v.handles[handle] + if !ok { panic(fmt.Sprintf("invalid pointer handle: %p", handle)) } - ptr := v.handles[slot] - - v.RUnlock() - return ptr } |
