mirror of
https://github.com/golang/go
synced 2024-11-26 07:38:00 -07:00
internal/sync: use normal comparison for keys in HashTrieMap
There's are unnecessary calls to the key's equal function -- we can just leverage the language here. Leave the values alone for now, we want to relax that constraint. Change-Id: Iccfaef030a2a29b6a24a7da41e5e816b70091c7c Reviewed-on: https://go-review.googlesource.com/c/go/+/594060 Auto-Submit: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
e51a33a0ef
commit
36b5b053be
@ -18,7 +18,6 @@ import (
|
|||||||
type HashTrieMap[K, V comparable] struct {
|
type HashTrieMap[K, V comparable] struct {
|
||||||
root *indirect[K, V]
|
root *indirect[K, V]
|
||||||
keyHash hashFunc
|
keyHash hashFunc
|
||||||
keyEqual equalFunc
|
|
||||||
valEqual equalFunc
|
valEqual equalFunc
|
||||||
seed uintptr
|
seed uintptr
|
||||||
}
|
}
|
||||||
@ -30,7 +29,6 @@ func NewHashTrieMap[K, V comparable]() *HashTrieMap[K, V] {
|
|||||||
ht := &HashTrieMap[K, V]{
|
ht := &HashTrieMap[K, V]{
|
||||||
root: newIndirectNode[K, V](nil),
|
root: newIndirectNode[K, V](nil),
|
||||||
keyHash: mapType.Hasher,
|
keyHash: mapType.Hasher,
|
||||||
keyEqual: mapType.Key.Equal,
|
|
||||||
valEqual: mapType.Elem.Equal,
|
valEqual: mapType.Elem.Equal,
|
||||||
seed: uintptr(runtime_rand()),
|
seed: uintptr(runtime_rand()),
|
||||||
}
|
}
|
||||||
@ -56,7 +54,7 @@ func (ht *HashTrieMap[K, V]) Load(key K) (value V, ok bool) {
|
|||||||
return *new(V), false
|
return *new(V), false
|
||||||
}
|
}
|
||||||
if n.isEntry {
|
if n.isEntry {
|
||||||
return n.entry().lookup(key, ht.keyEqual)
|
return n.entry().lookup(key)
|
||||||
}
|
}
|
||||||
i = n.indirect()
|
i = n.indirect()
|
||||||
}
|
}
|
||||||
@ -91,7 +89,7 @@ func (ht *HashTrieMap[K, V]) LoadOrStore(key K, value V) (result V, loaded bool)
|
|||||||
// We found an existing entry, which is as far as we can go.
|
// We found an existing entry, which is as far as we can go.
|
||||||
// If it stays this way, we'll have to replace it with an
|
// If it stays this way, we'll have to replace it with an
|
||||||
// indirect node.
|
// indirect node.
|
||||||
if v, ok := n.entry().lookup(key, ht.keyEqual); ok {
|
if v, ok := n.entry().lookup(key); ok {
|
||||||
return v, true
|
return v, true
|
||||||
}
|
}
|
||||||
haveInsertPoint = true
|
haveInsertPoint = true
|
||||||
@ -123,7 +121,7 @@ func (ht *HashTrieMap[K, V]) LoadOrStore(key K, value V) (result V, loaded bool)
|
|||||||
var oldEntry *entry[K, V]
|
var oldEntry *entry[K, V]
|
||||||
if n != nil {
|
if n != nil {
|
||||||
oldEntry = n.entry()
|
oldEntry = n.entry()
|
||||||
if v, ok := oldEntry.lookup(key, ht.keyEqual); ok {
|
if v, ok := oldEntry.lookup(key); ok {
|
||||||
// Easy case: by loading again, it turns out exactly what we wanted is here!
|
// Easy case: by loading again, it turns out exactly what we wanted is here!
|
||||||
return v, true
|
return v, true
|
||||||
}
|
}
|
||||||
@ -192,7 +190,7 @@ func (ht *HashTrieMap[K, V]) CompareAndDelete(key K, old V) (deleted bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try to delete the entry.
|
// Try to delete the entry.
|
||||||
e, deleted := n.entry().compareAndDelete(key, old, ht.keyEqual, ht.valEqual)
|
e, deleted := n.entry().compareAndDelete(key, old, ht.valEqual)
|
||||||
if !deleted {
|
if !deleted {
|
||||||
// Nothing was actually deleted, which means the node is no longer there.
|
// Nothing was actually deleted, which means the node is no longer there.
|
||||||
i.mu.Unlock()
|
i.mu.Unlock()
|
||||||
@ -250,7 +248,7 @@ func (ht *HashTrieMap[K, V]) find(key K, hash uintptr) (i *indirect[K, V], hashS
|
|||||||
}
|
}
|
||||||
if n.isEntry {
|
if n.isEntry {
|
||||||
// We found an entry. Check if it matches.
|
// We found an entry. Check if it matches.
|
||||||
if _, ok := n.entry().lookup(key, ht.keyEqual); !ok {
|
if _, ok := n.entry().lookup(key); !ok {
|
||||||
// No match, comparison failed.
|
// No match, comparison failed.
|
||||||
i = nil
|
i = nil
|
||||||
n = nil
|
n = nil
|
||||||
@ -362,9 +360,9 @@ func newEntryNode[K, V comparable](key K, value V) *entry[K, V] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *entry[K, V]) lookup(key K, equal equalFunc) (V, bool) {
|
func (e *entry[K, V]) lookup(key K) (V, bool) {
|
||||||
for e != nil {
|
for e != nil {
|
||||||
if equal(unsafe.Pointer(&e.key), abi.NoEscape(unsafe.Pointer(&key))) {
|
if e.key == key {
|
||||||
return e.value, true
|
return e.value, true
|
||||||
}
|
}
|
||||||
e = e.overflow.Load()
|
e = e.overflow.Load()
|
||||||
@ -376,17 +374,15 @@ func (e *entry[K, V]) lookup(key K, equal equalFunc) (V, bool) {
|
|||||||
// equal. Returns the new entry chain and whether or not anything was deleted.
|
// equal. Returns the new entry chain and whether or not anything was deleted.
|
||||||
//
|
//
|
||||||
// compareAndDelete must be called under the mutex of the indirect node which e is a child of.
|
// compareAndDelete must be called under the mutex of the indirect node which e is a child of.
|
||||||
func (head *entry[K, V]) compareAndDelete(key K, value V, keyEqual, valEqual equalFunc) (*entry[K, V], bool) {
|
func (head *entry[K, V]) compareAndDelete(key K, value V, valEqual equalFunc) (*entry[K, V], bool) {
|
||||||
if keyEqual(unsafe.Pointer(&head.key), abi.NoEscape(unsafe.Pointer(&key))) &&
|
if head.key == key && valEqual(unsafe.Pointer(&head.value), abi.NoEscape(unsafe.Pointer(&value))) {
|
||||||
valEqual(unsafe.Pointer(&head.value), abi.NoEscape(unsafe.Pointer(&value))) {
|
|
||||||
// Drop the head of the list.
|
// Drop the head of the list.
|
||||||
return head.overflow.Load(), true
|
return head.overflow.Load(), true
|
||||||
}
|
}
|
||||||
i := &head.overflow
|
i := &head.overflow
|
||||||
e := i.Load()
|
e := i.Load()
|
||||||
for e != nil {
|
for e != nil {
|
||||||
if keyEqual(unsafe.Pointer(&e.key), abi.NoEscape(unsafe.Pointer(&key))) &&
|
if e.key == key && valEqual(unsafe.Pointer(&e.value), abi.NoEscape(unsafe.Pointer(&value))) {
|
||||||
valEqual(unsafe.Pointer(&e.value), abi.NoEscape(unsafe.Pointer(&value))) {
|
|
||||||
i.Store(e.overflow.Load())
|
i.Store(e.overflow.Load())
|
||||||
return head, true
|
return head, true
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user