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
}
)
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()
}
}
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
)
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=
--- /dev/null
+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
+ }
+}
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
}
}
-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) {
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() {
}
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
-}
--- /dev/null
+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
+}
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()
}
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