46 lines
812 B
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()
|
|
}
|