Skip to main content

anode/xlock/
write_biased.rs

1use 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;