amuz.es/src/infra/goutils@v0.1.3/sync/reentrant_lock.go (about) 1 package sync 2 3 import ( 4 "sync" 5 "amuz.es/src/infra/goutils/runtime" 6 "sync/atomic" 7 "fmt" 8 ) 9 10 type ReentrantMutex struct { 11 lock sync.Mutex 12 owner int64 // current lock owner 13 recursion int64 //current recursion level 14 } 15 16 func (r *ReentrantMutex) Lock() { 17 caller := runtime.GOID() 18 // fast path 19 if atomic.LoadInt64(&r.owner) == caller { 20 r.recursion++ 21 return 22 } 23 24 r.lock.Lock() 25 // we are now inside the lock 26 atomic.StoreInt64(&r.owner, caller) 27 r.recursion = 1 28 } 29 30 func (r *ReentrantMutex) Unlock() { 31 caller := runtime.GOID() 32 if atomic.LoadInt64(&r.owner) != caller { 33 panic(fmt.Sprintf("you are not the owner(%d): %d!", r.owner, caller)) 34 } 35 36 r.recursion-- 37 // fast path 38 if r.recursion != 0 { 39 return 40 } 41 42 // we are going to release the lock 43 atomic.StoreInt64(&r.owner, 0) 44 r.lock.Unlock() 45 }