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