1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2024-11-27 09:12:53 +00:00

Moreatomic: Cave in and use upgradable mutex over sync.Map

This commit is contained in:
diamondburned 2020-12-18 23:47:47 -08:00
parent f11edb7260
commit 3ddb472644
3 changed files with 23 additions and 23 deletions

1
go.mod
View file

@ -5,6 +5,7 @@ go 1.13
require (
github.com/gorilla/schema v1.2.0
github.com/gorilla/websocket v1.4.2
github.com/kawasin73/umutex v0.2.1 // indirect
github.com/pkg/errors v0.9.1
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13 // indirect

2
go.sum
View file

@ -2,6 +2,8 @@ github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/kawasin73/umutex v0.2.1 h1:Onkzz3LKs1HThskVwdhhBocqdRQqwCZ03quDJzuPzPo=
github.com/kawasin73/umutex v0.2.1/go.mod h1:A02N2muKVFMvFlp5c+hBycgdH964YtieGs+7mYB16NU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=

View file

@ -1,14 +1,12 @@
package moreatomic
import (
"sync"
"sync/atomic"
)
import "github.com/kawasin73/umutex"
// Map is a thread-safe map that is a wrapper around sync.Map with slight API
// additions.
type Map struct {
smap atomic.Value
upmu umutex.UMutex
smap map[interface{}]interface{}
ctor func() interface{}
}
@ -17,27 +15,33 @@ type sentinelType struct{}
var sentinel = sentinelType{}
func NewMap(ctor func() interface{}) *Map {
smap := atomic.Value{}
smap.Store(&sync.Map{})
return &Map{smap, ctor}
return &Map{
smap: map[interface{}]interface{}{},
ctor: 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{})
sm.upmu.Lock()
sm.smap = map[interface{}]interface{}{}
sm.upmu.Unlock()
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)
sm.upmu.RLock()
defer sm.upmu.RUnlock()
lv, loaded = smap.LoadOrStore(k, sentinel)
lv, loaded = sm.smap[k]
if !loaded {
lv = sm.ctor()
smap.Store(k, lv)
sm.upmu.Upgrade()
sm.smap[k] = lv
}
return
@ -46,16 +50,9 @@ func (sm *Map) LoadOrStore(k interface{}) (lv interface{}, loaded bool) {
// 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)
sm.upmu.RLock()
defer sm.upmu.RUnlock()
for {
lv, ok = smap.Load(k)
if !ok {
return nil, false
}
if lv != sentinel {
return lv, true
}
}
lv, ok = sm.smap[k]
return
}