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() }