]> git.proxmox.com Git - rustc.git/blame - library/std/src/sys/hermit/rwlock.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / library / std / src / sys / hermit / rwlock.rs
CommitLineData
532ac7d7 1use crate::cell::UnsafeCell;
5e7ed085 2use crate::sys::locks::{Condvar, Mutex};
0bf4aa26 3
04454e1e 4pub struct RwLock {
0bf4aa26
XL
5 lock: Mutex,
6 cond: Condvar,
7 state: UnsafeCell<State>,
8}
9
04454e1e 10pub type MovableRwLock = RwLock;
17df50a5 11
0bf4aa26
XL
12enum State {
13 Unlocked,
14 Reading(usize),
15 Writing,
16}
17
04454e1e
FG
18unsafe impl Send for RwLock {}
19unsafe impl Sync for RwLock {}
0bf4aa26
XL
20
21// This rwlock implementation is a relatively simple implementation which has a
22// condition variable for readers/writers as well as a mutex protecting the
23// internal state of the lock. A current downside of the implementation is that
24// unlocking the lock will notify *all* waiters rather than just readers or just
25// writers. This can cause lots of "thundering stampede" problems. While
26// hopefully correct this implementation is very likely to want to be changed in
27// the future.
28
04454e1e
FG
29impl RwLock {
30 pub const fn new() -> RwLock {
31 RwLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) }
0bf4aa26
XL
32 }
33
34 #[inline]
35 pub unsafe fn read(&self) {
36 self.lock.lock();
37 while !(*self.state.get()).inc_readers() {
38 self.cond.wait(&self.lock);
39 }
40 self.lock.unlock();
41 }
42
43 #[inline]
44 pub unsafe fn try_read(&self) -> bool {
45 self.lock.lock();
46 let ok = (*self.state.get()).inc_readers();
47 self.lock.unlock();
dfeec247 48 return ok;
0bf4aa26
XL
49 }
50
51 #[inline]
52 pub unsafe fn write(&self) {
53 self.lock.lock();
54 while !(*self.state.get()).inc_writers() {
55 self.cond.wait(&self.lock);
56 }
57 self.lock.unlock();
58 }
59
60 #[inline]
61 pub unsafe fn try_write(&self) -> bool {
62 self.lock.lock();
63 let ok = (*self.state.get()).inc_writers();
64 self.lock.unlock();
dfeec247 65 return ok;
0bf4aa26
XL
66 }
67
68 #[inline]
69 pub unsafe fn read_unlock(&self) {
70 self.lock.lock();
71 let notify = (*self.state.get()).dec_readers();
72 self.lock.unlock();
73 if notify {
74 // FIXME: should only wake up one of these some of the time
75 self.cond.notify_all();
76 }
77 }
78
79 #[inline]
80 pub unsafe fn write_unlock(&self) {
81 self.lock.lock();
82 (*self.state.get()).dec_writers();
83 self.lock.unlock();
84 // FIXME: should only wake up one of these some of the time
85 self.cond.notify_all();
86 }
0bf4aa26
XL
87}
88
89impl State {
90 fn inc_readers(&mut self) -> bool {
91 match *self {
92 State::Unlocked => {
93 *self = State::Reading(1);
94 true
95 }
96 State::Reading(ref mut cnt) => {
97 *cnt += 1;
98 true
99 }
dfeec247 100 State::Writing => false,
0bf4aa26
XL
101 }
102 }
103
104 fn inc_writers(&mut self) -> bool {
105 match *self {
106 State::Unlocked => {
107 *self = State::Writing;
108 true
109 }
dfeec247 110 State::Reading(_) | State::Writing => false,
0bf4aa26
XL
111 }
112 }
113
114 fn dec_readers(&mut self) -> bool {
115 let zero = match *self {
116 State::Reading(ref mut cnt) => {
117 *cnt -= 1;
118 *cnt == 0
119 }
dfeec247 120 State::Unlocked | State::Writing => invalid(),
0bf4aa26
XL
121 };
122 if zero {
123 *self = State::Unlocked;
124 }
125 zero
126 }
127
128 fn dec_writers(&mut self) {
129 match *self {
130 State::Writing => {}
dfeec247 131 State::Unlocked | State::Reading(_) => invalid(),
0bf4aa26
XL
132 }
133 *self = State::Unlocked;
134 }
135}
136
137fn invalid() -> ! {
138 panic!("inconsistent rwlock");
139}