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.
60 lines
1.0 KiB
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()
|
|
})
|
|
}
|