diff options
Diffstat (limited to 'vendor/github.com/cornelk/hashmap/store.go')
-rw-r--r-- | vendor/github.com/cornelk/hashmap/store.go | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/vendor/github.com/cornelk/hashmap/store.go b/vendor/github.com/cornelk/hashmap/store.go new file mode 100644 index 000000000..8fc1d5986 --- /dev/null +++ b/vendor/github.com/cornelk/hashmap/store.go @@ -0,0 +1,45 @@ +package hashmap + +import ( + "sync/atomic" + "unsafe" +) + +type store[Key comparable, Value any] struct { + keyShifts uintptr // Pointer size - log2 of array size, to be used as index in the data array + count atomic.Uintptr // count of filled elements in the slice + array unsafe.Pointer // pointer to slice data array + index []*ListElement[Key, Value] // storage for the slice for the garbage collector to not clean it up +} + +// item returns the item for the given hashed key. +func (s *store[Key, Value]) item(hashedKey uintptr) *ListElement[Key, Value] { + index := hashedKey >> s.keyShifts + ptr := (*unsafe.Pointer)(unsafe.Pointer(uintptr(s.array) + index*intSizeBytes)) + item := (*ListElement[Key, Value])(atomic.LoadPointer(ptr)) + return item +} + +// adds an item to the index if needed and returns the new item counter if it changed, otherwise 0. +func (s *store[Key, Value]) addItem(item *ListElement[Key, Value]) uintptr { + index := item.keyHash >> s.keyShifts + ptr := (*unsafe.Pointer)(unsafe.Pointer(uintptr(s.array) + index*intSizeBytes)) + + for { // loop until the smallest key hash is in the index + element := (*ListElement[Key, Value])(atomic.LoadPointer(ptr)) // get the current item in the index + if element == nil { // no item yet at this index + if atomic.CompareAndSwapPointer(ptr, nil, unsafe.Pointer(item)) { + return s.count.Add(1) + } + continue // a new item was inserted concurrently, retry + } + + if item.keyHash < element.keyHash { + // the new item is the smallest for this index? + if !atomic.CompareAndSwapPointer(ptr, unsafe.Pointer(element), unsafe.Pointer(item)) { + continue // a new item was inserted concurrently, retry + } + } + return 0 + } +} |