Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
55f80432bb
|
|||
|
d6daf0e285
|
|||
|
1c2bc060da
|
105
dataext/multiMutex.go
Normal file
105
dataext/multiMutex.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package dataext
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MultiMutex is a simple map[key -> mutex]
|
||||||
|
type MultiMutex[TKey comparable] struct {
|
||||||
|
mutextMap *SyncMap[TKey, *CASMutex]
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMultiMutex[TKey comparable]() *MultiMutex[TKey] {
|
||||||
|
return &MultiMutex[TKey]{
|
||||||
|
mutextMap: NewSyncMap[TKey, *CASMutex](),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryLockWithContext attempts to acquire the lock, blocking until resources
|
||||||
|
// are available or ctx is done (timeout or cancellation).
|
||||||
|
func (mm *MultiMutex[TKey]) TryLockWithContext(ctx context.Context, key TKey) bool {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
return lck.TryLockWithContext(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock acquires the lock.
|
||||||
|
// If it is currently held by others, Lock will wait until it has a chance to acquire it.
|
||||||
|
func (mm *MultiMutex[TKey]) Lock(key TKey) {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
lck.Lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryLock attempts to acquire the lock without blocking.
|
||||||
|
// Return false if someone is holding it now.
|
||||||
|
func (mm *MultiMutex[TKey]) TryLock(key TKey) bool {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
return lck.TryLock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryLockWithTimeout attempts to acquire the lock within a period of time.
|
||||||
|
// Return false if spending time is more than duration and no chance to acquire it.
|
||||||
|
func (mm *MultiMutex[TKey]) TryLockWithTimeout(key TKey, duration time.Duration) bool {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
return lck.TryLockWithTimeout(duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock releases the lock.
|
||||||
|
func (mm *MultiMutex[TKey]) Unlock(key TKey) {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
lck.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RTryLockWithContext attempts to acquire the read lock, blocking until resources
|
||||||
|
// are available or ctx is done (timeout or cancellation).
|
||||||
|
func (mm *MultiMutex[TKey]) RTryLockWithContext(ctx context.Context, key TKey) bool {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
return lck.RTryLockWithContext(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RLock acquires the read lock.
|
||||||
|
// If it is currently held by others writing, RLock will wait until it has a chance to acquire it.
|
||||||
|
func (mm *MultiMutex[TKey]) RLock(key TKey) {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
lck.RLock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RTryLock attempts to acquire the read lock without blocking.
|
||||||
|
// Return false if someone is writing it now.
|
||||||
|
func (mm *MultiMutex[TKey]) RTryLock(key TKey) bool {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
return lck.RTryLock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RTryLockWithTimeout attempts to acquire the read lock within a period of time.
|
||||||
|
// Return false if spending time is more than duration and no chance to acquire it.
|
||||||
|
func (mm *MultiMutex[TKey]) RTryLockWithTimeout(duration time.Duration, key TKey) bool {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
return lck.RTryLockWithTimeout(duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RUnlock releases the read lock.
|
||||||
|
func (mm *MultiMutex[TKey]) RUnlock(key TKey) {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
lck.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RLocker returns a Locker interface that implements the Lock and Unlock methods
|
||||||
|
// by calling CASMutex.RLock and CASMutex.RUnlock.
|
||||||
|
func (mm *MultiMutex[TKey]) RLocker(key TKey) sync.Locker {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
return lck.RLocker()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns a Locker interface
|
||||||
|
func (mm *MultiMutex[TKey]) Get(key TKey) sync.Locker {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
return lck
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCAS returns the underlying CASMutex
|
||||||
|
func (mm *MultiMutex[TKey]) GetCAS(key TKey) *CASMutex {
|
||||||
|
lck := mm.mutextMap.GetAndSetIfNotContainsFunc(key, NewCASMutex)
|
||||||
|
return lck
|
||||||
|
}
|
||||||
2
go.mod
2
go.mod
@@ -38,7 +38,7 @@ require (
|
|||||||
github.com/golang/snappy v1.0.0 // indirect
|
github.com/golang/snappy v1.0.0 // indirect
|
||||||
github.com/google/uuid v1.5.0 // indirect
|
github.com/google/uuid v1.5.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.18.1 // indirect
|
github.com/klauspost/compress v1.18.2 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -149,6 +149,8 @@ github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zt
|
|||||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
|
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
|
||||||
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
|
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
|
||||||
|
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||||
|
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
package goext
|
package goext
|
||||||
|
|
||||||
const GoextVersion = "0.0.614"
|
const GoextVersion = "0.0.617"
|
||||||
|
|
||||||
const GoextVersionTimestamp = "2025-11-29T12:49:17+0100"
|
const GoextVersionTimestamp = "2025-12-06T11:54:36+0100"
|
||||||
|
|||||||
Reference in New Issue
Block a user