diff --git a/core/mutex.go b/core/mutex.go index 5b42364..88c0f94 100644 --- a/core/mutex.go +++ b/core/mutex.go @@ -6,29 +6,36 @@ import ( "time" ) +// UpgradeableMutex wraps a RWMutex and provides safe upgrading / downgrading +// by informing you whether a write lock was achieved in the brief swap time type UpgradeableMutex struct { wLast int64 internal sync.RWMutex } +// RLock exactly wraps the internal RWMutex func (mu *UpgradeableMutex) RLock() { mu.internal.RLock() } +// RUnlock exactly wraps the internal RWMutex func (mu *UpgradeableMutex) RUnlock() { mu.internal.RUnlock() } +// Lock wraps the internal RWMutex, atomically storing the last write-lock time func (mu *UpgradeableMutex) Lock() { - // Get lock, set last write-lock time mu.internal.Lock() atomic.StoreInt64(&mu.wLast, time.Now().UnixNano()) } +// Unlock exactly wraps the internal RWMutex func (mu *UpgradeableMutex) Unlock() { mu.internal.Unlock() } +// safeSwap stores the current time, performs the swap function and checks if +// any write locks were achieved during the swap function func (mu *UpgradeableMutex) safeSwap(swapFn func()) bool { // Get the 'now' time now := time.Now().UnixNano() @@ -44,6 +51,7 @@ func (mu *UpgradeableMutex) safeSwap(swapFn func()) bool { return atomic.LoadInt64(&mu.wLast) == now } +// UpgradeLock upgrades a read to a write lock, returning success state as a bool func (mu *UpgradeableMutex) UpgradeLock() bool { return mu.safeSwap(func() { mu.internal.RUnlock() @@ -51,6 +59,7 @@ func (mu *UpgradeableMutex) UpgradeLock() bool { }) } +// DowngradeLock downgrades a write to a read lock, returning success state as a bool func (mu *UpgradeableMutex) DowngradeLock() bool { return mu.safeSwap(func() { mu.internal.Unlock()