GoToSocial/vendor/codeberg.org/gruf/go-mutexes/mutex.go

106 lines
2.3 KiB
Go

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()
}
}