-
Notifications
You must be signed in to change notification settings - Fork 0
/
ugmutex.go
99 lines (77 loc) · 1.32 KB
/
ugmutex.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
package mutex
import (
"sync"
"sync/atomic"
)
type UgMutex struct {
l *sync.Mutex
c_l *sync.Cond
c_u *sync.Cond
wlf int32
ulf int32
cnt int32
}
func NewUgMutex() *UgMutex {
l := new(sync.Mutex)
return &UgMutex{l:l, c_l:sync.NewCond(l), c_u:sync.NewCond(l)}
}
func (m *UgMutex) Lock() {
for {
m.lockSlow()
if atomic.CompareAndSwapInt32(&m.wlf, MODE_OFF, MODE_ON) {
break
}
}
}
func (m *UgMutex) RLock() {
m.l.Lock()
if atomic.LoadInt32(&m.wlf) == MODE_ON {
m.c_l.Wait()
}
n_cnt := atomic.AddInt32(&m.cnt, int32(1))
if n_cnt > MAX_CNT || n_cnt < 0 {
panic("counter out of range.")
}
if n_cnt > 1 {
m.l.Unlock()
}
}
func (m *UgMutex) UgLock() {
m.lockSlow()
m.ulf = MODE_ON
m.l.Unlock()
}
func (m *UgMutex) Upgrade() {
atomic.StoreInt32(&m.wlf, MODE_ON)
m.l.Lock()
}
func (m *UgMutex) UgUnlock() {
if !atomic.CompareAndSwapInt32(&m.wlf, MODE_ON, MODE_OFF) {
m.l.Lock()
}
m.ulf = MODE_OFF
m.l.Unlock()
m.c_u.Signal()
m.c_l.Broadcast()
}
func (m *UgMutex) RUnlock() {
if n_cnt := atomic.AddInt32(&m.cnt, int32(-1)); n_cnt < 1 {
m.l.Unlock()
}
}
func (m *UgMutex) Unlock() {
atomic.StoreInt32(&m.wlf, MODE_OFF)
m.l.Unlock()
m.c_u.Signal()
m.c_l.Broadcast()
}
func (m *UgMutex) lockSlow() {
m.l.Lock()
for {
if m.ulf != MODE_OFF {
m.c_u.Wait()
continue
}
break
}
}