1 use crate::cell::UnsafeCell;
2 use crate::sys::locks::{MovableCondvar, Mutex};
7 state: UnsafeCell<State>,
10 pub type MovableRwLock = RwLock;
18 unsafe impl Send for RwLock {}
19 unsafe impl Sync for RwLock {}
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
30 pub const fn new() -> RwLock {
33 cond: MovableCondvar::new(),
34 state: UnsafeCell::new(State::Unlocked),
39 pub unsafe fn read(&self) {
41 while !(*self.state.get()).inc_readers() {
42 self.cond.wait(&self.lock);
48 pub unsafe fn try_read(&self) -> bool {
50 let ok = (*self.state.get()).inc_readers();
56 pub unsafe fn write(&self) {
58 while !(*self.state.get()).inc_writers() {
59 self.cond.wait(&self.lock);
65 pub unsafe fn try_write(&self) -> bool {
67 let ok = (*self.state.get()).inc_writers();
73 pub unsafe fn read_unlock(&self) {
75 let notify = (*self.state.get()).dec_readers();
78 // FIXME: should only wake up one of these some of the time
79 self.cond.notify_all();
84 pub unsafe fn write_unlock(&self) {
86 (*self.state.get()).dec_writers();
88 // FIXME: should only wake up one of these some of the time
89 self.cond.notify_all();
94 fn inc_readers(&mut self) -> bool {
97 *self = State::Reading(1);
100 State::Reading(ref mut cnt) => {
104 State::Writing => false,
108 fn inc_writers(&mut self) -> bool {
111 *self = State::Writing;
114 State::Reading(_) | State::Writing => false,
118 fn dec_readers(&mut self) -> bool {
119 let zero = match *self {
120 State::Reading(ref mut cnt) => {
124 State::Unlocked | State::Writing => invalid(),
127 *self = State::Unlocked;
132 fn dec_writers(&mut self) {
135 State::Unlocked | State::Reading(_) => invalid(),
137 *self = State::Unlocked;
142 panic!("inconsistent rwlock");