mirror of
https://github.com/hashicorp/vault.git
synced 2025-12-25 11:21:11 +01:00
* 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>
104 lines
2.4 KiB
Go
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
|
|
}
|