mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-17 03:57:01 +02:00
The upcoming event main plugin will use a very similar pattern as the database plugin map, so it makes sense to refactor this and move this map out. It also cleans up the database plugin backend so that it does not have to keep track of the lock. Co-authored-by: Tom Proctor <tomhjp@users.noreply.github.com>
87 lines
1.9 KiB
Go
87 lines
1.9 KiB
Go
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
|
|
}
|
|
|
|
// 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
|
|
}
|