]> 127.0.0.1 Git - part/.git/commitdiff
1 (#43) v0.28.20250412164915
authorqydysky <qydysky@foxmail.com>
Sat, 12 Apr 2025 16:49:08 +0000 (00:49 +0800)
committerGitHub <noreply@github.com>
Sat, 12 Apr 2025 16:49:08 +0000 (00:49 +0800)
* 1

* 1

* 1

* 1

* 1

file/FileWR.go
file/FileWR_test.go
go.mod
go.sum
sync/LoadOrStoreFunc.go [new file with mode: 0644]
sync/Map.go
sync/MapExceeded.go [new file with mode: 0644]
sync/Map_test.go
web/Web.go

index 4c82e38d7f305a23fb9cb98ac2cd6df3b9cbc85b..59ab056d81089c342e5c739c2c7cdbd9a0e3e5a5 100644 (file)
@@ -176,7 +176,7 @@ func (t *File) CheckRoot(root string) *File {
                remove:    os.Remove,
                removeAll: os.RemoveAll,
                stat:      os.Stat,
-       }, t.Config.root+"/.t", fs.ModeDir)
+       }, t.Config.root+"/.t", fs.ModePerm|fs.ModeDir)
        return t
 }
 
index 3d1dc132311495153100622a03c00d9e88930892..a3613209ac64092842ffb3da1daafa61e1ea47cc 100644 (file)
@@ -17,18 +17,18 @@ import (
 )
 
 func TestDir(t *testing.T) {
-       Open("test2").Delete()
-       if Open("test2").IsExist() {
+       Open("./test2").Delete()
+       if Open("./test2").IsExist() {
                t.Fatal()
        }
-       if f, e := DirFS("test2").Open("FileWR.go"); e != nil {
+       if f, e := DirFS("./test2").Open("1.txt"); e != nil {
                t.Fatal(e)
        } else if _, e := f.(*File).Write([]byte{'1'}, false); e != nil {
                t.Fatal(e)
        } else {
                f.(*File).Delete()
        }
-       if !Open("test2").IsExist() {
+       if !Open("./test2").IsExist() {
                t.Fatal()
        }
 }
diff --git a/go.mod b/go.mod
index c25f4309d1873eaa15e0bb4476f3314e2bdd9cff..e055b72177b36bcead632e926ab5c7fc546a438a 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -46,7 +46,7 @@ require (
        github.com/jackc/pgx/v5 v5.7.1
        github.com/stretchr/testify v1.10.0 // indirect
        golang.org/x/net v0.37.0 // indirect
-       golang.org/x/sys v0.31.0 // indirect
+       golang.org/x/sys v0.32.0 // indirect
        modernc.org/sqlite v1.34.2
 )
 
diff --git a/go.sum b/go.sum
index 407c346072488d02654e63c262b0ae0d8b686cea..671e268aa7a4fb75a4699a9c76828491a99906fe 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -68,8 +68,8 @@ golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
-golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
+golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
 golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
 golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
diff --git a/sync/LoadOrStoreFunc.go b/sync/LoadOrStoreFunc.go
new file mode 100644 (file)
index 0000000..e28c949
--- /dev/null
@@ -0,0 +1,61 @@
+package part
+
+import "sync"
+
+type LoadOrInitFunc[T any] struct {
+       Map interface {
+               LoadOrStore(k, v any) (actual any, loaded bool)
+       }
+       Init  func() *T
+       cache *T
+       l     sync.Mutex
+}
+
+func NewLoadOrInitFunc[T any](m interface {
+       LoadOrStore(k, v any) (actual any, loaded bool)
+}) *LoadOrInitFunc[T] {
+       return &LoadOrInitFunc[T]{
+               Map: m,
+       }
+}
+
+func (l *LoadOrInitFunc[T]) SetInit(init func() *T) *LoadOrInitFunc[T] {
+       l.l.Lock()
+       defer l.l.Unlock()
+       l.Init = init
+       return l
+}
+
+func (l *LoadOrInitFunc[T]) LoadOrInit(k any) (actual T, loaded bool) {
+       l.l.Lock()
+       defer l.l.Unlock()
+       a, b := l.loadOrInitP(k)
+       return *a, b
+}
+
+func (l *LoadOrInitFunc[T]) LoadOrInitPThen(k any) func(func(actual *T, loaded bool) (*T, bool)) (*T, bool) {
+       return func(f func(actual *T, loaded bool) (*T, bool)) (*T, bool) {
+               l.l.Lock()
+               defer l.l.Unlock()
+               return f(l.loadOrInitP(k))
+       }
+}
+
+func (l *LoadOrInitFunc[T]) LoadOrInitP(k any) (actual *T, loaded bool) {
+       l.l.Lock()
+       defer l.l.Unlock()
+
+       return l.loadOrInitP(k)
+}
+
+func (l *LoadOrInitFunc[T]) loadOrInitP(k any) (actual *T, loaded bool) {
+       if l.cache == nil {
+               l.cache = l.Init()
+       }
+       if actual, loaded := l.Map.LoadOrStore(k, l.cache); !loaded {
+               l.cache = nil
+               return actual.(*T), false
+       } else {
+               return actual.(*T), true
+       }
+}
index bcbcd5aae866cd1b72a61e33bc138102e37d695e..10eb6d4316bedef9f6b5b922b2c0c2d5ea684e5c 100644 (file)
@@ -3,9 +3,23 @@ package part
 import (
        "sync"
        "sync/atomic"
-       "time"
 )
 
+type MapFunc[T, E any] interface {
+       Clear()
+       CompareAndDelete(key T, old E) (deleted bool)
+       CompareAndSwap(key T, old E, new E) (swapped bool)
+       Delete(key T)
+       Load(key T) (value E, ok bool)
+       LoadAndDelete(key T) (value E, loaded bool)
+       LoadOrStore(key T, value E) (actual E, loaded bool)
+       Range(f func(key T, value E) bool)
+       Store(key T, value E)
+       Swap(key T, value E) (previous E, loaded bool)
+}
+
+var _ = MapFunc[any, any](&Map{})
+
 type Map struct {
        size atomic.Int64
        m    sync.Map
@@ -17,52 +31,36 @@ func (t *Map) Store(k, v any) {
        }
 }
 
-func (t *Map) LoadOrStore(k, v any) (actual any, loaded bool) {
-       actual, loaded = t.m.LoadOrStore(k, v)
-       if !loaded {
-               t.size.Add(1)
-       }
-       return
+func (t *Map) CompareAndSwap(key any, old any, new any) (swapped bool) {
+       return t.m.CompareAndSwap(key, old, new)
 }
 
-type LoadOrStoreFunc[T any] struct {
-       Init  func() *T
-       cache *T
-       l     sync.Mutex
+func (t *Map) CompareAndDelete(key any, old any) (deleted bool) {
+       deleted = t.m.CompareAndDelete(key, old)
+       if deleted {
+               t.size.Add(-1)
+       }
+       return
 }
 
-func (l *LoadOrStoreFunc[T]) LoadOrStore(t interface {
-       LoadOrStore(k, v any) (actual any, loaded bool)
-}, k any) (actual T, loaded bool) {
-       l.l.Lock()
-       defer l.l.Unlock()
-
-       if l.cache == nil {
-               l.cache = l.Init()
-       }
-       if actual, loaded := t.LoadOrStore(k, l.cache); !loaded {
-               l.cache = nil
-               return *(actual.(*T)), false
-       } else {
-               return *(actual.(*T)), true
+func (t *Map) LoadAndDelete(key any) (value any, loaded bool) {
+       value, loaded = t.m.LoadAndDelete(key)
+       if loaded {
+               t.size.Add(-1)
        }
+       return
 }
 
-func (l *LoadOrStoreFunc[T]) LoadOrStoreP(t interface {
-       LoadOrStore(k, v any) (actual any, loaded bool)
-}, k any) (actual *T, loaded bool) {
-       l.l.Lock()
-       defer l.l.Unlock()
+func (t *Map) Swap(key any, value any) (previous any, loaded bool) {
+       return t.m.Swap(key, value)
+}
 
-       if l.cache == nil {
-               l.cache = l.Init()
-       }
-       if actual, loaded := t.LoadOrStore(k, l.cache); !loaded {
-               l.cache = nil
-               return actual.(*T), false
-       } else {
-               return actual.(*T), true
+func (t *Map) LoadOrStore(k, v any) (actual any, loaded bool) {
+       actual, loaded = t.m.LoadOrStore(k, v)
+       if !loaded {
+               t.size.Add(1)
        }
+       return
 }
 
 func (t *Map) Load(k any) (any, bool) {
@@ -78,12 +76,14 @@ func (t *Map) Range(f func(key, value any) bool) {
        t.m.Range(f)
 }
 
-func (t *Map) Delete(k any) (ok bool) {
+func (t *Map) Delete(k any) {
        if _, ok := t.m.LoadAndDelete(k); ok {
                t.size.Add(-1)
-               return true
        }
-       return false
+}
+
+func (t *Map) Clear() {
+       t.ClearAll()
 }
 
 func (t *Map) ClearAll() {
@@ -122,99 +122,3 @@ func Copy[T comparable, S any](s map[T]S) map[T]S {
        }
        return t
 }
-
-type MapExceeded[K, V any] struct {
-       m Map
-}
-
-type mapExceededItem[V any] struct {
-       data     V
-       exceeded time.Time
-       wait     sync.RWMutex
-}
-
-func (t *MapExceeded[K, V]) Copy() (m *MapExceeded[K, V]) {
-       m = &MapExceeded[K, V]{}
-       t.m.Range(func(key, value any) bool {
-               if value.(*mapExceededItem[V]).exceeded.After(time.Now()) {
-                       m.m.Store(key, value)
-               }
-               return true
-       })
-       return
-}
-
-func (t *MapExceeded[K, V]) Store(k K, v V, dur time.Duration) {
-       t.m.Store(k, &mapExceededItem[V]{
-               data:     v,
-               exceeded: time.Now().Add(dur),
-       })
-}
-
-func (t *MapExceeded[K, V]) Load(k K) (v V, ok bool) {
-       if v, ok := t.m.LoadV(k).(*mapExceededItem[V]); ok {
-               if v.exceeded.After(time.Now()) {
-                       return v.data, true
-               }
-               t.Delete(k)
-       }
-       return
-}
-
-func (t *MapExceeded[K, V]) Range(f func(key K, value *V) bool) {
-       t.m.Range(func(key, value any) bool {
-               if value.(*mapExceededItem[V]).exceeded.After(time.Now()) {
-                       return f(key.(K), value.(*V))
-               }
-               t.Delete(key.(K))
-               return true
-       })
-}
-
-func (t *MapExceeded[K, V]) Len() int {
-       return t.m.Len()
-}
-
-func (t *MapExceeded[K, V]) GC() {
-       t.m.Range(func(key, value any) bool {
-               if value.(*mapExceededItem[V]).exceeded.Before(time.Now()) {
-                       t.Delete(key.(K))
-               }
-               return true
-       })
-}
-
-func (t *MapExceeded[K, V]) Delete(k K) {
-       t.m.Delete(k)
-}
-
-func (t *MapExceeded[K, V]) LoadOrStore(k K) (vr V, loaded bool, store func(v1 V, dur time.Duration)) {
-       store = func(v1 V, dur time.Duration) {}
-       var actual any
-       actual, loaded = t.m.LoadOrStore(k, &mapExceededItem[V]{})
-       v := actual.(*mapExceededItem[V])
-       v.wait.RLock()
-       exp := v.exceeded
-       vr = v.data
-       v.wait.RUnlock()
-       if loaded && time.Now().Before(exp) {
-               return
-       }
-       if !loaded || (loaded && !exp.IsZero()) {
-               store = func(v1 V, dur time.Duration) {
-                       v.wait.Lock()
-                       v.data = v1
-                       v.exceeded = time.Now().Add(dur)
-                       v.wait.Unlock()
-               }
-               return
-       }
-       for loaded && exp.IsZero() {
-               time.Sleep(time.Millisecond * 20)
-               v.wait.RLock()
-               exp = v.exceeded
-               vr = v.data
-               v.wait.RUnlock()
-       }
-       return
-}
diff --git a/sync/MapExceeded.go b/sync/MapExceeded.go
new file mode 100644 (file)
index 0000000..0f4ed32
--- /dev/null
@@ -0,0 +1,102 @@
+package part
+
+import (
+       "sync"
+       "time"
+)
+
+type MapExceeded[K, V any] struct {
+       m Map
+}
+
+type mapExceededItem[V any] struct {
+       data     V
+       exceeded time.Time
+       wait     sync.RWMutex
+}
+
+func (t *MapExceeded[K, V]) Copy() (m *MapExceeded[K, V]) {
+       m = &MapExceeded[K, V]{}
+       t.m.Range(func(key, value any) bool {
+               if value.(*mapExceededItem[V]).exceeded.After(time.Now()) {
+                       m.m.Store(key, value)
+               }
+               return true
+       })
+       return
+}
+
+func (t *MapExceeded[K, V]) Store(k K, v V, dur time.Duration) {
+       t.m.Store(k, &mapExceededItem[V]{
+               data:     v,
+               exceeded: time.Now().Add(dur),
+       })
+}
+
+func (t *MapExceeded[K, V]) Load(k K) (v V, ok bool) {
+       if v, ok := t.m.LoadV(k).(*mapExceededItem[V]); ok {
+               if v.exceeded.After(time.Now()) {
+                       return v.data, true
+               }
+               t.Delete(k)
+       }
+       return
+}
+
+func (t *MapExceeded[K, V]) Range(f func(key K, value *V) bool) {
+       t.m.Range(func(key, value any) bool {
+               if value.(*mapExceededItem[V]).exceeded.After(time.Now()) {
+                       return f(key.(K), value.(*V))
+               }
+               t.Delete(key.(K))
+               return true
+       })
+}
+
+func (t *MapExceeded[K, V]) Len() int {
+       return t.m.Len()
+}
+
+func (t *MapExceeded[K, V]) GC() {
+       t.m.Range(func(key, value any) bool {
+               if value.(*mapExceededItem[V]).exceeded.Before(time.Now()) {
+                       t.Delete(key.(K))
+               }
+               return true
+       })
+}
+
+func (t *MapExceeded[K, V]) Delete(k K) {
+       t.m.Delete(k)
+}
+
+func (t *MapExceeded[K, V]) LoadOrStore(k K) (vr V, loaded bool, store func(v1 V, dur time.Duration)) {
+       store = func(v1 V, dur time.Duration) {}
+       var actual any
+       actual, loaded = t.m.LoadOrStore(k, &mapExceededItem[V]{})
+       v := actual.(*mapExceededItem[V])
+       v.wait.RLock()
+       exp := v.exceeded
+       vr = v.data
+       v.wait.RUnlock()
+       if loaded && time.Now().Before(exp) {
+               return
+       }
+       if !loaded || (loaded && !exp.IsZero()) {
+               store = func(v1 V, dur time.Duration) {
+                       v.wait.Lock()
+                       v.data = v1
+                       v.exceeded = time.Now().Add(dur)
+                       v.wait.Unlock()
+               }
+               return
+       }
+       for loaded && exp.IsZero() {
+               time.Sleep(time.Millisecond * 20)
+               v.wait.RLock()
+               exp = v.exceeded
+               vr = v.data
+               v.wait.RUnlock()
+       }
+       return
+}
index 805e8924c32eacba36a072b15b9271070ca075d9..d5475b5c57db9449953ca0e357d2c7e58a711538 100644 (file)
@@ -13,17 +13,15 @@ type tmp struct {
 
 func TestLS(t *testing.T) {
        var c Map
-       var ls = LoadOrStoreFunc[int]{
-               Init: func() *int {
-                       var i = 1
-                       return &i
-               },
-       }
-       a0, l0 := ls.LoadOrStore(&c, `1`)
+       var ls = NewLoadOrInitFunc[int](&c).SetInit(func() *int {
+               var i = 1
+               return &i
+       })
+       a0, l0 := ls.LoadOrInit(`1`)
        if l0 {
                t.Fatal()
        }
-       a1, l1 := ls.LoadOrStore(&c, `1`)
+       a1, l1 := ls.LoadOrInit(`1`)
        if !l1 {
                t.Fatal()
        }
index bf22f387cdf9afa7d693f91e5c0e1245f7ea06c0..8a36ca021d783391f49c05f59970d879404088c7 100644 (file)
@@ -674,7 +674,7 @@ func (t *Exprier) Reg(dur time.Duration, reNewKey ...string) (string, error) {
                        for {
                                select {
                                case key1 := <-t.mc:
-                                       if t.m.Delete(key1) {
+                                       if _, ok := t.m.LoadAndDelete(key1); ok {
                                                t.mc <- newkey
                                                t.m.Store(newkey, time.Now().Add(dur))
                                                return newkey, nil