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 }