mirror of
https://github.com/nabbar/golib.git
synced 2025-12-24 11:51:02 +08:00
Package atomic:
- new package to simplify usage of atomic.Value & sync map by using generic struct/interface with cast - add generic function to cast model
This commit is contained in:
47
atomic/cast.go
Normal file
47
atomic/cast.go
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2024 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package atomic
|
||||
|
||||
import "reflect"
|
||||
|
||||
func Cast[M any](src any) (model M, casted bool) {
|
||||
if reflect.DeepEqual(src, model) {
|
||||
return model, false
|
||||
} else if v, k := src.(M); !k {
|
||||
return model, false
|
||||
} else {
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
|
||||
func IsEmpty[M any](src any) bool {
|
||||
if _, k := Cast[M](src); !k {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
45
atomic/default.go
Normal file
45
atomic/default.go
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2024 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package atomic
|
||||
|
||||
type defaultValue[T any] interface {
|
||||
GetDefault() T
|
||||
}
|
||||
|
||||
type defVal[T any] struct {
|
||||
v T
|
||||
}
|
||||
|
||||
func (d *defVal[T]) GetDefault() T {
|
||||
return d.v
|
||||
}
|
||||
|
||||
func newDefault[T any](def T) *defVal[T] {
|
||||
return &defVal[T]{
|
||||
v: def,
|
||||
}
|
||||
}
|
||||
108
atomic/interface.go
Normal file
108
atomic/interface.go
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2024 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package atomic
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
type Value[T any] interface {
|
||||
SetDefaultLoad(def T)
|
||||
SetDefaultStore(def T)
|
||||
|
||||
Load() (val T)
|
||||
Store(val T)
|
||||
Swap(new T) (old T)
|
||||
CompareAndSwap(old, new T) (swapped bool)
|
||||
}
|
||||
|
||||
type Map[K comparable] interface {
|
||||
Load(key K) (value any, ok bool)
|
||||
Store(key K, value any)
|
||||
|
||||
LoadOrStore(key K, value any) (actual any, loaded bool)
|
||||
LoadAndDelete(key K) (value any, loaded bool)
|
||||
|
||||
Delete(key K)
|
||||
Swap(key K, value any) (previous any, loaded bool)
|
||||
|
||||
CompareAndSwap(key K, old, new any) bool
|
||||
CompareAndDelete(key K, old any) (deleted bool)
|
||||
|
||||
Range(f func(key K, value any) bool)
|
||||
}
|
||||
|
||||
type MapTyped[K comparable, V any] interface {
|
||||
Load(key K) (value V, ok bool)
|
||||
Store(key K, value V)
|
||||
|
||||
LoadOrStore(key K, value V) (actual V, loaded bool)
|
||||
LoadAndDelete(key K) (value V, loaded bool)
|
||||
|
||||
Delete(key K)
|
||||
Swap(key K, value V) (previous V, loaded bool)
|
||||
|
||||
CompareAndSwap(key K, old, new V) bool
|
||||
CompareAndDelete(key K, old V) (deleted bool)
|
||||
|
||||
Range(f func(key K, value V) bool)
|
||||
}
|
||||
|
||||
func NewValue[T any]() Value[T] {
|
||||
var (
|
||||
tmp1 T
|
||||
tmp2 T
|
||||
)
|
||||
|
||||
return NewValueDefault[T](tmp1, tmp2)
|
||||
}
|
||||
|
||||
func NewValueDefault[T any](load, store T) Value[T] {
|
||||
o := &val[T]{
|
||||
av: new(atomic.Value),
|
||||
dl: new(atomic.Value),
|
||||
ds: new(atomic.Value),
|
||||
}
|
||||
|
||||
o.SetDefaultLoad(load)
|
||||
o.SetDefaultStore(store)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func NewMapAny[K comparable]() Map[K] {
|
||||
return &ma[K]{
|
||||
m: sync.Map{},
|
||||
}
|
||||
}
|
||||
|
||||
func NewMapTyped[K comparable, V any]() MapTyped[K, V] {
|
||||
return &mt[K, V]{
|
||||
m: NewMapAny[K](),
|
||||
}
|
||||
}
|
||||
83
atomic/mapany.go
Normal file
83
atomic/mapany.go
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2024 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package atomic
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type ma[K comparable] struct {
|
||||
m sync.Map
|
||||
}
|
||||
|
||||
func (o *ma[K]) Load(key K) (value any, ok bool) {
|
||||
return o.m.Load(key)
|
||||
}
|
||||
|
||||
func (o *ma[K]) Store(key K, value any) {
|
||||
o.m.Store(key, value)
|
||||
}
|
||||
|
||||
func (o *ma[K]) LoadOrStore(key K, value any) (actual any, loaded bool) {
|
||||
return o.m.LoadOrStore(key, value)
|
||||
}
|
||||
|
||||
func (o *ma[K]) LoadAndDelete(key K) (value any, loaded bool) {
|
||||
return o.m.LoadAndDelete(key)
|
||||
}
|
||||
|
||||
func (o *ma[K]) Delete(key K) {
|
||||
o.m.Delete(key)
|
||||
}
|
||||
|
||||
func (o *ma[K]) Swap(key K, value any) (previous any, loaded bool) {
|
||||
return o.m.Swap(key, value)
|
||||
}
|
||||
|
||||
func (o *ma[K]) CompareAndSwap(key K, old, new any) bool {
|
||||
return o.m.CompareAndSwap(key, old, new)
|
||||
}
|
||||
|
||||
func (o *ma[K]) CompareAndDelete(key K, old any) (deleted bool) {
|
||||
return o.m.CompareAndDelete(key, old)
|
||||
}
|
||||
|
||||
func (o *ma[K]) Range(f func(key K, value any) bool) {
|
||||
o.m.Range(func(key, value any) bool {
|
||||
var (
|
||||
l bool
|
||||
k K
|
||||
)
|
||||
|
||||
if k, l = Cast[K](key); !l {
|
||||
o.m.Delete(key)
|
||||
return true
|
||||
}
|
||||
|
||||
return f(k, value)
|
||||
})
|
||||
}
|
||||
91
atomic/synmap.go
Normal file
91
atomic/synmap.go
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2024 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package atomic
|
||||
|
||||
type mt[K comparable, V any] struct {
|
||||
m Map[K]
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) cast(in any) (value V, ok bool) {
|
||||
return Cast[V](in)
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) castBool(in any, chk bool) (value V, ok bool) {
|
||||
if chk {
|
||||
return Cast[V](in)
|
||||
} else {
|
||||
return value, false
|
||||
}
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) Load(key K) (value V, ok bool) {
|
||||
return o.castBool(o.m.Load(key))
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) Store(key K, value V) {
|
||||
o.m.Store(key, value)
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
|
||||
return o.castBool(o.m.LoadOrStore(key, value))
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) LoadAndDelete(key K) (value V, loaded bool) {
|
||||
return o.castBool(o.m.LoadAndDelete(key))
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) Delete(key K) {
|
||||
o.m.Delete(key)
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) Swap(key K, value V) (previous V, loaded bool) {
|
||||
return o.castBool(o.m.Swap(key, value))
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) CompareAndSwap(key K, old, new V) bool {
|
||||
return o.m.CompareAndSwap(key, old, new)
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) CompareAndDelete(key K, old V) (deleted bool) {
|
||||
return o.m.CompareAndDelete(key, old)
|
||||
}
|
||||
|
||||
func (o *mt[K, V]) Range(f func(key K, value V) bool) {
|
||||
o.m.Range(func(key K, value any) bool {
|
||||
var (
|
||||
l bool
|
||||
v V
|
||||
)
|
||||
|
||||
if v, l = Cast[V](value); !l {
|
||||
o.m.Delete(key)
|
||||
return true
|
||||
}
|
||||
|
||||
return f(key, v)
|
||||
})
|
||||
}
|
||||
102
atomic/value.go
Normal file
102
atomic/value.go
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2024 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package atomic
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
type val[T any] struct {
|
||||
av *atomic.Value // atomic value of T
|
||||
dl *atomic.Value // default value for load
|
||||
ds *atomic.Value // default value for store
|
||||
}
|
||||
|
||||
func (o *val[T]) SetDefaultLoad(def T) {
|
||||
o.dl.Store(newDefault[T](def))
|
||||
}
|
||||
|
||||
func (o *val[T]) SetDefaultStore(def T) {
|
||||
o.ds.Store(newDefault[T](def))
|
||||
}
|
||||
|
||||
func (o *val[T]) getDefault(i any) T {
|
||||
if v, k := Cast[defaultValue[T]](i); !k {
|
||||
var tmp T
|
||||
return tmp
|
||||
} else {
|
||||
return v.GetDefault()
|
||||
}
|
||||
}
|
||||
|
||||
func (o *val[T]) getDefaultLoad() T {
|
||||
return o.getDefault(o.dl.Load())
|
||||
}
|
||||
|
||||
func (o *val[T]) getDefaultStore() T {
|
||||
return o.getDefault(o.ds.Load())
|
||||
}
|
||||
|
||||
func (o *val[T]) Load() (val T) {
|
||||
if v, k := Cast[T](o.av.Load()); !k {
|
||||
return o.getDefaultLoad()
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *val[T]) Store(val T) {
|
||||
if IsEmpty[T](val) {
|
||||
o.av.Store(o.getDefaultStore())
|
||||
} else {
|
||||
o.av.Store(val)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *val[T]) Swap(new T) (old T) {
|
||||
if IsEmpty[T](new) {
|
||||
new = o.getDefaultStore()
|
||||
}
|
||||
|
||||
if v, k := Cast[T](o.av.Swap(new)); !k {
|
||||
return o.getDefaultLoad()
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *val[T]) CompareAndSwap(old, new T) (swapped bool) {
|
||||
if IsEmpty[T](old) {
|
||||
old = o.getDefaultStore()
|
||||
}
|
||||
|
||||
if IsEmpty[T](new) {
|
||||
new = o.getDefaultStore()
|
||||
}
|
||||
|
||||
return o.av.CompareAndSwap(old, new)
|
||||
}
|
||||
Reference in New Issue
Block a user