2023-02-17 15:36:54 +00:00
|
|
|
package reload
|
|
|
|
|
2023-03-04 06:44:51 +00:00
|
|
|
import (
|
2023-11-12 13:39:04 +00:00
|
|
|
"github.com/fthvgb1/wp-go/helper"
|
2023-04-25 12:58:22 +00:00
|
|
|
"github.com/fthvgb1/wp-go/helper/number"
|
2023-10-14 06:57:57 +00:00
|
|
|
"github.com/fthvgb1/wp-go/helper/slice"
|
2023-03-04 06:44:51 +00:00
|
|
|
"github.com/fthvgb1/wp-go/safety"
|
2023-04-04 15:02:54 +00:00
|
|
|
"sync"
|
2023-03-04 06:44:51 +00:00
|
|
|
)
|
2023-02-17 15:36:54 +00:00
|
|
|
|
2023-10-14 06:57:57 +00:00
|
|
|
type queue struct {
|
|
|
|
fn func()
|
|
|
|
order float64
|
2023-10-23 14:32:20 +00:00
|
|
|
name string
|
2023-10-14 06:57:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
var mut = &sync.Mutex{}
|
2023-02-17 15:36:54 +00:00
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
func GetGlobeMutex() *sync.Mutex {
|
|
|
|
return mut
|
|
|
|
}
|
|
|
|
|
|
|
|
var waitReloadCalls = safety.NewSlice(make([]queue, 0))
|
|
|
|
var callMap = safety.NewMap[string, func()]()
|
|
|
|
|
|
|
|
var setFnVal = safety.NewMap[string, any]()
|
2023-03-06 15:43:58 +00:00
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
type SafetyVar[T, A any] struct {
|
|
|
|
Val *safety.Var[Val[T]]
|
|
|
|
Mutex sync.Mutex
|
2023-04-04 15:02:54 +00:00
|
|
|
}
|
2024-01-18 15:29:50 +00:00
|
|
|
type Val[T any] struct {
|
|
|
|
V T
|
|
|
|
Ok bool
|
2023-04-04 15:02:54 +00:00
|
|
|
}
|
2024-01-18 15:29:50 +00:00
|
|
|
type SafetyMap[K comparable, V, A any] struct {
|
|
|
|
Val *safety.Map[K, V]
|
|
|
|
Mutex sync.Mutex
|
2023-04-04 15:02:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var safetyMaps = safety.NewMap[string, any]()
|
|
|
|
var safetyMapLock = sync.Mutex{}
|
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
var deleteMapFn = safety.NewMap[string, func(any)]()
|
|
|
|
|
|
|
|
// GetValMap can get stored map value with namespace which called BuildSafetyMap, BuildMapFnWithConfirm, BuildMapFn, BuildMapFnWithAnyParams
|
|
|
|
func GetValMap[K comparable, V any](namespace string) (*safety.Map[K, V], bool) {
|
|
|
|
m, ok := safetyMaps.Load(namespace)
|
|
|
|
if !ok {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
v, ok := m.(*safety.Map[K, V])
|
|
|
|
return v, ok
|
|
|
|
}
|
2023-10-23 14:32:20 +00:00
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
func DeleteMapVal[T any](namespace string, key ...T) {
|
|
|
|
fn, ok := deleteMapFn.Load(namespace)
|
2023-10-27 12:51:46 +00:00
|
|
|
if !ok || len(key) < 1 {
|
2023-10-23 14:32:20 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
fn(key)
|
|
|
|
}
|
|
|
|
|
2024-01-18 16:14:04 +00:00
|
|
|
func Specifies(namespaces ...string) {
|
2023-10-24 08:06:59 +00:00
|
|
|
for _, namespace := range namespaces {
|
2024-01-18 15:29:50 +00:00
|
|
|
fn, ok := callMap.Load(namespace)
|
2023-10-24 08:06:59 +00:00
|
|
|
if !ok {
|
2023-10-24 08:07:48 +00:00
|
|
|
continue
|
2023-10-24 08:06:59 +00:00
|
|
|
}
|
|
|
|
fn()
|
2023-10-23 14:32:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
// BuildMapFnWithConfirm same as BuildMapFn
|
|
|
|
func BuildMapFnWithConfirm[K comparable, V, A any](namespace string, fn func(A) (V, bool), a ...any) func(key K, args A) V {
|
|
|
|
m := BuildSafetyMap[K, V, A](namespace, a...)
|
|
|
|
return func(key K, a A) V {
|
|
|
|
v, ok := m.Val.Load(key)
|
|
|
|
if ok {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
m.Mutex.Lock()
|
|
|
|
defer m.Mutex.Unlock()
|
|
|
|
v, ok = m.Val.Load(key)
|
|
|
|
if ok {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
v, ok = fn(a)
|
|
|
|
if ok {
|
|
|
|
m.Val.Store(key, v)
|
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-18 16:14:04 +00:00
|
|
|
// BuildMapFn build given fn with a new fn which returned value can be saved and flushed when called Reload or Specifies
|
2024-01-18 15:29:50 +00:00
|
|
|
// with namespace
|
|
|
|
//
|
|
|
|
// if give a float then can be reloaded early or lately, more bigger more earlier
|
|
|
|
//
|
|
|
|
// if give a bool false will not flushed when called Reload, then can called GetValMap to flush manually
|
|
|
|
func BuildMapFn[K comparable, V, A any](namespace string, fn func(A) V, a ...any) func(key K, args A) V {
|
|
|
|
m := BuildSafetyMap[K, V, A](namespace, a...)
|
2023-04-04 15:02:54 +00:00
|
|
|
return func(key K, a A) V {
|
2024-01-18 15:29:50 +00:00
|
|
|
v, ok := m.Val.Load(key)
|
|
|
|
if ok {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
m.Mutex.Lock()
|
|
|
|
defer m.Mutex.Unlock()
|
|
|
|
v, ok = m.Val.Load(key)
|
|
|
|
if ok {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
v = fn(a)
|
|
|
|
m.Val.Store(key, v)
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// BuildMapFnWithAnyParams same as BuildMapFn use multiple params
|
|
|
|
func BuildMapFnWithAnyParams[K comparable, V any](namespace string, fn func(...any) V, a ...any) func(key K, a ...any) V {
|
|
|
|
m := BuildSafetyMap[K, V, any](namespace, a...)
|
|
|
|
return func(key K, a ...any) V {
|
|
|
|
v, ok := m.Val.Load(key)
|
2023-04-04 15:02:54 +00:00
|
|
|
if ok {
|
|
|
|
return v
|
|
|
|
}
|
2024-01-18 15:29:50 +00:00
|
|
|
m.Mutex.Lock()
|
|
|
|
defer m.Mutex.Unlock()
|
|
|
|
v, ok = m.Val.Load(key)
|
2023-04-04 15:02:54 +00:00
|
|
|
if ok {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
v = fn(a)
|
2024-01-18 15:29:50 +00:00
|
|
|
m.Val.Store(key, v)
|
2023-04-04 15:02:54 +00:00
|
|
|
return v
|
2023-03-06 15:43:58 +00:00
|
|
|
}
|
2023-02-18 16:14:33 +00:00
|
|
|
}
|
2023-04-04 15:02:54 +00:00
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
func BuildSafetyMap[K comparable, V, A any](namespace string, args ...any) *SafetyMap[K, V, A] {
|
2023-04-04 15:02:54 +00:00
|
|
|
vv, ok := safetyMaps.Load(namespace)
|
2024-01-18 15:29:50 +00:00
|
|
|
var m *SafetyMap[K, V, A]
|
2023-03-18 05:17:21 +00:00
|
|
|
if ok {
|
2024-01-18 15:29:50 +00:00
|
|
|
m = vv.(*SafetyMap[K, V, A])
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
safetyMapLock.Lock()
|
|
|
|
defer safetyMapLock.Unlock()
|
|
|
|
vv, ok = safetyMaps.Load(namespace)
|
|
|
|
if ok {
|
|
|
|
m = vv.(*SafetyMap[K, V, A])
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
m = &SafetyMap[K, V, A]{safety.NewMap[K, V](), sync.Mutex{}}
|
|
|
|
ord, _ := parseArgs(args...)
|
|
|
|
autoFlush := helper.ParseArgs(true, args...)
|
|
|
|
deleteMapFn.Store(namespace, func(a any) {
|
|
|
|
k, ok := a.([]K)
|
|
|
|
if !ok && len(k) > 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, key := range k {
|
|
|
|
m.Val.Delete(key)
|
2023-04-04 15:02:54 +00:00
|
|
|
}
|
2024-01-18 15:29:50 +00:00
|
|
|
})
|
|
|
|
if autoFlush {
|
|
|
|
Push(func() {
|
|
|
|
m.Val.Flush()
|
|
|
|
}, ord, namespace)
|
2023-03-18 05:17:21 +00:00
|
|
|
}
|
2024-01-18 15:29:50 +00:00
|
|
|
safetyMaps.Store(namespace, m)
|
|
|
|
|
2023-04-04 15:02:54 +00:00
|
|
|
return m
|
2023-03-18 05:17:21 +00:00
|
|
|
}
|
2023-02-18 16:14:33 +00:00
|
|
|
|
2023-11-12 13:39:04 +00:00
|
|
|
func GetAnyValMapBy[K comparable, V, A any](namespace string, key K, a A, fn func(A) (V, bool), args ...any) V {
|
2024-01-18 15:29:50 +00:00
|
|
|
m := BuildSafetyMap[K, V, A](namespace, args...)
|
|
|
|
v, ok := m.Val.Load(key)
|
2023-03-04 06:44:51 +00:00
|
|
|
if ok {
|
|
|
|
return v
|
|
|
|
}
|
2024-01-18 15:29:50 +00:00
|
|
|
m.Mutex.Lock()
|
|
|
|
defer m.Mutex.Unlock()
|
|
|
|
v, ok = m.Val.Load(key)
|
2023-04-04 15:02:54 +00:00
|
|
|
if ok {
|
|
|
|
return v
|
|
|
|
}
|
2023-11-12 13:39:04 +00:00
|
|
|
v, ok = fn(a)
|
|
|
|
if ok {
|
2024-01-18 15:29:50 +00:00
|
|
|
m.Val.Store(key, v)
|
2023-11-12 13:39:04 +00:00
|
|
|
}
|
2023-03-04 06:44:51 +00:00
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
func BuildAnyVal[T, A any](namespace string, counter bool, args ...any) *SafetyVar[T, A] {
|
|
|
|
var vv *SafetyVar[T, A]
|
2023-04-04 15:02:54 +00:00
|
|
|
vvv, ok := safetyMaps.Load(namespace)
|
|
|
|
if ok {
|
2024-01-18 15:29:50 +00:00
|
|
|
vv = vvv.(*SafetyVar[T, A])
|
2023-04-04 15:02:54 +00:00
|
|
|
} else {
|
|
|
|
safetyMapLock.Lock()
|
2023-11-12 13:39:04 +00:00
|
|
|
defer safetyMapLock.Unlock()
|
2023-04-04 15:02:54 +00:00
|
|
|
vvv, ok = safetyMaps.Load(namespace)
|
|
|
|
if ok {
|
2024-01-18 15:29:50 +00:00
|
|
|
vv = vvv.(*SafetyVar[T, A])
|
2023-04-04 15:02:54 +00:00
|
|
|
} else {
|
2024-01-18 15:29:50 +00:00
|
|
|
v := Val[T]{}
|
|
|
|
vv = &SafetyVar[T, A]{safety.NewVar(v), sync.Mutex{}}
|
2023-10-23 14:32:20 +00:00
|
|
|
ord, _ := parseArgs(args...)
|
2023-04-04 15:02:54 +00:00
|
|
|
Push(func() {
|
|
|
|
vv.Val.Flush()
|
2023-10-23 14:32:20 +00:00
|
|
|
}, ord, namespace)
|
2023-04-04 15:02:54 +00:00
|
|
|
safetyMaps.Store(namespace, vv)
|
|
|
|
}
|
|
|
|
}
|
2023-04-25 12:58:22 +00:00
|
|
|
return vv
|
|
|
|
}
|
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
func GetAnyValBys[T, A any](namespace string, a A, fn func(A) (T, bool), args ...any) T {
|
|
|
|
var vv = BuildAnyVal[T, A](namespace, false, args...)
|
2023-04-25 12:58:22 +00:00
|
|
|
v := vv.Val.Load()
|
2024-01-18 15:29:50 +00:00
|
|
|
if v.Ok {
|
|
|
|
return v.V
|
2023-04-25 12:58:22 +00:00
|
|
|
}
|
2024-01-18 15:29:50 +00:00
|
|
|
vv.Mutex.Lock()
|
|
|
|
defer vv.Mutex.Unlock()
|
2023-04-25 12:58:22 +00:00
|
|
|
v = vv.Val.Load()
|
2024-01-18 15:29:50 +00:00
|
|
|
if v.Ok {
|
|
|
|
return v.V
|
2023-11-12 13:39:04 +00:00
|
|
|
}
|
2024-01-18 15:29:50 +00:00
|
|
|
v.V, v.Ok = fn(a)
|
|
|
|
vv.Val.Store(v)
|
|
|
|
return v.V
|
|
|
|
}
|
|
|
|
|
|
|
|
// BuildValFnWithConfirm same as BuildValFn
|
|
|
|
//
|
|
|
|
// if give a int and value bigger than 1 will be a times which built fn called return false
|
|
|
|
func BuildValFnWithConfirm[T, A any](namespace string, fn func(A) (T, bool), args ...any) func(A) T {
|
|
|
|
var vv = BuildAnyVal[T, A](namespace, false, args...)
|
2023-11-12 13:39:04 +00:00
|
|
|
tryTimes := helper.ParseArgs(1, args...)
|
2024-01-18 15:29:50 +00:00
|
|
|
var counter func() int
|
|
|
|
if tryTimes > 1 {
|
|
|
|
counter = number.Counters[int]()
|
|
|
|
}
|
|
|
|
return func(a A) T {
|
|
|
|
v := vv.Val.Load()
|
|
|
|
if v.Ok {
|
|
|
|
return v.V
|
|
|
|
}
|
|
|
|
vv.Mutex.Lock()
|
|
|
|
defer vv.Mutex.Unlock()
|
|
|
|
v = vv.Val.Load()
|
|
|
|
if v.Ok {
|
|
|
|
return v.V
|
|
|
|
}
|
|
|
|
v.V, v.Ok = fn(a)
|
|
|
|
if v.Ok {
|
|
|
|
vv.Val.Store(v)
|
|
|
|
return v.V
|
|
|
|
}
|
|
|
|
if counter == nil {
|
|
|
|
return v.V
|
|
|
|
}
|
|
|
|
times := counter()
|
|
|
|
if times >= tryTimes {
|
|
|
|
v.Ok = true
|
|
|
|
vv.Val.Store(v)
|
|
|
|
}
|
|
|
|
return v.V
|
2023-04-25 12:58:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-18 16:14:04 +00:00
|
|
|
// BuildValFn build given fn a new fn which return value can be saved and flushed when called Reload or Specifies
|
2024-01-18 15:29:50 +00:00
|
|
|
// with namespace.
|
|
|
|
//
|
|
|
|
// note: namespace should be not same as BuildMapFn and related fn, they stored same safety.Map[string,any].
|
|
|
|
//
|
|
|
|
// if give a float then can be reloaded early or lately, more bigger more earlier
|
|
|
|
//
|
|
|
|
// if give a bool false will not flushed when called Reload, then can called GetValMap to flush manually
|
|
|
|
func BuildValFn[T, A any](namespace string, fn func(A) T, args ...any) func(A) T {
|
|
|
|
var vv = BuildAnyVal[T, A](namespace, false, args...)
|
|
|
|
return func(a A) T {
|
|
|
|
v := vv.Val.Load()
|
|
|
|
if v.Ok {
|
|
|
|
return v.V
|
|
|
|
}
|
|
|
|
vv.Mutex.Lock()
|
|
|
|
defer vv.Mutex.Unlock()
|
|
|
|
v = vv.Val.Load()
|
|
|
|
if v.Ok {
|
|
|
|
return v.V
|
|
|
|
}
|
|
|
|
v.V = fn(a)
|
|
|
|
v.Ok = true
|
|
|
|
vv.Val.Store(v)
|
|
|
|
return v.V
|
2023-04-04 15:02:54 +00:00
|
|
|
}
|
2024-01-18 15:29:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// BuildValFnWithAnyParams same as BuildValFn use multiple params
|
|
|
|
func BuildValFnWithAnyParams[T any](namespace string, fn func(...any) T, args ...any) func(...any) T {
|
|
|
|
var vv = BuildAnyVal[T, any](namespace, false, args...)
|
|
|
|
return func(a ...any) T {
|
|
|
|
v := vv.Val.Load()
|
|
|
|
if v.Ok {
|
|
|
|
return v.V
|
|
|
|
}
|
|
|
|
vv.Mutex.Lock()
|
|
|
|
defer vv.Mutex.Unlock()
|
|
|
|
v = vv.Val.Load()
|
|
|
|
if v.Ok {
|
|
|
|
return v.V
|
|
|
|
}
|
|
|
|
v.V = fn(a...)
|
|
|
|
v.Ok = true
|
|
|
|
vv.Val.Store(v)
|
|
|
|
return v.V
|
2023-04-04 15:02:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-13 13:15:54 +00:00
|
|
|
// Vars get default value and whenever reloaded assign default value
|
|
|
|
//
|
|
|
|
// args same as Push
|
2024-01-18 15:29:50 +00:00
|
|
|
//
|
2024-01-18 16:14:04 +00:00
|
|
|
// if give a name, then can be flushed by calls Specifies
|
2024-01-18 15:29:50 +00:00
|
|
|
//
|
|
|
|
// if give a float then can be reloaded early or lately, more bigger more earlier
|
2023-10-23 14:32:20 +00:00
|
|
|
func Vars[T any](defaults T, args ...any) *safety.Var[T] {
|
2023-02-17 15:36:54 +00:00
|
|
|
ss := safety.NewVar(defaults)
|
2023-10-23 14:32:20 +00:00
|
|
|
ord, name := parseArgs(args...)
|
|
|
|
Push(func() {
|
2023-02-17 15:36:54 +00:00
|
|
|
ss.Store(defaults)
|
2023-10-23 14:32:20 +00:00
|
|
|
}, ord, name)
|
2023-02-17 15:36:54 +00:00
|
|
|
return ss
|
|
|
|
}
|
2023-10-14 06:57:57 +00:00
|
|
|
|
2023-10-23 14:32:20 +00:00
|
|
|
func parseArgs(a ...any) (ord float64, name string) {
|
|
|
|
if len(a) > 0 {
|
|
|
|
for _, arg := range a {
|
|
|
|
v, ok := arg.(float64)
|
|
|
|
if ok {
|
|
|
|
ord = v
|
|
|
|
}
|
|
|
|
vv, ok := arg.(string)
|
|
|
|
if ok {
|
|
|
|
name = vv
|
|
|
|
}
|
|
|
|
}
|
2023-10-14 06:57:57 +00:00
|
|
|
}
|
2023-10-23 14:32:20 +00:00
|
|
|
return ord, name
|
2023-10-14 06:57:57 +00:00
|
|
|
}
|
2024-01-13 13:15:54 +00:00
|
|
|
|
|
|
|
// VarsBy
|
|
|
|
//
|
|
|
|
// args same as Push
|
2024-01-18 16:14:04 +00:00
|
|
|
// if give a name, then can be flushed by calls Specifies
|
2023-10-23 14:32:20 +00:00
|
|
|
func VarsBy[T any](fn func() T, args ...any) *safety.Var[T] {
|
2023-02-17 15:36:54 +00:00
|
|
|
ss := safety.NewVar(fn())
|
2023-10-23 14:32:20 +00:00
|
|
|
ord, name := parseArgs(args...)
|
|
|
|
Push(func() {
|
|
|
|
ss.Store(fn())
|
|
|
|
}, ord, name)
|
2023-02-17 15:36:54 +00:00
|
|
|
return ss
|
|
|
|
}
|
2023-10-23 14:32:20 +00:00
|
|
|
func MapBy[K comparable, T any](fn func(*safety.Map[K, T]), args ...any) *safety.Map[K, T] {
|
2023-08-26 14:01:20 +00:00
|
|
|
m := safety.NewMap[K, T]()
|
|
|
|
if fn != nil {
|
|
|
|
fn(m)
|
|
|
|
}
|
2023-10-23 14:32:20 +00:00
|
|
|
ord, name := parseArgs(args...)
|
|
|
|
Push(func() {
|
|
|
|
m.Flush()
|
|
|
|
if fn != nil {
|
|
|
|
fn(m)
|
|
|
|
}
|
|
|
|
}, ord, name)
|
2023-08-26 14:01:20 +00:00
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
2023-10-23 14:32:20 +00:00
|
|
|
func SafeMap[K comparable, T any](args ...any) *safety.Map[K, T] {
|
2023-08-26 14:01:20 +00:00
|
|
|
m := safety.NewMap[K, T]()
|
2023-10-23 14:32:20 +00:00
|
|
|
ord, name := parseArgs(args...)
|
|
|
|
Push(func() {
|
2023-08-26 14:01:20 +00:00
|
|
|
m.Flush()
|
2023-10-23 14:32:20 +00:00
|
|
|
}, ord, name)
|
2023-08-26 14:01:20 +00:00
|
|
|
return m
|
|
|
|
}
|
2023-02-17 15:36:54 +00:00
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
// Push the func that will be called whenever Reload called
|
2024-01-13 13:15:54 +00:00
|
|
|
//
|
2024-01-18 16:14:04 +00:00
|
|
|
// if give a name, then can be called by called Specifies
|
2024-01-18 15:29:50 +00:00
|
|
|
//
|
|
|
|
// if give a float then can be called early or lately when called Reload, more bigger more earlier
|
2023-10-23 14:32:20 +00:00
|
|
|
func Push(fn func(), a ...any) {
|
|
|
|
ord, name := parseArgs(a...)
|
2024-01-18 15:29:50 +00:00
|
|
|
waitReloadCalls.Append(queue{fn, ord, name})
|
2023-10-23 14:32:20 +00:00
|
|
|
if name != "" {
|
2024-01-18 15:29:50 +00:00
|
|
|
callMap.Store(name, fn)
|
2023-10-23 14:32:20 +00:00
|
|
|
}
|
2023-02-17 15:36:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func Reload() {
|
2024-01-18 15:29:50 +00:00
|
|
|
mut.Lock()
|
|
|
|
defer mut.Unlock()
|
|
|
|
callMap.Flush()
|
|
|
|
deleteMapFn.Flush()
|
|
|
|
reloadCalls := waitReloadCalls.Load()
|
|
|
|
slice.SimpleSort(reloadCalls, slice.DESC, func(t queue) float64 {
|
2023-12-05 13:39:13 +00:00
|
|
|
return t.order
|
2023-10-14 06:57:57 +00:00
|
|
|
})
|
2024-01-18 15:29:50 +00:00
|
|
|
for _, call := range reloadCalls {
|
2023-10-14 06:57:57 +00:00
|
|
|
call.fn()
|
2023-02-17 15:36:54 +00:00
|
|
|
}
|
2023-10-23 14:38:52 +00:00
|
|
|
return
|
2023-02-17 15:36:54 +00:00
|
|
|
}
|
2023-11-28 14:46:22 +00:00
|
|
|
|
|
|
|
type Any[T any] struct {
|
2024-01-18 15:29:50 +00:00
|
|
|
fn func() T
|
|
|
|
v *safety.Var[T]
|
|
|
|
isManual *safety.Var[bool]
|
2023-11-28 14:46:22 +00:00
|
|
|
}
|
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
// BuildFnVal build a new fn which can be set value by SetFnVal with name or set default value by given fn when called Reload
|
|
|
|
func BuildFnVal[T any](name string, t T, fn func() T) func() T {
|
2023-11-28 14:46:22 +00:00
|
|
|
if fn == nil {
|
|
|
|
fn = func() T {
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t = fn()
|
|
|
|
}
|
|
|
|
p := safety.NewVar(t)
|
|
|
|
e := Any[T]{
|
2024-01-18 15:29:50 +00:00
|
|
|
fn: fn,
|
|
|
|
v: p,
|
|
|
|
isManual: safety.NewVar(false),
|
2023-11-28 14:46:22 +00:00
|
|
|
}
|
|
|
|
Push(func() {
|
2024-01-18 15:29:50 +00:00
|
|
|
if !e.isManual.Load() {
|
2023-11-28 14:46:22 +00:00
|
|
|
e.v.Store(fn())
|
|
|
|
}
|
|
|
|
})
|
2024-01-18 15:29:50 +00:00
|
|
|
setFnVal.Store(name, e)
|
2023-11-28 14:46:22 +00:00
|
|
|
return func() T {
|
|
|
|
return e.v.Load()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-18 15:29:50 +00:00
|
|
|
func SetFnVal[T any](name string, val T, onlyManual bool) {
|
|
|
|
v, ok := setFnVal.Load(name)
|
2023-11-28 14:46:22 +00:00
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
vv, ok := v.(Any[T])
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
2024-01-18 15:29:50 +00:00
|
|
|
if onlyManual && !vv.isManual.Load() {
|
|
|
|
vv.isManual.Store(true)
|
2023-11-28 14:46:22 +00:00
|
|
|
}
|
|
|
|
vv.v.Store(val)
|
|
|
|
}
|