]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys_common/condvar/check.rs
Rollup merge of #98555 - mkroening:hermit-lock-init, r=m-ou-se
[rust.git] / library / std / src / sys_common / condvar / check.rs
1 use crate::ptr;
2 use crate::sync::atomic::{AtomicPtr, Ordering};
3 use crate::sys::locks as imp;
4 use crate::sys_common::lazy_box::{LazyBox, LazyInit};
5 use crate::sys_common::mutex::MovableMutex;
6
7 pub trait CondvarCheck {
8     type Check;
9 }
10
11 /// For boxed mutexes, a `Condvar` will check it's only ever used with the same
12 /// mutex, based on its (stable) address.
13 impl<T: LazyInit> CondvarCheck for LazyBox<T> {
14     type Check = SameMutexCheck;
15 }
16
17 pub struct SameMutexCheck {
18     addr: AtomicPtr<()>,
19 }
20
21 #[allow(dead_code)]
22 impl SameMutexCheck {
23     pub const fn new() -> Self {
24         Self { addr: AtomicPtr::new(ptr::null_mut()) }
25     }
26     pub fn verify(&self, mutex: &MovableMutex) {
27         let addr = mutex.raw() as *const imp::Mutex as *const () as *mut _;
28         // Relaxed is okay here because we never read through `self.addr`, and only use it to
29         // compare addresses.
30         match self.addr.compare_exchange(
31             ptr::null_mut(),
32             addr,
33             Ordering::Relaxed,
34             Ordering::Relaxed,
35         ) {
36             Ok(_) => {}               // Stored the address
37             Err(n) if n == addr => {} // Lost a race to store the same address
38             _ => panic!("attempted to use a condition variable with two mutexes"),
39         }
40     }
41 }
42
43 /// Unboxed mutexes may move, so `Condvar` can not require its address to stay
44 /// constant.
45 impl CondvarCheck for imp::Mutex {
46     type Check = NoCheck;
47 }
48
49 pub struct NoCheck;
50
51 #[allow(dead_code)]
52 impl NoCheck {
53     pub const fn new() -> Self {
54         Self
55     }
56     pub fn verify(&self, _: &MovableMutex) {}
57 }