]> git.proxmox.com Git - rustc.git/blob - library/std/src/sys_common/condvar/check.rs
New upstream version 1.63.0+dfsg1
[rustc.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 }