diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-mutexes')
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/LICENSE | 9 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/README.md | 1 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/cond.go | 67 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/debug.go | 39 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/hash_map.go | 56 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/map.go | 235 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/mutex.go | 105 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/mutex_safe.go | 50 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/mutex_timeout.go | 85 |
9 files changed, 0 insertions, 647 deletions
diff --git a/vendor/codeberg.org/gruf/go-mutexes/LICENSE b/vendor/codeberg.org/gruf/go-mutexes/LICENSE deleted file mode 100644 index d6f08d0ab..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright (c) gruf - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/codeberg.org/gruf/go-mutexes/README.md b/vendor/codeberg.org/gruf/go-mutexes/README.md deleted file mode 100644 index f25ccad81..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/README.md +++ /dev/null @@ -1 +0,0 @@ -Library that provides more complex mutex implementations than default libraries
\ No newline at end of file diff --git a/vendor/codeberg.org/gruf/go-mutexes/cond.go b/vendor/codeberg.org/gruf/go-mutexes/cond.go deleted file mode 100644 index 3d7f21126..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/cond.go +++ /dev/null @@ -1,67 +0,0 @@ -package mutexes - -import ( - "sync" -) - -// Cond is similar to a sync.Cond{}, but -// it encompasses the Mutex{} within itself. -type Cond struct { - c sync.Cond - sync.Mutex -} - -// See: sync.Cond{}.Wait(). -func (c *Cond) Wait() { - if c.c.L == nil { - c.c.L = &c.Mutex - } - c.c.Wait() -} - -// See: sync.Cond{}.Signal(). -func (c *Cond) Signal() { - if c.c.L == nil { - c.c.L = &c.Mutex - } - c.c.Signal() -} - -// See: sync.Cond{}.Broadcast(). -func (c *Cond) Broadcast() { - if c.c.L == nil { - c.c.L = &c.Mutex - } - c.c.Broadcast() -} - -// RWCond is similar to a sync.Cond{}, but -// it encompasses the RWMutex{} within itself. -type RWCond struct { - c sync.Cond - sync.RWMutex -} - -// See: sync.Cond{}.Wait(). -func (c *RWCond) Wait() { - if c.c.L == nil { - c.c.L = &c.RWMutex - } - c.c.Wait() -} - -// See: sync.Cond{}.Signal(). -func (c *RWCond) Signal() { - if c.c.L == nil { - c.c.L = &c.RWMutex - } - c.c.Signal() -} - -// See: sync.Cond{}.Broadcast(). -func (c *RWCond) Broadcast() { - if c.c.L == nil { - c.c.L = &c.RWMutex - } - c.c.Broadcast() -} diff --git a/vendor/codeberg.org/gruf/go-mutexes/debug.go b/vendor/codeberg.org/gruf/go-mutexes/debug.go deleted file mode 100644 index 1b7be60c7..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/debug.go +++ /dev/null @@ -1,39 +0,0 @@ -package mutexes - -// func init() { -// log.SetFlags(log.Flags() | log.Lshortfile) -// } - -// type debugMutex sync.Mutex - -// func (mu *debugMutex) Lock() { -// log.Output(2, "Lock()") -// (*sync.Mutex)(mu).Lock() -// } - -// func (mu *debugMutex) Unlock() { -// log.Output(2, "Unlock()") -// (*sync.Mutex)(mu).Unlock() -// } - -// type debugRWMutex sync.RWMutex - -// func (mu *debugRWMutex) Lock() { -// log.Output(2, "Lock()") -// (*sync.RWMutex)(mu).Lock() -// } - -// func (mu *debugRWMutex) Unlock() { -// log.Output(2, "Unlock()") -// (*sync.RWMutex)(mu).Unlock() -// } - -// func (mu *debugRWMutex) RLock() { -// log.Output(2, "RLock()") -// (*sync.RWMutex)(mu).RLock() -// } - -// func (mu *debugRWMutex) RUnlock() { -// log.Output(2, "RUnlock()") -// (*sync.RWMutex)(mu).RUnlock() -// } diff --git a/vendor/codeberg.org/gruf/go-mutexes/hash_map.go b/vendor/codeberg.org/gruf/go-mutexes/hash_map.go deleted file mode 100644 index a177133b5..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/hash_map.go +++ /dev/null @@ -1,56 +0,0 @@ -package mutexes - -type hashmap struct { - m map[string]*rwmutex - n int -} - -func (m *hashmap) init(cap int) { - m.m = make(map[string]*rwmutex, cap) - m.n = cap -} - -func (m *hashmap) Get(key string) *rwmutex { return m.m[key] } - -func (m *hashmap) Put(key string, mu *rwmutex) { - m.m[key] = mu - if n := len(m.m); n > m.n { - m.n = n - } -} - -func (m *hashmap) Delete(key string) { - delete(m.m, key) -} - -func (m *hashmap) Compact() { - // Noop when hashmap size - // is too small to matter. - if m.n < 2048 { - return - } - - // Difference between maximum map - // size and the current map size. - diff := m.n - len(m.m) - - // Maximum load factor before - // runtime allocates new hmap: - // maxLoad = 13 / 16 - // - // So we apply the inverse/2, once - // $maxLoad/2 % of hmap is empty we - // compact the map to drop buckets. - if 2*16*diff > m.n*13 { - - // Create new map only as big as required. - m2 := make(map[string]*rwmutex, len(m.m)) - for k, v := range m.m { - m2[k] = v - } - - // Set new. - m.m = m2 - m.n = len(m2) - } -} diff --git a/vendor/codeberg.org/gruf/go-mutexes/map.go b/vendor/codeberg.org/gruf/go-mutexes/map.go deleted file mode 100644 index 4b721cec4..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/map.go +++ /dev/null @@ -1,235 +0,0 @@ -package mutexes - -import ( - "sync" - "sync/atomic" - "unsafe" - - "codeberg.org/gruf/go-mempool" -) - -const ( - // possible lock types. - lockTypeRead = uint8(1) << 0 - lockTypeWrite = uint8(1) << 1 -) - -// MutexMap is a structure that allows read / write locking -// per key, performing as you'd expect a map[string]*RWMutex -// to perform, without you needing to worry about deadlocks -// between competing read / write locks and the map's own mutex. -// It uses memory pooling for the internal "mutex" (ish) types -// and performs self-eviction of keys. -// -// Under the hood this is achieved using a single mutex for the -// map, state tracking for individual keys, and some sync.Cond{} -// like structures for sleeping / awaking awaiting goroutines. -type MutexMap struct { - mapmu sync.Mutex - mumap hashmap - mupool mempool.UnsafePool -} - -// checkInit ensures MutexMap is initialized (UNSAFE). -func (mm *MutexMap) checkInit() { - if mm.mumap.m == nil { - mm.mumap.init(0) - mm.mupool.DirtyFactor = 256 - } -} - -// Lock acquires a write lock on key in map, returning unlock function. -func (mm *MutexMap) Lock(key string) func() { - return mm.lock(key, lockTypeWrite) -} - -// RLock acquires a read lock on key in map, returning runlock function. -func (mm *MutexMap) RLock(key string) func() { - return mm.lock(key, lockTypeRead) -} - -func (mm *MutexMap) lock(key string, lt uint8) func() { - // Perform first map lock - // and check initialization - // OUTSIDE the main loop. - mm.mapmu.Lock() - mm.checkInit() - - for { - // Check map for mutex. - mu := mm.mumap.Get(key) - - if mu == nil { - // Allocate mutex. - mu = mm.acquire() - mm.mumap.Put(key, mu) - } - - if !mu.Lock(lt) { - // Wait on mutex unlock, after - // immediately relocking map mu. - mu.WaitRelock() - continue - } - - // Done with map. - mm.mapmu.Unlock() - - // Return mutex unlock function. - return func() { mm.unlock(key, mu) } - } -} - -func (mm *MutexMap) unlock(key string, mu *rwmutex) { - // Get map lock. - mm.mapmu.Lock() - - // Unlock mutex. - if !mu.Unlock() { - - // Fast path. Mutex still - // used so no map change. - mm.mapmu.Unlock() - return - } - - // Mutex fully unlocked - // with zero waiters. Self - // evict and release it. - mm.mumap.Delete(key) - mm.release(mu) - - // Check if compaction - // needed. - mm.mumap.Compact() - - // Done with map. - mm.mapmu.Unlock() -} - -// acquire will acquire mutex from memory pool, or alloc new. -func (mm *MutexMap) acquire() *rwmutex { - if ptr := mm.mupool.Get(); ptr != nil { - return (*rwmutex)(ptr) - } - mu := new(rwmutex) - mu.c.L = &mm.mapmu - return mu -} - -// release will release given mutex to memory pool. -func (mm *MutexMap) release(mu *rwmutex) { - ptr := unsafe.Pointer(mu) - mm.mupool.Put(ptr) -} - -// rwmutex represents a RW mutex when used correctly within -// a MapMutex. It should ONLY be access when protected by -// the outer map lock, except for the 'notifyList' which is -// a runtime internal structure borrowed from the sync.Cond{}. -// -// this functions very similarly to a sync.Cond{}, but with -// lock state tracking, and returning on 'Broadcast()' whether -// any goroutines were actually awoken. it also has a less -// confusing API than sync.Cond{} with the outer locking -// mechanism we use, otherwise all Cond{}.L would reference -// the same outer map mutex. -type rwmutex struct { - c sync.Cond // 'trigger' mechanism - l int32 // no. locks - t uint8 // lock type -} - -// Lock will lock the mutex for given lock type, in the -// sense that it will update the internal state tracker -// accordingly. Return value is true on successful lock. -func (mu *rwmutex) Lock(lt uint8) bool { - switch mu.t { - case lockTypeRead: - // already read locked, - // only permit more reads. - if lt != lockTypeRead { - return false - } - - case lockTypeWrite: - // already write locked, - // no other locks allowed. - return false - - default: - // Fully unlocked, - // set incoming type. - mu.t = lt - } - - // Update - // count. - mu.l++ - - return true -} - -// Unlock will unlock the mutex, in the sense that it -// will update the internal state tracker accordingly. -// On totally unlocked state, it will awaken all -// sleeping goroutines waiting on this mutex. -func (mu *rwmutex) Unlock() bool { - switch mu.l--; { - case mu.l > 0 && mu.t == lockTypeWrite: - panic("BUG: multiple writer locks") - case mu.l < 0: - panic("BUG: negative lock count") - - case mu.l == 0: - // Fully unlocked. - mu.t = 0 - - // NOTE: must remain in - // sync with runtime.notifyList{}. - // - // goexperiment.staticlockranking - // does change it slightly, but - // this does not alter the first - // 2 fields which are all we need. - type notifyList struct { - _ uint32 - notify uint32 - // ... other fields - } - - // NOTE: must remain in - // sync with sync.Cond{}. - type syncCond struct { - _ struct{} - L sync.Locker - n notifyList - // ... other fields - } - - // Awake all blocked goroutines and check - // for change in the last notified ticket. - cptr := (*syncCond)(unsafe.Pointer(&mu.c)) - before := atomic.LoadUint32(&cptr.n.notify) - mu.c.Broadcast() // awakes all blocked! - after := atomic.LoadUint32(&cptr.n.notify) - - // If ticket changed, this indicates - // AT LEAST one goroutine was awoken. - // - // (before != after) => (waiters > 0) - // (before == after) => (waiters = 0) - return (before == after) - - default: - // i.e. mutex still - // locked by others. - return false - } -} - -// WaitRelock expects a mutex to be passed in, already in the -// locked state. It incr the notifyList waiter count before -// unlocking the outer mutex and blocking on notifyList wait. -// On awake it will decr wait count and relock outer mutex. -func (mu *rwmutex) WaitRelock() { mu.c.Wait() } diff --git a/vendor/codeberg.org/gruf/go-mutexes/mutex.go b/vendor/codeberg.org/gruf/go-mutexes/mutex.go deleted file mode 100644 index 3841c9423..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/mutex.go +++ /dev/null @@ -1,105 +0,0 @@ -package mutexes - -import ( - "sync" -) - -// Mutex defines a wrappable mutex. By forcing unlocks -// via returned function it makes wrapping much easier -type Mutex interface { - // Lock performs a mutex lock, returning an unlock function - Lock() (unlock func()) -} - -// RWMutex defines a wrappable read-write mutex. By forcing -// unlocks via returned functions it makes wrapping much easier -type RWMutex interface { - Mutex - - // RLock performs a mutex read lock, returning an unlock function - RLock() (runlock func()) -} - -// New returns a new base Mutex implementation -func New() Mutex { - return &baseMutex{} -} - -// NewRW returns a new base RWMutex implementation -func NewRW() RWMutex { - return &baseRWMutex{} -} - -// WithFunc wraps the supplied Mutex to call the provided hooks on lock / unlock -func WithFunc(mu Mutex, onLock, onUnlock func()) Mutex { - return &fnMutex{mu: mu, lo: onLock, un: onUnlock} -} - -// WithFuncRW wrapps the supplied RWMutex to call the provided hooks on lock / rlock / unlock/ runlock -func WithFuncRW(mu RWMutex, onLock, onRLock, onUnlock, onRUnlock func()) RWMutex { - return &fnRWMutex{mu: mu, lo: onLock, rlo: onRLock, un: onUnlock, run: onRUnlock} -} - -// baseMutex simply wraps a sync.Mutex to implement our Mutex interface -type baseMutex sync.Mutex - -func (mu *baseMutex) Lock() func() { - (*sync.Mutex)(mu).Lock() - return (*sync.Mutex)(mu).Unlock -} - -// baseRWMutex simply wraps a sync.RWMutex to implement our RWMutex interface -type baseRWMutex sync.RWMutex - -func (mu *baseRWMutex) Lock() func() { - (*sync.RWMutex)(mu).Lock() - return (*sync.RWMutex)(mu).Unlock -} - -func (mu *baseRWMutex) RLock() func() { - (*sync.RWMutex)(mu).RLock() - return (*sync.RWMutex)(mu).RUnlock -} - -// fnMutex wraps a Mutex to add hooks for Lock and Unlock -type fnMutex struct { - mu Mutex - lo func() - un func() -} - -func (mu *fnMutex) Lock() func() { - unlock := mu.mu.Lock() - mu.lo() - return func() { - mu.un() - unlock() - } -} - -// fnRWMutex wraps a RWMutex to add hooks for Lock, RLock, Unlock and RUnlock -type fnRWMutex struct { - mu RWMutex - lo func() - rlo func() - un func() - run func() -} - -func (mu *fnRWMutex) Lock() func() { - unlock := mu.mu.Lock() - mu.lo() - return func() { - mu.un() - unlock() - } -} - -func (mu *fnRWMutex) RLock() func() { - unlock := mu.mu.RLock() - mu.rlo() - return func() { - mu.run() - unlock() - } -} diff --git a/vendor/codeberg.org/gruf/go-mutexes/mutex_safe.go b/vendor/codeberg.org/gruf/go-mutexes/mutex_safe.go deleted file mode 100644 index 5a0383dce..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/mutex_safe.go +++ /dev/null @@ -1,50 +0,0 @@ -package mutexes - -import ( - "sync/atomic" -) - -// WithSafety wrapps the supplied Mutex to protect unlock fns -// from being called multiple times -func WithSafety(mu Mutex) Mutex { - return &safeMutex{mu: mu} -} - -// WithSafetyRW wrapps the supplied RWMutex to protect unlock -// fns from being called multiple times -func WithSafetyRW(mu RWMutex) RWMutex { - return &safeRWMutex{mu: mu} -} - -// safeMutex simply wraps a Mutex to add multi-unlock safety -type safeMutex struct{ mu Mutex } - -func (mu *safeMutex) Lock() func() { - unlock := mu.mu.Lock() - return once(unlock) -} - -// safeRWMutex simply wraps a RWMutex to add multi-unlock safety -type safeRWMutex struct{ mu RWMutex } - -func (mu *safeRWMutex) Lock() func() { - unlock := mu.mu.Lock() - return once(unlock) -} - -func (mu *safeRWMutex) RLock() func() { - unlock := mu.mu.RLock() - return once(unlock) -} - -// once will perform 'do' only once, this is safe for unlocks -// as 2 functions calling 'unlock()' don't need absolute guarantees -// that by the time it is completed the unlock was finished. -func once(do func()) func() { - var done uint32 - return func() { - if atomic.CompareAndSwapUint32(&done, 0, 1) { - do() - } - } -} diff --git a/vendor/codeberg.org/gruf/go-mutexes/mutex_timeout.go b/vendor/codeberg.org/gruf/go-mutexes/mutex_timeout.go deleted file mode 100644 index e00444b64..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/mutex_timeout.go +++ /dev/null @@ -1,85 +0,0 @@ -package mutexes - -import ( - "time" -) - -// TimeoutMutex defines a Mutex with timeouts on locks -type TimeoutMutex interface { - Mutex - - // LockFunc is functionally the same as Lock(), but allows setting a custom hook called on timeout - LockFunc(func()) func() -} - -// TimeoutRWMutex defines a RWMutex with timeouts on locks -type TimeoutRWMutex interface { - RWMutex - - // LockFunc is functionally the same as Lock(), but allows setting a custom hook called on timeout - LockFunc(func()) func() - - // RLockFunc is functionally the same as RLock(), but allows setting a custom hook called on timeout - RLockFunc(func()) func() -} - -// WithTimeout wraps the supplied Mutex to add a timeout -func WithTimeout(mu Mutex, d time.Duration) TimeoutMutex { - return &timeoutMutex{mu: mu, d: d} -} - -// WithTimeoutRW wraps the supplied RWMutex to add read/write timeouts -func WithTimeoutRW(mu RWMutex, rd, wd time.Duration) TimeoutRWMutex { - return &timeoutRWMutex{mu: mu, rd: rd, wd: wd} -} - -// timeoutMutex wraps a Mutex with timeout -type timeoutMutex struct { - mu Mutex // mu is the wrapped mutex - d time.Duration // d is the timeout duration -} - -func (mu *timeoutMutex) Lock() func() { - return mu.LockFunc(func() { panic("lock timed out") }) -} - -func (mu *timeoutMutex) LockFunc(fn func()) func() { - return mutexTimeout(mu.d, mu.mu.Lock(), fn) -} - -// TimeoutRWMutex wraps a RWMutex with timeouts -type timeoutRWMutex struct { - mu RWMutex // mu is the wrapped rwmutex - rd time.Duration // rd is the rlock timeout duration - wd time.Duration // wd is the lock timeout duration -} - -func (mu *timeoutRWMutex) Lock() func() { - return mu.LockFunc(func() { panic("lock timed out") }) -} - -func (mu *timeoutRWMutex) LockFunc(fn func()) func() { - return mutexTimeout(mu.wd, mu.mu.Lock(), fn) -} - -func (mu *timeoutRWMutex) RLock() func() { - return mu.RLockFunc(func() { panic("rlock timed out") }) -} - -func (mu *timeoutRWMutex) RLockFunc(fn func()) func() { - return mutexTimeout(mu.rd, mu.mu.RLock(), fn) -} - -// mutexTimeout performs a timed unlock, calling supplied fn if timeout is reached -func mutexTimeout(d time.Duration, unlock func(), fn func()) func() { - if d < 1 { - // No timeout, just unlock - return unlock - } - - // Start timer to call fn. - t := time.AfterFunc(d, fn) - - // Wrap unlock to stop mutex timer. - return func() { t.Stop(); unlock() } -} |