mirror of
https://github.com/diamondburned/arikawa.git
synced 2024-12-03 20:32:55 +00:00
62 lines
1.2 KiB
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
|
|
}
|
|
}
|
|
}
|