anode/xlock/
write_biased.rs1use std::time::Duration;
2use crate::deadline::Deadline;
3use crate::monitor::{Directive, Monitor, SpeculativeMonitor};
4use crate::xlock::{Moderator};
5
6#[derive(Debug)]
7pub struct WriteBiased;
8
9pub struct WriteBiasedSync {
10 monitor: SpeculativeMonitor<WriteBiasedState>,
11}
12
13#[derive(Debug)]
14struct WriteBiasedState {
15 readers: u32,
16 writer: bool,
17 writer_pending: bool,
18}
19
20impl Moderator for WriteBiased {
21 type Sync = WriteBiasedSync;
22
23 #[inline]
24 fn new() -> Self::Sync {
25 Self::Sync {
26 monitor: SpeculativeMonitor::new(WriteBiasedState { readers: 0, writer: false, writer_pending: false }),
27 }
28 }
29
30 #[inline]
31 fn try_read(sync: &Self::Sync, duration: Duration) -> bool {
32 let mut deadline = Deadline::lazy_after(duration);
33 let mut acquired = false;
34 let mut saw_no_pending_writer = false;
35 sync.monitor.enter(|state| {
36 if !state.writer_pending {
37 saw_no_pending_writer = true;
38 }
39
40 if !acquired && !state.writer && saw_no_pending_writer {
41 acquired = true;
42 state.readers += 1;
43 }
44
45 if acquired {
46 Directive::Return
47 } else {
48 Directive::Wait(deadline.remaining())
49 }
50 });
51 acquired
52 }
53
54 #[inline]
55 fn read_unlock(sync: &Self::Sync) {
56 let mut released = false;
57 sync.monitor.enter(|state| {
58 if !released {
59 debug_assert!(state.readers > 0, "readers: {}", state.readers);
60 debug_assert!(!state.writer);
61
62 released = true;
63 state.readers -= 1;
64 }
65
66 match state.readers {
67 0 | 1 => Directive::NotifyAll,
68 _ => Directive::Return
69 }
70 });
71 }
72
73 #[inline]
74 fn try_write(sync: &Self::Sync, duration: Duration) -> bool {
75 let mut deadline = Deadline::lazy_after(duration);
76 let mut acquired = false;
77 let mut self_writer_pending = false;
78 sync.monitor.enter(|state| {
79 if !acquired {
80 if state.readers == 0 && !state.writer {
81 state.writer = true;
82 acquired = true;
83 } else if !state.writer_pending {
84 self_writer_pending = true;
85 state.writer_pending = true;
86 }
87 }
88
89 if acquired {
90 Directive::Return
91 } else {
92 Directive::Wait(deadline.remaining())
93 }
94 });
95
96 if self_writer_pending {
97 let mut cleared_writer_pending = false;
98 sync.monitor.enter(|state| {
99 if !cleared_writer_pending {
100 cleared_writer_pending = true;
101 state.writer_pending = false;
102 }
103
104 if acquired {
105 Directive::Return
106 } else {
107 Directive::NotifyAll
108 }
109 });
110 }
111
112 acquired
113 }
114
115 #[inline]
116 fn write_unlock(sync: &Self::Sync) {
117 let mut released = false;
118 sync.monitor.enter(|state| {
119 if !released {
120 debug_assert!(state.readers == 0, "readers: {}", state.readers);
121 debug_assert!(state.writer);
122
123 released = true;
124 state.writer = false;
125 }
126
127 Directive::NotifyAll
128 });
129 }
130
131 fn downgrade(sync: &Self::Sync) {
132 let mut released = false;
133 sync.monitor.enter(|state| {
134 if !released {
135 debug_assert!(state.readers == 0, "readers: {}", state.readers);
136 debug_assert!(state.writer);
137
138 released = true;
139 state.writer = false;
140 state.readers = 1;
141 }
142
143 Directive::NotifyAll
144 });
145 }
146
147 fn try_upgrade(sync: &Self::Sync, duration: Duration) -> bool {
148 let mut deadline = Deadline::lazy_after(duration);
149 let mut acquired = false;
150 let mut self_writer_pending = false;
151 sync.monitor.enter(|state| {
152 if !acquired {
153 debug_assert!(!state.writer);
154
155 if state.readers == 1 {
156 acquired = true;
157 state.readers = 0;
158 state.writer = true;
159 } else if !state.writer_pending {
160 self_writer_pending = true;
161 state.writer_pending = true;
162 }
163 }
164
165 if acquired {
166 Directive::Return
167 } else {
168 Directive::Wait(deadline.remaining())
169 }
170 });
171
172 if self_writer_pending {
173 let mut cleared_writer_pending = false;
174 sync.monitor.enter(|state| {
175 if !cleared_writer_pending {
176 cleared_writer_pending = true;
177 state.writer_pending = false;
178 }
179
180 if acquired {
181 Directive::Return
182 } else {
183 Directive::NotifyAll
184 }
185 });
186 }
187
188 acquired
189 }
190}
191
192#[cfg(test)]
193mod tests;