You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gophi/core/mutex.go

60 lines
1.0 KiB
Go

package core
import (
"sync"
"sync/atomic"
"time"
)
type UpgradeableMutex struct {
wLast int64
internal sync.RWMutex
}
func (mu *UpgradeableMutex) RLock() {
mu.internal.RLock()
}
func (mu *UpgradeableMutex) RUnlock() {
mu.internal.RUnlock()
}
func (mu *UpgradeableMutex) Lock() {
// Get lock, set last write-lock time
mu.internal.Lock()
atomic.StoreInt64(&mu.wLast, time.Now().UnixNano())
}
func (mu *UpgradeableMutex) Unlock() {
mu.internal.Unlock()
}
func (mu *UpgradeableMutex) safeSwap(swapFn func()) bool {
// Get the 'now' time
now := time.Now().UnixNano()
// Store now time
atomic.StoreInt64(&mu.wLast, now)
// Perform the swap
swapFn()
// Successful swap determined by if last write-lock
// is still equal to 'now'
return atomic.LoadInt64(&mu.wLast) == now
}
func (mu *UpgradeableMutex) UpgradeLock() bool {
return mu.safeSwap(func() {
mu.internal.RUnlock()
mu.internal.Lock()
})
}
func (mu *UpgradeableMutex) DowngradeLock() bool {
return mu.safeSwap(func() {
mu.internal.Unlock()
mu.internal.RLock()
})
}