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/debug.go | 39 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/map.go | 466 | ||||
-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 | 137 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-mutexes/pool.go | 40 |
8 files changed, 0 insertions, 847 deletions
diff --git a/vendor/codeberg.org/gruf/go-mutexes/LICENSE b/vendor/codeberg.org/gruf/go-mutexes/LICENSE deleted file mode 100644 index b7c4417ac..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright (c) 2021 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/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/map.go b/vendor/codeberg.org/gruf/go-mutexes/map.go deleted file mode 100644 index c0f740eec..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/map.go +++ /dev/null @@ -1,466 +0,0 @@ -package mutexes - -import ( - "runtime" - "sync" - "sync/atomic" -) - -const ( - // possible lock types. - lockTypeRead = uint8(1) << 0 - lockTypeWrite = uint8(1) << 1 - lockTypeMap = uint8(1) << 2 - - // possible mutexmap states. - stateUnlockd = uint8(0) - stateRLocked = uint8(1) - stateLocked = uint8(2) - stateInUse = uint8(3) - - // default values. - defaultWake = 1024 -) - -// acquireState attempts to acquire required map state for lockType. -func acquireState(state uint8, lt uint8) (uint8, bool) { - switch state { - // Unlocked state - // (all allowed) - case stateUnlockd: - - // Keys locked, no state lock. - // (don't allow map locks) - case stateInUse: - if lt&lockTypeMap != 0 { - return 0, false - } - - // Read locked - // (only allow read locks) - case stateRLocked: - if lt&lockTypeRead == 0 { - return 0, false - } - - // Write locked - // (none allowed) - case stateLocked: - return 0, false - - // shouldn't reach here - default: - panic("unexpected state") - } - - switch { - // If unlocked and not a map - // lock request, set in use - case lt&lockTypeMap == 0: - if state == stateUnlockd { - state = stateInUse - } - - // Set read lock state - case lt&lockTypeRead != 0: - state = stateRLocked - - // Set write lock state - case lt&lockTypeWrite != 0: - state = stateLocked - - default: - panic("unexpected lock type") - } - - return state, true -} - -// MutexMap is a structure that allows read / write locking key, performing -// as you'd expect a map[string]*sync.RWMutex to perform. The differences -// being that the entire map can itself be read / write locked, it uses memory -// pooling for the mutex (not quite) structures, and it is self-evicting. The -// core configurations of maximum no. open locks and wake modulus* are user -// definable. -// -// * The wake modulus is the number that the current number of open locks is -// modulused against to determine how often to notify sleeping goroutines. -// These are goroutines that are attempting to lock a key / whole map and are -// awaiting a permissible state (.e.g no key write locks allowed when the -// map is read locked). -type MutexMap struct { - qpool pool - queue []*sync.Mutex - - mumap map[string]*rwmutex - mpool pool - evict []*rwmutex - - count int32 - maxmu int32 - wake int32 - - mapmu sync.Mutex - state uint8 -} - -// NewMap returns a new MutexMap instance with provided max no. open mutexes. -func NewMap(max, wake int32) MutexMap { - // Determine wake mod. - if wake < 1 { - wake = defaultWake - } - - // Determine max no. mutexes - if max < 1 { - procs := runtime.GOMAXPROCS(0) - max = wake * int32(procs) - } - - return MutexMap{ - qpool: pool{ - alloc: func() interface{} { - return &sync.Mutex{} - }, - }, - mumap: make(map[string]*rwmutex, max), - mpool: pool{ - alloc: func() interface{} { - return &rwmutex{} - }, - }, - maxmu: max, - wake: wake, - } -} - -// MAX sets the MutexMap max open locks and wake modulus, returns current values. -// For values less than zero defaults are set, and zero is non-op. -func (mm *MutexMap) SET(max, wake int32) (int32, int32) { - mm.mapmu.Lock() - - switch { - // Set default wake - case wake < 0: - mm.wake = defaultWake - - // Set supplied wake - case wake > 0: - mm.wake = wake - } - - switch { - // Set default max - case max < 0: - procs := runtime.GOMAXPROCS(0) - mm.maxmu = wake * int32(procs) - - // Set supplied max - case max > 0: - mm.maxmu = max - } - - // Fetch values - max = mm.maxmu - wake = mm.wake - - mm.mapmu.Unlock() - return max, wake -} - -// spinLock will wait (using a mutex to sleep thread) until conditional returns true. -func (mm *MutexMap) spinLock(cond func() bool) { - var mu *sync.Mutex - - for { - // Acquire map lock - mm.mapmu.Lock() - - if cond() { - // Release mu if needed - if mu != nil { - mm.qpool.Release(mu) - } - return - } - - // Alloc mu if needed - if mu == nil { - v := mm.qpool.Acquire() - mu = v.(*sync.Mutex) - } - - // Queue ourselves - mm.queue = append(mm.queue, mu) - mu.Lock() - - // Unlock map - mm.mapmu.Unlock() - - // Wait on notify - mu.Lock() - mu.Unlock() - } -} - -// lock will acquire a lock of given type on the 'mutex' at key. -func (mm *MutexMap) lock(key string, lt uint8) func() { - var ok bool - var mu *rwmutex - - // Spin lock until returns true - mm.spinLock(func() bool { - // Check not overloaded - if !(mm.count < mm.maxmu) { - return false - } - - // Attempt to acquire usable map state - state, ok := acquireState(mm.state, lt) - if !ok { - return false - } - - // Update state - mm.state = state - - // Ensure mutex at key - // is in lockable state - mu, ok = mm.mumap[key] - return !ok || mu.CanLock(lt) - }) - - // Incr count - mm.count++ - - if !ok { - // No mutex found for key - - // Alloc from pool - v := mm.mpool.Acquire() - mu = v.(*rwmutex) - mm.mumap[key] = mu - - // Set our key - mu.key = key - - // Queue for eviction - mm.evict = append(mm.evict, mu) - } - - // Lock mutex - mu.Lock(lt) - - // Unlock map - mm.mapmu.Unlock() - - return func() { - mm.mapmu.Lock() - mu.Unlock() - go mm.cleanup() - } -} - -// lockMap will lock the whole map under given lock type. -func (mm *MutexMap) lockMap(lt uint8) { - // Spin lock until returns true - mm.spinLock(func() bool { - // Attempt to acquire usable map state - state, ok := acquireState(mm.state, lt) - if !ok { - return false - } - - // Update state - mm.state = state - - return true - }) - - // Incr count - mm.count++ - - // State acquired, unlock - mm.mapmu.Unlock() -} - -// cleanup is performed as the final stage of unlocking a locked key / map state, finally unlocks map. -func (mm *MutexMap) cleanup() { - // Decr count - mm.count-- - - if mm.count%mm.wake == 0 { - // Notify queued routines - for _, mu := range mm.queue { - mu.Unlock() - } - - // Reset queue - mm.queue = mm.queue[:0] - } - - if mm.count < 1 { - // Perform evictions - for _, mu := range mm.evict { - key := mu.key - mu.key = "" - delete(mm.mumap, key) - mm.mpool.Release(mu) - } - - // Reset map state - mm.evict = mm.evict[:0] - mm.state = stateUnlockd - mm.mpool.GC() - mm.qpool.GC() - } - - // Unlock map - mm.mapmu.Unlock() -} - -// RLockMap acquires a read lock over the entire map, returning a lock state for acquiring key read locks. -// Please note that the 'unlock()' function will block until all keys locked from this state are unlocked. -func (mm *MutexMap) RLockMap() *LockState { - mm.lockMap(lockTypeRead | lockTypeMap) - return &LockState{ - mmap: mm, - ltyp: lockTypeRead, - } -} - -// LockMap acquires a write lock over the entire map, returning a lock state for acquiring key read/write locks. -// Please note that the 'unlock()' function will block until all keys locked from this state are unlocked. -func (mm *MutexMap) LockMap() *LockState { - mm.lockMap(lockTypeWrite | lockTypeMap) - return &LockState{ - mmap: mm, - ltyp: lockTypeWrite, - } -} - -// RLock acquires a mutex read lock for supplied key, returning an RUnlock function. -func (mm *MutexMap) RLock(key string) (runlock func()) { - return mm.lock(key, lockTypeRead) -} - -// Lock acquires a mutex write lock for supplied key, returning an Unlock function. -func (mm *MutexMap) Lock(key string) (unlock func()) { - return mm.lock(key, lockTypeWrite) -} - -// LockState represents a window to a locked MutexMap. -type LockState struct { - wait sync.WaitGroup - mmap *MutexMap - done uint32 - ltyp uint8 -} - -// Lock: see MutexMap.Lock() definition. Will panic if map only read locked. -func (st *LockState) Lock(key string) (unlock func()) { - return st.lock(key, lockTypeWrite) -} - -// RLock: see MutexMap.RLock() definition. -func (st *LockState) RLock(key string) (runlock func()) { - return st.lock(key, lockTypeRead) -} - -// lock: see MutexMap.lock() definition. -func (st *LockState) lock(key string, lt uint8) func() { - st.wait.Add(1) // track lock - - if atomic.LoadUint32(&st.done) == 1 { - panic("called (r)lock on unlocked state") - } else if lt&lockTypeWrite != 0 && - st.ltyp&lockTypeWrite == 0 { - panic("called lock on rlocked map") - } - - var ok bool - var mu *rwmutex - - // Spin lock until returns true - st.mmap.spinLock(func() bool { - // Check not overloaded - if !(st.mmap.count < st.mmap.maxmu) { - return false - } - - // Ensure mutex at key - // is in lockable state - mu, ok = st.mmap.mumap[key] - return !ok || mu.CanLock(lt) - }) - - // Incr count - st.mmap.count++ - - if !ok { - // No mutex found for key - - // Alloc from pool - v := st.mmap.mpool.Acquire() - mu = v.(*rwmutex) - st.mmap.mumap[key] = mu - - // Set our key - mu.key = key - - // Queue for eviction - st.mmap.evict = append(st.mmap.evict, mu) - } - - // Lock mutex - mu.Lock(lt) - - // Unlock map - st.mmap.mapmu.Unlock() - - return func() { - st.mmap.mapmu.Lock() - mu.Unlock() - go st.mmap.cleanup() - st.wait.Add(-1) - } -} - -// UnlockMap will close this state and release the currently locked map. -func (st *LockState) UnlockMap() { - if !atomic.CompareAndSwapUint32(&st.done, 0, 1) { - panic("called unlockmap on expired state") - } - st.wait.Wait() - st.mmap.mapmu.Lock() - go st.mmap.cleanup() -} - -// rwmutex is a very simple *representation* of a read-write -// mutex, though not one in implementation. it works by -// tracking the lock state for a given map key, which is -// protected by the map's mutex. -type rwmutex struct { - rcnt uint32 - lock uint8 - key string -} - -func (mu *rwmutex) CanLock(lt uint8) bool { - return mu.lock == 0 || - (mu.lock&lockTypeRead != 0 && lt&lockTypeRead != 0) -} - -func (mu *rwmutex) Lock(lt uint8) { - mu.lock = lt - if lt&lockTypeRead != 0 { - mu.rcnt++ - } -} - -func (mu *rwmutex) Unlock() { - mu.rcnt-- - if mu.rcnt == 0 { - mu.lock = 0 - } -} 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 03bf0e389..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/mutex_timeout.go +++ /dev/null @@ -1,137 +0,0 @@ -package mutexes - -import ( - "sync" - "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 - } - - // Acquire timer from pool - t := timerPool.Get().(*timer) - - // Start the timer - go t.Start(d, fn) - - // Return func cancelling timeout, - // replacing Timeout in pool and - // finally unlocking mutex - return func() { - defer timerPool.Put(t) - t.Cancel() - unlock() - } -} - -// timerPool is the global &timer{} pool. -var timerPool = sync.Pool{ - New: func() interface{} { - t := time.NewTimer(time.Minute) - t.Stop() - return &timer{t: t, c: make(chan struct{})} - }, -} - -// timer represents a reusable cancellable timer. -type timer struct { - t *time.Timer - c chan struct{} -} - -// Start will start the timer with duration 'd', performing 'fn' on timeout. -func (t *timer) Start(d time.Duration, fn func()) { - t.t.Reset(d) - select { - // Timed out - case <-t.t.C: - fn() - - // Cancelled - case <-t.c: - } -} - -// Cancel will attempt to cancel the running timer. -func (t *timer) Cancel() { - select { - // cancel successful - case t.c <- struct{}{}: - if !t.t.Stop() { - <-t.t.C - } // stop timer - - // already stopped - default: - } -} diff --git a/vendor/codeberg.org/gruf/go-mutexes/pool.go b/vendor/codeberg.org/gruf/go-mutexes/pool.go deleted file mode 100644 index 135e2c117..000000000 --- a/vendor/codeberg.org/gruf/go-mutexes/pool.go +++ /dev/null @@ -1,40 +0,0 @@ -package mutexes - -// pool is a very simply memory pool. -type pool struct { - current []interface{} - victim []interface{} - alloc func() interface{} -} - -// Acquire will returns a sync.RWMutex from pool (or alloc new). -func (p *pool) Acquire() interface{} { - // First try the current queue - if l := len(p.current) - 1; l >= 0 { - v := p.current[l] - p.current = p.current[:l] - return v - } - - // Next try the victim queue. - if l := len(p.victim) - 1; l >= 0 { - v := p.victim[l] - p.victim = p.victim[:l] - return v - } - - // Lastly, alloc new. - return p.alloc() -} - -// Release places a sync.RWMutex back in the pool. -func (p *pool) Release(v interface{}) { - p.current = append(p.current, v) -} - -// GC will clear out unused entries from the pool. -func (p *pool) GC() { - current := p.current - p.current = nil - p.victim = current -} |