infra
/
goutils
Archived
1
0
Fork 0
This repository has been archived on 2022-04-06. You can view files and clone it, but cannot push or open issues or pull requests.
goutils/sync/reentrant_lock.go

46 lines
812 B
Go

package sync
import (
"sync"
"amuz.es/src/infra/goutils/runtime"
"sync/atomic"
"fmt"
)
type ReentrantMutex struct {
lock sync.Mutex
owner int64 // current lock owner
recursion int64 //current recursion level
}
func (r *ReentrantMutex) Lock() {
caller := runtime.GOID()
// fast path
if atomic.LoadInt64(&r.owner) == caller {
r.recursion++
return
}
r.lock.Lock()
// we are now inside the lock
atomic.StoreInt64(&r.owner, caller)
r.recursion = 1
}
func (r *ReentrantMutex) Unlock() {
caller := runtime.GOID()
if atomic.LoadInt64(&r.owner) != caller {
panic(fmt.Sprintf("you are not the owner(%d): %d!", r.owner, caller))
}
r.recursion--
// fast path
if r.recursion != 0 {
return
}
// we are going to release the lock
atomic.StoreInt64(&r.owner, 0)
r.lock.Unlock()
}