1 use crate::cell::UnsafeCell;
2 use crate::sys::condvar::Condvar;
3 use crate::sys::mutex::Mutex;
8 state: UnsafeCell<State>,
17 unsafe impl Send for RWLock {}
18 unsafe impl Sync for RWLock {}
20 // This rwlock implementation is a relatively simple implementation which has a
21 // condition variable for readers/writers as well as a mutex protecting the
22 // internal state of the lock. A current downside of the implementation is that
23 // unlocking the lock will notify *all* waiters rather than just readers or just
24 // writers. This can cause lots of "thundering stampede" problems. While
25 // hopefully correct this implementation is very likely to want to be changed in
29 pub const fn new() -> RWLock {
30 RWLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) }
34 pub unsafe fn read(&self) {
36 while !(*self.state.get()).inc_readers() {
37 self.cond.wait(&self.lock);
43 pub unsafe fn try_read(&self) -> bool {
45 let ok = (*self.state.get()).inc_readers();
51 pub unsafe fn write(&self) {
53 while !(*self.state.get()).inc_writers() {
54 self.cond.wait(&self.lock);
60 pub unsafe fn try_write(&self) -> bool {
62 let ok = (*self.state.get()).inc_writers();
68 pub unsafe fn read_unlock(&self) {
70 let notify = (*self.state.get()).dec_readers();
73 // FIXME: should only wake up one of these some of the time
74 self.cond.notify_all();
79 pub unsafe fn write_unlock(&self) {
81 (*self.state.get()).dec_writers();
83 // FIXME: should only wake up one of these some of the time
84 self.cond.notify_all();
88 pub unsafe fn destroy(&self) {
95 fn inc_readers(&mut self) -> bool {
98 *self = State::Reading(1);
101 State::Reading(ref mut cnt) => {
105 State::Writing => false,
109 fn inc_writers(&mut self) -> bool {
112 *self = State::Writing;
115 State::Reading(_) | State::Writing => false,
119 fn dec_readers(&mut self) -> bool {
120 let zero = match *self {
121 State::Reading(ref mut cnt) => {
125 State::Unlocked | State::Writing => invalid(),
128 *self = State::Unlocked;
133 fn dec_writers(&mut self) {
136 State::Unlocked | State::Reading(_) => invalid(),
138 *self = State::Unlocked;
143 panic!("inconsistent rwlock");