]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/rwlock.rs
Remove unnecessary feature gates from const fns
[rust.git] / src / libstd / sys / sgx / rwlock.rs
1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use num::NonZeroUsize;
12
13 use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex, NotifiedTcs, try_lock_or_false};
14
15 pub struct RWLock {
16     readers: SpinMutex<WaitVariable<Option<NonZeroUsize>>>,
17     writer: SpinMutex<WaitVariable<bool>>,
18 }
19
20 //unsafe impl Send for RWLock {}
21 //unsafe impl Sync for RWLock {} // FIXME
22
23 impl RWLock {
24     pub const fn new() -> RWLock {
25         RWLock {
26             readers: SpinMutex::new(WaitVariable::new(None)),
27             writer: SpinMutex::new(WaitVariable::new(false))
28         }
29     }
30
31     #[inline]
32     pub unsafe fn read(&self) {
33         let mut rguard = self.readers.lock();
34         let wguard = self.writer.lock();
35         if *wguard.lock_var() || !wguard.queue_empty() {
36             // Another thread has or is waiting for the write lock, wait
37             drop(wguard);
38             WaitQueue::wait(rguard);
39             // Another thread has passed the lock to us
40         } else {
41             // No waiting writers, acquire the read lock
42             *rguard.lock_var_mut() =
43                 NonZeroUsize::new(rguard.lock_var().map_or(0, |n| n.get()) + 1);
44         }
45     }
46
47     #[inline]
48     pub unsafe fn try_read(&self) -> bool {
49         let mut rguard = try_lock_or_false!(self.readers);
50         let wguard = try_lock_or_false!(self.writer);
51         if *wguard.lock_var() || !wguard.queue_empty() {
52             // Another thread has or is waiting for the write lock
53             false
54         } else {
55             // No waiting writers, acquire the read lock
56             *rguard.lock_var_mut() =
57                 NonZeroUsize::new(rguard.lock_var().map_or(0, |n| n.get()) + 1);
58             true
59         }
60     }
61
62     #[inline]
63     pub unsafe fn write(&self) {
64         let rguard = self.readers.lock();
65         let mut wguard = self.writer.lock();
66         if *wguard.lock_var() || rguard.lock_var().is_some() {
67             // Another thread has the lock, wait
68             drop(rguard);
69             WaitQueue::wait(wguard);
70             // Another thread has passed the lock to us
71         } else {
72             // We are just now obtaining the lock
73             *wguard.lock_var_mut() = true;
74         }
75     }
76
77     #[inline]
78     pub unsafe fn try_write(&self) -> bool {
79         let rguard = try_lock_or_false!(self.readers);
80         let mut wguard = try_lock_or_false!(self.writer);
81         if *wguard.lock_var() || rguard.lock_var().is_some() {
82             // Another thread has the lock
83             false
84         } else {
85             // We are just now obtaining the lock
86             *wguard.lock_var_mut() = true;
87             true
88         }
89     }
90
91     #[inline]
92     pub unsafe fn read_unlock(&self) {
93         let mut rguard = self.readers.lock();
94         let wguard = self.writer.lock();
95         *rguard.lock_var_mut() = NonZeroUsize::new(rguard.lock_var().unwrap().get() - 1);
96         if rguard.lock_var().is_some() {
97             // There are other active readers
98         } else {
99             if let Ok(mut wguard) = WaitQueue::notify_one(wguard) {
100                 // A writer was waiting, pass the lock
101                 *wguard.lock_var_mut() = true;
102             } else {
103                 // No writers were waiting, the lock is released
104                 assert!(rguard.queue_empty());
105             }
106         }
107     }
108
109     #[inline]
110     pub unsafe fn write_unlock(&self) {
111         let rguard = self.readers.lock();
112         let wguard = self.writer.lock();
113         if let Err(mut wguard) = WaitQueue::notify_one(wguard) {
114             // No writers waiting, release the write lock
115             *wguard.lock_var_mut() = false;
116             if let Ok(mut rguard) = WaitQueue::notify_all(rguard) {
117                 // One or more readers were waiting, pass the lock to them
118                 if let NotifiedTcs::All { count } = rguard.notified_tcs() {
119                     *rguard.lock_var_mut() = Some(count)
120                 } else {
121                     unreachable!() // called notify_all
122                 }
123             } else {
124                 // No readers waiting, the lock is released
125             }
126         } else {
127             // There was a thread waiting for write, just pass the lock
128         }
129     }
130
131     #[inline]
132     pub unsafe fn destroy(&self) {}
133 }