-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathlock.go
95 lines (76 loc) · 1.34 KB
/
lock.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
package redis
import (
"time"
contractscache "github.com/goravel/framework/contracts/cache"
)
const NoExpiration time.Duration = 0
type Lock struct {
store contractscache.Driver
key string
time *time.Duration
get bool
}
func NewLock(instance contractscache.Driver, key string, t ...time.Duration) *Lock {
if len(t) == 0 {
return &Lock{
store: instance,
key: key,
}
}
return &Lock{
store: instance,
key: key,
time: &t[0],
}
}
func (r *Lock) Block(t time.Duration, callback ...func()) bool {
timer := time.NewTimer(t)
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
res := make(chan bool, 1)
go func() {
for {
select {
case <-timer.C:
if r.Get(callback...) {
res <- true
return
}
res <- false
return
case <-ticker.C:
if r.Get(callback...) {
res <- true
return
}
}
}
}()
return <-res
}
func (r *Lock) Get(callback ...func()) bool {
var res bool
if r.time == nil {
res = r.store.Add(r.key, 1, NoExpiration)
} else {
res = r.store.Add(r.key, 1, *r.time)
}
if !res {
return false
}
r.get = true
if len(callback) == 0 {
return true
}
callback[0]()
return r.Release()
}
func (r *Lock) Release() bool {
if r.get {
return r.ForceRelease()
}
return false
}
func (r *Lock) ForceRelease() bool {
return r.store.Forget(r.key)
}