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  }