github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/f/lock.go (about) 1 /* 2 Package locker is a simple package to manage named ReadWrite mutexes. These 3 appear to be especially useful for synchronizing access to session based 4 information in web applications. 5 6 The common use case is to use the package level functions, which use a package 7 level set of locks (safe to use from multiple goroutines simultaneously). 8 However, you may also create a new separate set of locks. 9 10 All locks are implemented with read-write mutexes. To use them like a regular 11 mutex, simply ignore the RLock/RUnlock functions. 12 */ 13 package f 14 15 // github.com/BurntSushi/locker 16 // BUG: The locker here can grow without bound in long running 17 // programs. Since it's intended to be used in web applications, this is a 18 // major problem. Figure out a way to keep the locker lean. 19 20 import ( 21 "sync" 22 ) 23 24 // Locker represents the set of named ReadWrite mutexes. It is safe to access 25 // from multiple goroutines simultaneously. 26 type Locker struct { 27 locks map[string]*sync.RWMutex 28 locksRW *sync.RWMutex 29 } 30 31 var locker *Locker 32 33 func init() { 34 locker = NewLocker() 35 } 36 37 func Lock(key string) { locker.Lock(key) } 38 func Unlock(key string) { locker.Unlock(key) } 39 func RLock(key string) { locker.RLock(key) } 40 func RUnlock(key string) { locker.RUnlock(key) } 41 func DeLock(key string) { locker.deleteLock(key) } 42 43 func NewLocker() *Locker { 44 return &Locker{ 45 locks: make(map[string]*sync.RWMutex), 46 locksRW: new(sync.RWMutex), 47 } 48 } 49 50 func (l *Locker) Lock(key string) { 51 lk, ok := l.getLock(key) 52 if !ok { 53 lk = l.newLock(key) 54 } 55 lk.Lock() 56 } 57 58 func (l *Locker) Unlock(key string) { 59 lk, ok := l.getLock(key) 60 if ok { 61 lk.Unlock() 62 } 63 } 64 65 func (l *Locker) RLock(key string) { 66 lk, ok := l.getLock(key) 67 if !ok { 68 lk = l.newLock(key) 69 } 70 lk.RLock() 71 } 72 73 func (l *Locker) RUnlock(key string) { 74 lk, ok := l.getLock(key) 75 if ok { 76 lk.RUnlock() 77 } 78 } 79 80 func (l *Locker) newLock(key string) *sync.RWMutex { 81 l.locksRW.Lock() 82 defer l.locksRW.Unlock() 83 84 if lk, ok := l.locks[key]; ok { 85 return lk 86 } 87 lk := new(sync.RWMutex) 88 l.locks[key] = lk 89 return lk 90 } 91 92 func (l *Locker) getLock(key string) (*sync.RWMutex, bool) { 93 l.locksRW.RLock() 94 defer l.locksRW.RUnlock() 95 96 lock, ok := l.locks[key] 97 return lock, ok 98 } 99 100 func (l *Locker) deleteLock(key string) { 101 l.locksRW.Lock() 102 defer l.locksRW.Unlock() 103 104 if _, ok := l.locks[key]; ok { 105 delete(l.locks, key) 106 } 107 }