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 }