-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathblock.go
92 lines (81 loc) · 1.28 KB
/
block.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
package syncdo
import "sync"
var ll2 = &sync.Mutex{}
var blm = make(map[string]*bmutex)
var bls = make([]*bmutex, 0)
var delc2 int
func BLock(b ...string) func() {
ll2.Lock()
var bl *bmutex
for _, k := range b {
if blm[k] != nil {
bl = blm[k]
break
}
}
// TODO more than one lock
for _, k := range b {
if blm[k] != nil && blm[k] != bl {
ll2.Unlock()
return nil
}
}
if bl == nil {
bl = usebl()
}
var found bool
for _, k := range b {
found = false
for _, k0 := range bl.set {
if k0 == k {
found = true
break
}
}
if !found {
bl.set = append(bl.set, k)
}
}
for _, k0 := range bl.set {
blm[k0] = bl
}
bl.num++
ll2.Unlock()
bl.Lock()
return func() {
ll2.Lock()
bl.num--
if bl.num == 0 {
for _, k0 := range bl.set {
delete(blm, k0)
delc2++
}
// go issue shrink map
if delc2 > 8192 && len(blm) < 128 {
m := make(map[string]*bmutex, len(blm))
for k, v := range blm {
m[k] = v
}
blm = m
delc2 = 0
}
}
ll2.Unlock()
bl.Unlock()
}
}
func usebl() *bmutex {
for _, bl := range bls {
if bl.num == 0 {
return bl
}
}
bl := &bmutex{Mutex: &sync.Mutex{}}
bls = append(bls, bl)
return bl
}
type bmutex struct {
*sync.Mutex
num int // number of waiters for the lock
set []string
}