1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2024-11-09 00:14:57 +00:00
arikawa/internal/moreatomic/syncmap.go

62 lines
1.2 KiB
Go

package moreatomic
import (
"sync"
"sync/atomic"
)
// Map is a thread-safe map that is a wrapper around sync.Map with slight API
// additions.
type Map struct {
smap atomic.Value
ctor func() interface{}
}
type sentinelType struct{}
var sentinel = sentinelType{}
func NewMap(ctor func() interface{}) *Map {
smap := atomic.Value{}
smap.Store(&sync.Map{})
return &Map{smap, ctor}
}
// Reset swaps the internal map out with a fresh one, dropping the old map. This
// method never errors.
func (sm *Map) Reset() error {
sm.smap.Store(&sync.Map{})
return nil
}
// LoadOrStore loads an existing value or stores a new value created from the
// given constructor then return that value.
func (sm *Map) LoadOrStore(k interface{}) (lv interface{}, loaded bool) {
smap := sm.smap.Load().(*sync.Map)
lv, loaded = smap.LoadOrStore(k, sentinel)
if !loaded {
lv = sm.ctor()
smap.Store(k, lv)
}
return
}
// Load loads an existing value; it returns ok set to false if there is no
// value with that key.
func (sm *Map) Load(k interface{}) (lv interface{}, ok bool) {
smap := sm.smap.Load().(*sync.Map)
for {
lv, ok = smap.Load(k)
if !ok {
return nil, false
}
if lv != sentinel {
return lv, true
}
}
}