mirror of
https://github.com/diamondburned/arikawa.git
synced 2024-11-16 11:54:29 +00:00
diamondburned
c6679dc52c
This commit refactors the Store interface in State into smaller interfaces in package store. These interfaces are combined into one structure called a "Cabinet". The default implementation of those interfaces have been rewritten in package defaultstore, while the old no-op implementation stays with the store package. This commit also omitted several state handlers for user events, as it is unclear what they are actually structured like.
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{}) (v interface{}, loaded bool) {
|
|
smap := sm.smap.Load().(*sync.Map)
|
|
|
|
v, loaded = smap.LoadOrStore(k, sentinel)
|
|
if loaded {
|
|
v = sm.ctor()
|
|
smap.Store(k, v)
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
}
|