-
Notifications
You must be signed in to change notification settings - Fork 28
/
fake.go
131 lines (113 loc) · 3.21 KB
/
fake.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package concurrency
// mutexState is a type to represent different states of a mutex.
type mutexState uint64
// enumeration of different mutex states.
const (
mutexFree mutexState = iota
mutexLocked
)
// fakeMutex is an abstract representation of a mutex.
type fakeMutex struct {
// clock records the logical time of the last access to the mutex.
clock clock
// state records the state of the mutex.
state mutexState
}
// newFakeMutex is the fakeMutex factory.
func newFakeMutex(clock clock) *fakeMutex {
return &fakeMutex{clock: clock.clone()}
}
// free checks if the mutex is free.
func (m *fakeMutex) free() bool {
return m.state == mutexFree
}
// locked checks if the mutex is locked.
func (m *fakeMutex) locked() bool {
return m.state == mutexLocked
}
// lock models the action of locking the mutex.
func (m *fakeMutex) lock() {
if m.state != mutexFree {
panic("Locking a mutex that is already locked.")
}
m.state = mutexLocked
}
// unlock models the action of unlocking the mutex.
func (m *fakeMutex) unlock() {
if m.state != mutexLocked {
panic("Unlocking a mutex that is not locked.")
}
m.state = mutexFree
}
// rwMutexState is a type to represent different states of a mutex.
type rwMutexState uint64
// enumeration of different rwMutex states.
const (
rwMutexFree rwMutexState = iota
rwMutexShared
rwMutexExclusive
)
// fakeRWMutex is an abstract representation of a read-write mutex.
type fakeRWMutex struct {
// clock records the logical time of the last access to the
// read-write mutex.
clock clock
// state records the state of the read-write mutex.
state rwMutexState
// nreaders records the number of readers.
nreaders int
}
// newFakeRWMutex is the fakeRWMutex factory.
func newFakeRWMutex(clock clock) *fakeRWMutex {
return &fakeRWMutex{clock: clock.clone()}
}
// exclusive checks if the read-write mutex is exclusive.
func (rw *fakeRWMutex) exclusive() bool {
return rw.state == rwMutexExclusive
}
// free checks if the read-write mutex is free.
func (rw *fakeRWMutex) free() bool {
return rw.state == rwMutexFree
}
// shared checks if the read-write mutex is shared.
func (rw *fakeRWMutex) shared() bool {
return rw.state == rwMutexShared
}
// lock models the action of read-locking or write-locking the
// read-write mutex.
func (rw *fakeRWMutex) lock(read bool) {
if read {
if rw.state == rwMutexExclusive {
panic("Read-locking a read-write mutex that is write-locked.")
}
if rw.state == rwMutexFree {
rw.state = rwMutexShared
}
rw.nreaders++
} else {
if rw.state != rwMutexFree {
panic("Write-locking a read-write mutex that is not free.")
}
rw.state = rwMutexExclusive
}
}
// unlock models the action of unlocking the read-write mutex.
func (rw *fakeRWMutex) unlock(read bool) {
if read {
if rw.state != rwMutexShared {
panic("Read-unlocking a read-write mutex that is not read-locked.")
}
rw.nreaders--
if rw.nreaders == 0 {
rw.state = rwMutexFree
}
} else {
if rw.state != rwMutexExclusive {
panic("Write-unlocking a read-write mutex that is not write-locked.")
}
rw.state = rwMutexFree
}
}