github.com/gogf/gf/v2@v2.7.4/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/gogf/gf. 6 7 package gmlock 8 9 import ( 10 "sync" 11 12 "github.com/gogf/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 }