91 lines
1.5 KiB
Go
91 lines
1.5 KiB
Go
package safe
|
|
|
|
import (
|
|
"maps"
|
|
"sync"
|
|
)
|
|
|
|
// SyncMap is a thread-safe map
|
|
type SyncMap[K comparable, V any] struct {
|
|
sync.RWMutex
|
|
m map[K]V
|
|
}
|
|
|
|
// NewSyncMap creates a new thread-safe map
|
|
func NewSyncMap[K comparable, V any]() *SyncMap[K, V] {
|
|
return &SyncMap[K, V]{
|
|
m: make(map[K]V),
|
|
}
|
|
}
|
|
|
|
func (m *SyncMap[K, V]) Store(k K, v V) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
m.m[k] = v
|
|
}
|
|
|
|
func (m *SyncMap[K, V]) Load(k K) (v V, ok bool) {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
v, ok = m.m[k]
|
|
return
|
|
}
|
|
|
|
// LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns the given value.
|
|
func (m *SyncMap[K, V]) LoadOrStore(k K, v V) (actual V, loaded bool) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
actual, loaded = m.m[k]
|
|
if loaded {
|
|
return
|
|
}
|
|
m.m[k] = v
|
|
return v, false
|
|
}
|
|
|
|
// LoadAndDelete deletes the value for a key, and returns the previous value if any.
|
|
func (m *SyncMap[K, V]) LoadAndDelete(k K) (v V, loaded bool) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
v, loaded = m.m[k]
|
|
if loaded {
|
|
delete(m.m, k)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (m *SyncMap[K, V]) Delete(k K) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
delete(m.m, k)
|
|
}
|
|
|
|
func (m *SyncMap[K, V]) Clear() {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
clear(m.m)
|
|
}
|
|
|
|
func (m *SyncMap[K, V]) Len() int {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
return len(m.m)
|
|
}
|
|
|
|
func (m *SyncMap[K, V]) Clone() map[K]V {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
return maps.Clone(m.m)
|
|
}
|
|
|
|
func (m *SyncMap[K, V]) Range(f func(k K, v V) bool) {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
|
|
for k, v := range m.m {
|
|
if !f(k, v) {
|
|
break
|
|
}
|
|
}
|
|
}
|