-
Notifications
You must be signed in to change notification settings - Fork 9
/
wplock.go
58 lines (47 loc) · 1.17 KB
/
wplock.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
package common
import (
"sync"
"sync/atomic"
)
// WP lock, write Prior lock is a lock built based on sync.WRLock.
// Just as WRLock, Write is an exclusive lock, and Read is a shared lock.
// WP adds an extra behaviour that read lock is also blocked while a write is waiting.
// So that an exclusive lock will not be starving when read lock is acquired extremely intensive
type WPLock struct {
writeLock sync.Mutex
waiting int32
waitingLock sync.Mutex
lock sync.RWMutex
}
// Lock is the exclusive lock
func (wp *WPLock) Lock() {
wp.waitingLock.Lock()
if atomic.CompareAndSwapInt32(&wp.waiting, 0, 1) {
wp.writeLock.Lock()
} else {
atomic.AddInt32(&wp.waiting, 1)
}
wp.waitingLock.Unlock()
wp.lock.Lock()
}
// Unlock release the exclusive lock
func (wp *WPLock) Unlock() {
wp.waitingLock.Lock()
if atomic.CompareAndSwapInt32(&wp.waiting, 1, 0) {
wp.writeLock.Unlock()
} else {
atomic.AddInt32(&wp.waiting, -1)
}
wp.waitingLock.Unlock()
wp.lock.Unlock()
}
// RLock locks for read
func (wp *WPLock) RLock() {
wp.writeLock.Lock()
wp.writeLock.Unlock()
wp.lock.RLock()
}
// RUnlock unlocks the read
func (wp *WPLock) RUnlock() {
wp.lock.RUnlock()
}