github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/deadlock/mutex.go (about)

     1  package deadlock
     2  
     3  import (
     4  	"context"
     5  	"unsafe"
     6  )
     7  
     8  // Mutex is like sync.Mutex but with builtin deadlock detecting ability
     9  type Mutex struct {
    10  	sema *Weighted
    11  }
    12  
    13  // NewMutex is ctor for Mutex
    14  func NewMutex() *Mutex {
    15  	m := &Mutex{}
    16  	m.Init()
    17  	return m
    18  }
    19  
    20  // Init for embeded usage
    21  func (m *Mutex) Init() {
    22  	m.sema = NewWeighted(1, m)
    23  }
    24  
    25  // Lock with context
    26  func (m *Mutex) Lock() (err error) {
    27  	err = m.sema.Acquire(context.Background(), 1)
    28  	return
    29  }
    30  
    31  // Unlock should only be called after a successful Lock
    32  func (m *Mutex) Unlock() {
    33  	m.sema.Release(1)
    34  }
    35  
    36  // TryLock returns true if lock acquired
    37  func (m *Mutex) TryLock() bool {
    38  	return m.sema.TryAcquire(1)
    39  }
    40  
    41  func (m *Mutex) onAcquiredLocked(n int64) {
    42  	d.onAcquiredLocked(uint64(uintptr(unsafe.Pointer(m))), true)
    43  }
    44  
    45  func (m *Mutex) onWaitLocked(n int64) {
    46  	d.onWaitLocked(uint64(uintptr(unsafe.Pointer(m))), true)
    47  }
    48  
    49  func (m *Mutex) onWaitCanceledLocked(n int64) {
    50  	panic("this should never happen")
    51  }
    52  
    53  func (m *Mutex) onReleaseLocked(n int64) {
    54  	d.onReleaseLocked(uint64(uintptr(unsafe.Pointer(m))), true)
    55  }