github.com/wangyougui/gf/v2@v2.6.5/os/gmlock/gmlock_locker.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/wangyougui/gf.
     6  
     7  package gmlock
     8  
     9  import (
    10  	"sync"
    11  
    12  	"github.com/wangyougui/gf/v2/container/gmap"
    13  )
    14  
    15  // Locker is a memory based locker.
    16  // Note that there's no cache expire mechanism for mutex in locker.
    17  // You need remove certain mutex manually when you do not want use it anymore.
    18  type Locker struct {
    19  	m *gmap.StrAnyMap
    20  }
    21  
    22  // New creates and returns a new memory locker.
    23  // A memory locker can lock/unlock with dynamic string key.
    24  func New() *Locker {
    25  	return &Locker{
    26  		m: gmap.NewStrAnyMap(true),
    27  	}
    28  }
    29  
    30  // Lock locks the `key` with writing lock.
    31  // If there's a write/reading lock the `key`,
    32  // it will block until the lock is released.
    33  func (l *Locker) Lock(key string) {
    34  	l.getOrNewMutex(key).Lock()
    35  }
    36  
    37  // TryLock tries locking the `key` with writing lock,
    38  // it returns true if success, or it returns false if there's a writing/reading lock the `key`.
    39  func (l *Locker) TryLock(key string) bool {
    40  	return l.getOrNewMutex(key).TryLock()
    41  }
    42  
    43  // Unlock unlocks the writing lock of the `key`.
    44  func (l *Locker) Unlock(key string) {
    45  	if v := l.m.Get(key); v != nil {
    46  		v.(*sync.RWMutex).Unlock()
    47  	}
    48  }
    49  
    50  // RLock locks the `key` with reading lock.
    51  // If there's a writing lock on `key`,
    52  // it will blocks until the writing lock is released.
    53  func (l *Locker) RLock(key string) {
    54  	l.getOrNewMutex(key).RLock()
    55  }
    56  
    57  // TryRLock tries locking the `key` with reading lock.
    58  // It returns true if success, or if there's a writing lock on `key`, it returns false.
    59  func (l *Locker) TryRLock(key string) bool {
    60  	return l.getOrNewMutex(key).TryRLock()
    61  }
    62  
    63  // RUnlock unlocks the reading lock of the `key`.
    64  func (l *Locker) RUnlock(key string) {
    65  	if v := l.m.Get(key); v != nil {
    66  		v.(*sync.RWMutex).RUnlock()
    67  	}
    68  }
    69  
    70  // LockFunc locks the `key` with writing lock and callback function `f`.
    71  // If there's a write/reading lock the `key`,
    72  // it will block until the lock is released.
    73  //
    74  // It releases the lock after `f` is executed.
    75  func (l *Locker) LockFunc(key string, f func()) {
    76  	l.Lock(key)
    77  	defer l.Unlock(key)
    78  	f()
    79  }
    80  
    81  // RLockFunc locks the `key` with reading lock and callback function `f`.
    82  // If there's a writing lock the `key`,
    83  // it will block until the lock is released.
    84  //
    85  // It releases the lock after `f` is executed.
    86  func (l *Locker) RLockFunc(key string, f func()) {
    87  	l.RLock(key)
    88  	defer l.RUnlock(key)
    89  	f()
    90  }
    91  
    92  // TryLockFunc locks the `key` with writing lock and callback function `f`.
    93  // It returns true if success, or else if there's a write/reading lock the `key`, it return false.
    94  //
    95  // It releases the lock after `f` is executed.
    96  func (l *Locker) TryLockFunc(key string, f func()) bool {
    97  	if l.TryLock(key) {
    98  		defer l.Unlock(key)
    99  		f()
   100  		return true
   101  	}
   102  	return false
   103  }
   104  
   105  // TryRLockFunc locks the `key` with reading lock and callback function `f`.
   106  // It returns true if success, or else if there's a writing lock the `key`, it returns false.
   107  //
   108  // It releases the lock after `f` is executed.
   109  func (l *Locker) TryRLockFunc(key string, f func()) bool {
   110  	if l.TryRLock(key) {
   111  		defer l.RUnlock(key)
   112  		f()
   113  		return true
   114  	}
   115  	return false
   116  }
   117  
   118  // Remove removes mutex with given `key` from locker.
   119  func (l *Locker) Remove(key string) {
   120  	l.m.Remove(key)
   121  }
   122  
   123  // Clear removes all mutexes from locker.
   124  func (l *Locker) Clear() {
   125  	l.m.Clear()
   126  }
   127  
   128  // getOrNewMutex returns the mutex of given `key` if it exists,
   129  // or else creates and returns a new one.
   130  func (l *Locker) getOrNewMutex(key string) *sync.RWMutex {
   131  	return l.m.GetOrSetFuncLock(key, func() interface{} {
   132  		return &sync.RWMutex{}
   133  	}).(*sync.RWMutex)
   134  }