vault/helper/syncmap/syncmap.go
Vault Automation 0c6c13dd38
license: update headers to IBM Corp. (#10229) (#10233)
* license: update headers to IBM Corp.
* `make proto`
* update offset because source file changed

Signed-off-by: Ryan Cragun <me@ryan.ec>
Co-authored-by: Ryan Cragun <me@ryan.ec>
2025-10-21 15:20:20 -06:00

104 lines
2.4 KiB
Go

// Copyright IBM Corp. 2016, 2025
// SPDX-License-Identifier: BUSL-1.1
package syncmap
import "sync"
// SyncMap implements a map similar to sync.Map, but with generics and with an equality
// in the values specified by an "ID()" method.
type SyncMap[K comparable, V IDer] struct {
// lock is used to synchronize access to the map
lock sync.RWMutex
// data holds the actual data
data map[K]V
}
// NewSyncMap returns a new, empty SyncMap.
func NewSyncMap[K comparable, V IDer]() *SyncMap[K, V] {
return &SyncMap[K, V]{
data: make(map[K]V),
}
}
// Get returns the value for the given key.
func (m *SyncMap[K, V]) Get(k K) V {
m.lock.RLock()
defer m.lock.RUnlock()
return m.data[k]
}
// Pop deletes and returns the value for the given key, if it exists.
func (m *SyncMap[K, V]) Pop(k K) V {
m.lock.Lock()
defer m.lock.Unlock()
v, ok := m.data[k]
if ok {
delete(m.data, k)
}
return v
}
// PopIfEqual deletes and returns the value for the given key, if it exists
// and only if the ID is equal to the provided string.
func (m *SyncMap[K, V]) PopIfEqual(k K, id string) V {
m.lock.Lock()
defer m.lock.Unlock()
v, ok := m.data[k]
if ok && v.ID() == id {
delete(m.data, k)
return v
}
var zero V
return zero
}
// Put adds the given key-value pair to the map and returns the previous value, if any.
func (m *SyncMap[K, V]) Put(k K, v V) V {
m.lock.Lock()
defer m.lock.Unlock()
oldV := m.data[k]
m.data[k] = v
return oldV
}
// PutIfEmpty adds the given key-value pair to the map only if there is no value already in it,
// and returns the new value and true if so.
// If there is already a value, it returns the existing value and false.
func (m *SyncMap[K, V]) PutIfEmpty(k K, v V) (V, bool) {
m.lock.Lock()
defer m.lock.Unlock()
oldV, ok := m.data[k]
if ok {
return oldV, false
}
m.data[k] = v
return v, true
}
// Clear deletes all entries from the map, and returns the previous map.
func (m *SyncMap[K, V]) Clear() map[K]V {
m.lock.Lock()
defer m.lock.Unlock()
old := m.data
m.data = make(map[K]V)
return old
}
// Values returns a copy of all values in the map.
func (m *SyncMap[K, V]) Values() []V {
m.lock.RLock()
defer m.lock.RUnlock()
values := make([]V, 0, len(m.data))
for _, v := range m.data {
values = append(values, v)
}
return values
}
// IDer is used to extract an ID that SyncMap uses for equality checking.
type IDer interface {
ID() string
}