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

     1  package mutex
     2  
     3  import (
     4  	"context"
     5  
     6  	"golang.org/x/sync/semaphore"
     7  )
     8  
     9  const rwmutexMaxReaders = 1 << 30
    10  
    11  // CRWMutex implements a cancelable rwmutex (in fact also a try-able rwmutex)
    12  type CRWMutex struct {
    13  	sema *semaphore.Weighted
    14  }
    15  
    16  // NewCRWMutex is ctor for CRWMutex
    17  func NewCRWMutex() *CRWMutex {
    18  	rw := &CRWMutex{}
    19  	rw.Init()
    20  	return rw
    21  }
    22  
    23  // Init for embeded usage
    24  func (rw *CRWMutex) Init() {
    25  	rw.sema = semaphore.NewWeighted(rwmutexMaxReaders)
    26  }
    27  
    28  // Lock with context
    29  func (rw *CRWMutex) Lock(ctx context.Context) (err error) {
    30  	err = rw.sema.Acquire(ctx, rwmutexMaxReaders)
    31  	return
    32  }
    33  
    34  // Unlock should only be called after a successful Lock
    35  func (rw *CRWMutex) Unlock() {
    36  	rw.sema.Release(rwmutexMaxReaders)
    37  	return
    38  }
    39  
    40  // RLock with context
    41  func (rw *CRWMutex) RLock(ctx context.Context) (err error) {
    42  	err = rw.sema.Acquire(ctx, 1)
    43  	return
    44  }
    45  
    46  // RUnlock should only be called after a successful RLock
    47  func (rw *CRWMutex) RUnlock() {
    48  	rw.sema.Release(1)
    49  }
    50  
    51  // TryLock returns true if lock acquired
    52  func (rw *CRWMutex) TryLock() bool {
    53  	return rw.sema.TryAcquire(rwmutexMaxReaders)
    54  }
    55  
    56  // TryRLock returns true if rlock acquired
    57  func (rw *CRWMutex) TryRLock() bool {
    58  	return rw.sema.TryAcquire(1)
    59  }