github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/deadlock/rwmutex.go (about) 1 package deadlock 2 3 import ( 4 "context" 5 "unsafe" 6 ) 7 8 const rwmutexMaxReaders = 1 << 30 9 10 // RWMutex is like sync.RWMutex but with builtin deadlock detecting ability 11 type RWMutex struct { 12 sema *Weighted 13 } 14 15 // NewRWMutex is ctor for RWMutex 16 func NewRWMutex() *RWMutex { 17 rw := &RWMutex{} 18 rw.Init() 19 return rw 20 } 21 22 // Init for embeded usage 23 func (rw *RWMutex) Init() { 24 rw.sema = NewWeighted(rwmutexMaxReaders, rw) 25 } 26 27 // Lock for write lock 28 func (rw *RWMutex) Lock() { 29 rw.sema.Acquire(context.Background(), rwmutexMaxReaders) 30 return 31 } 32 33 // Unlock should only be called after a successful Lock 34 func (rw *RWMutex) Unlock() { 35 rw.sema.Release(rwmutexMaxReaders) 36 return 37 } 38 39 // RLock for read lock 40 func (rw *RWMutex) RLock() { 41 rw.sema.Acquire(context.Background(), 1) 42 } 43 44 // RUnlock should only be called after a successful RLock 45 func (rw *RWMutex) RUnlock() { 46 rw.sema.Release(1) 47 } 48 49 // TryLock returns true if lock acquired 50 func (rw *RWMutex) TryLock() bool { 51 return rw.sema.TryAcquire(rwmutexMaxReaders) 52 } 53 54 // TryRLock returns true if rlock acquired 55 func (rw *RWMutex) TryRLock() bool { 56 return rw.sema.TryAcquire(1) 57 } 58 59 func (rw *RWMutex) onAcquiredLocked(n int64) { 60 d.onAcquiredLocked(uint64(uintptr(unsafe.Pointer(rw))), n == rwmutexMaxReaders) 61 } 62 63 func (rw *RWMutex) onWaitLocked(n int64) { 64 d.onWaitLocked(uint64(uintptr(unsafe.Pointer(rw))), n == rwmutexMaxReaders) 65 } 66 67 func (rw *RWMutex) onWaitCanceledLocked(n int64) { 68 panic("this should never happen") 69 } 70 71 func (rw *RWMutex) onReleaseLocked(n int64) { 72 d.onReleaseLocked(uint64(uintptr(unsafe.Pointer(rw))), n == rwmutexMaxReaders) 73 }