Skip to content

Commit

Permalink
Merge pull request #64 from flier/feature/handleMap
Browse files Browse the repository at this point in the history
reducing lock conflicts with handleMap
  • Loading branch information
flier authored Dec 1, 2024
2 parents 717fbfe + 3df6eca commit b369d39
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 55 deletions.
16 changes: 0 additions & 16 deletions internal/handle/go1_15.go

This file was deleted.

14 changes: 0 additions & 14 deletions internal/handle/go1_17.go

This file was deleted.

18 changes: 0 additions & 18 deletions internal/handle/go1_9.go

This file was deleted.

40 changes: 33 additions & 7 deletions internal/handle/handle.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
//go:build !go1.17
// +build !go1.17

// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package handle

import (
"runtime"
"strconv"
"sync"
"sync/atomic"
)
Expand Down Expand Up @@ -78,22 +77,49 @@ func New(v interface{}) Handle {
panic("runtime/cgo: ran out of handle space")
}

handles.Store(h, v)
handles(Handle(h)).Store(h, v)

return Handle(h)
}

// Value returns the associated Go value for a valid handle.
//
// The method panics if the handle is invalid.
func (h Handle) Value() interface{} {
v, ok := handles.Load(uintptr(h))
v, ok := handles(h).Load(uintptr(h))
if !ok {
panic("runtime/cgo: misuse of an invalid Handle")
}
return v
}

// Delete invalidates a handle.
// This method should only be called once the program no longer needs to pass the handle to C
// and the C code no longer has a copy of the handle value.
//
// The method panics if the handle is invalid.
func (h Handle) Delete() {
_, ok := handles(h).LoadAndDelete(uintptr(h))
if !ok {
panic("runtime/cgo: misuse of an invalid Handle")
}
}

func handles(h Handle) *sync.Map {
return &handleMap[uintptr(h)%uintptr(len(handleMap))]
}

var (
handles = sync.Map{} // map[Handle]interface{}
handleIdx uintptr // atomic
mapSize = "" // --ldflags="-X 'github.com/flier/gohs/internal/handle.mapSize=64'"
handleMap = newHandleMap() // []map[Handle]interface{}
handleIdx uintptr // atomic
)

func newHandleMap() []sync.Map {
n, err := strconv.Atoi(mapSize)
if err != nil {
n = runtime.NumCPU() * 2
}

return make([]sync.Map, n)
}

0 comments on commit b369d39

Please sign in to comment.