-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmutex.go
67 lines (56 loc) · 1 KB
/
mutex.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
package var_mtx
import (
"sync"
)
type refMutex struct {
ref int32
mtx *sync.Mutex
}
type VarMutex struct {
mtx *sync.Mutex
var_mtx map[interface{}]*refMutex
}
func NewVarMutex() *VarMutex {
return &VarMutex{
mtx: &sync.Mutex{},
var_mtx: map[interface{}]*refMutex{},
}
}
func (km *VarMutex) incr_mtx(key interface{}) *sync.Mutex {
km.mtx.Lock()
defer km.mtx.Unlock()
rm, ok := km.var_mtx[key]
if ok {
rm.ref++
if rm.ref <= 0 {
panic("too many locks")
}
} else {
rm = &refMutex{ref: 1, mtx: &sync.Mutex{}}
km.var_mtx[key] = rm
}
return rm.mtx
}
func (km *VarMutex) decr_mtx(key interface{}) *sync.Mutex {
km.mtx.Lock()
defer km.mtx.Unlock()
rm, ok := km.var_mtx[key]
if !ok {
panic("not locked")
}
mtx := rm.mtx
rm.ref--
if rm.ref <= 0 {
rm.mtx = nil
delete(km.var_mtx, key)
}
return mtx
}
func (km *VarMutex) Lock(key interface{}) {
mtx := km.incr_mtx(key)
mtx.Lock()
}
func (km *VarMutex) Unlock(key interface{}) {
mtx := km.decr_mtx(key)
mtx.Unlock()
}