95 lines
2.0 KiB
Go
95 lines
2.0 KiB
Go
package util
|
|
|
|
import (
|
|
"sync"
|
|
)
|
|
|
|
// https://sreramk.medium.com/go-inside-sync-map-how-does-sync-map-work-internally-97e87b8e6bf
|
|
|
|
// RWMutexMap is an implementation of mapInterface using a sync.RWMutex.
|
|
type RWMutexMap struct {
|
|
mu sync.RWMutex
|
|
dirty map[interface{}]interface{}
|
|
}
|
|
|
|
func (m *RWMutexMap) Load(key interface{}) (value interface{}, ok bool) {
|
|
m.mu.RLock()
|
|
value, ok = m.dirty[key]
|
|
m.mu.RUnlock()
|
|
return
|
|
}
|
|
|
|
func (m *RWMutexMap) Store(key, value interface{}) {
|
|
m.mu.Lock()
|
|
if m.dirty == nil {
|
|
m.dirty = make(map[interface{}]interface{})
|
|
}
|
|
m.dirty[key] = value
|
|
m.mu.Unlock()
|
|
}
|
|
|
|
func (m *RWMutexMap) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) {
|
|
m.mu.Lock()
|
|
actual, loaded = m.dirty[key]
|
|
if !loaded {
|
|
actual = value
|
|
if m.dirty == nil {
|
|
m.dirty = make(map[interface{}]interface{})
|
|
}
|
|
m.dirty[key] = value
|
|
}
|
|
m.mu.Unlock()
|
|
return actual, loaded
|
|
}
|
|
|
|
func (m *RWMutexMap) LoadAndDelete(key interface{}) (value interface{}, loaded bool) {
|
|
m.mu.Lock()
|
|
value, loaded = m.dirty[key]
|
|
if !loaded {
|
|
m.mu.Unlock()
|
|
return nil, false
|
|
}
|
|
delete(m.dirty, key)
|
|
m.mu.Unlock()
|
|
return value, loaded
|
|
}
|
|
|
|
func (m *RWMutexMap) Delete(key interface{}) {
|
|
m.mu.Lock()
|
|
delete(m.dirty, key)
|
|
m.mu.Unlock()
|
|
}
|
|
|
|
func (m *RWMutexMap) Range(f func(key, value interface{}) (shouldContinue bool)) {
|
|
m.mu.RLock()
|
|
keys := make([]interface{}, 0, len(m.dirty))
|
|
for k := range m.dirty {
|
|
keys = append(keys, k)
|
|
}
|
|
m.mu.RUnlock()
|
|
|
|
for _, k := range keys {
|
|
v, ok := m.Load(k)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if !f(k, v) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// MapInterface is the interface Map implements.
|
|
type MapInterface interface {
|
|
Load(interface{}) (interface{}, bool)
|
|
Store(key, value interface{})
|
|
LoadOrStore(key, value interface{}) (actual interface{}, loaded bool)
|
|
LoadAndDelete(key interface{}) (value interface{}, loaded bool)
|
|
Delete(interface{})
|
|
Range(func(key, value interface{}) (shouldContinue bool))
|
|
}
|
|
|
|
func NewRWMutexMap() MapInterface {
|
|
return &RWMutexMap{}
|
|
}
|