-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwrapped.go
100 lines (89 loc) · 2.13 KB
/
wrapped.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
package detectlock
func acquire(lockerPtr uintptr, rLocker bool, doLock func()) {
if doLock == nil {
return
}
gid := getGoroutineID()
shardKey := gid % shardCount
mapShard := cache[shardKey]
var locker *LockerState
func() {
defer mapShard.locker.Unlock()
mapShard.locker.Lock()
var lockers []*LockerState
if exists, ok := mapShard.items[gid]; ok {
lockers = exists
} else {
lockers = make([]*LockerState, 0, 16)
}
locker = &LockerState{LockerPtr: lockerPtr, Status: StatusWait, RLocker: rLocker}
lockers = append(lockers, locker)
mapShard.items[gid] = lockers
}()
locker.Caller = getCaller(4)
doLock()
locker.Status = StatusAcquired
}
func tryAcquire(lockerPtr uintptr, rLocker bool, tryLock func() bool) bool {
if tryLock == nil {
return false
}
if tryLock() {
gid := getGoroutineID()
shardKey := gid % shardCount
mapShard := cache[shardKey]
var locker *LockerState
func() {
defer mapShard.locker.Unlock()
mapShard.locker.Lock()
var lockers []*LockerState
if exists, ok := mapShard.items[gid]; ok {
lockers = exists
} else {
lockers = make([]*LockerState, 0, 16)
}
locker = &LockerState{LockerPtr: lockerPtr, Status: StatusAcquired, RLocker: rLocker}
lockers = append(lockers, locker)
mapShard.items[gid] = lockers
}()
locker.Caller = getCaller(4)
return true
} else {
return false
}
}
func release(lockerPtr uintptr, rLocker bool, doUnlock func()) {
if doUnlock == nil {
return
}
doUnlock()
gid := getGoroutineID()
shardKey := gid % shardCount
mapShard := cache[shardKey]
defer mapShard.locker.Unlock()
mapShard.locker.Lock()
if lockers, ok := mapShard.items[gid]; ok {
removeIndex := -1
for i := 0; i < len(lockers); i++ {
l := lockers[i]
if l.LockerPtr == lockerPtr && l.Status == StatusAcquired && l.RLocker == rLocker {
removeIndex = i
break
}
}
if removeIndex < 0 {
return
}
llen := len(lockers)
if llen == 1 {
lockers = nil
} else {
lockers = append(lockers[:removeIndex], lockers[removeIndex+1:]...)
}
if len(lockers) == 0 {
delete(mapShard.items, gid)
} else {
mapShard.items[gid] = lockers
}
}
}