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  }