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 }