All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 2m18s
106 lines
3.6 KiB
Go
106 lines
3.6 KiB
Go
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
|
|
}
|