github.com/zhongdalu/gf@v1.0.0/g/os/gmlock/gmlock_locker.go (about)

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