tokio/loom/std/
parking_lot.rs

1//! A minimal adaption of the `parking_lot` synchronization primitives to the
2//! equivalent `std::sync` types.
3//!
4//! This can be extended to additional types/methods as required.
5
6use std::fmt;
7use std::marker::PhantomData;
8use std::ops::{Deref, DerefMut};
9use std::sync::{LockResult, TryLockError};
10use std::time::Duration;
11
12// All types in this file are marked with PhantomData to ensure that
13// parking_lot's send_guard feature does not leak through and affect when Tokio
14// types are Send.
15//
16// See <https://github.com/tokio-rs/tokio/pull/4359> for more info.
17
18// Types that do not need wrapping
19pub(crate) use parking_lot::WaitTimeoutResult;
20
21#[derive(Debug)]
22pub(crate) struct Mutex<T: ?Sized>(PhantomData<std::sync::Mutex<T>>, parking_lot::Mutex<T>);
23
24#[derive(Debug)]
25pub(crate) struct RwLock<T>(PhantomData<std::sync::RwLock<T>>, parking_lot::RwLock<T>);
26
27#[derive(Debug)]
28pub(crate) struct Condvar(PhantomData<std::sync::Condvar>, parking_lot::Condvar);
29
30#[derive(Debug)]
31pub(crate) struct MutexGuard<'a, T: ?Sized>(
32    PhantomData<std::sync::MutexGuard<'a, T>>,
33    parking_lot::MutexGuard<'a, T>,
34);
35
36#[derive(Debug)]
37pub(crate) struct RwLockReadGuard<'a, T: ?Sized>(
38    PhantomData<std::sync::RwLockReadGuard<'a, T>>,
39    parking_lot::RwLockReadGuard<'a, T>,
40);
41
42#[derive(Debug)]
43pub(crate) struct RwLockWriteGuard<'a, T: ?Sized>(
44    PhantomData<std::sync::RwLockWriteGuard<'a, T>>,
45    parking_lot::RwLockWriteGuard<'a, T>,
46);
47
48impl<T> Mutex<T> {
49    #[inline]
50    pub(crate) fn new(t: T) -> Mutex<T> {
51        Mutex(PhantomData, parking_lot::Mutex::new(t))
52    }
53
54    #[inline]
55    #[cfg(not(all(loom, test)))]
56    pub(crate) const fn const_new(t: T) -> Mutex<T> {
57        Mutex(PhantomData, parking_lot::const_mutex(t))
58    }
59
60    #[inline]
61    pub(crate) fn lock(&self) -> MutexGuard<'_, T> {
62        MutexGuard(PhantomData, self.1.lock())
63    }
64
65    #[inline]
66    pub(crate) fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
67        self.1
68            .try_lock()
69            .map(|guard| MutexGuard(PhantomData, guard))
70    }
71
72    #[inline]
73    pub(crate) fn get_mut(&mut self) -> &mut T {
74        self.1.get_mut()
75    }
76
77    // Note: Additional methods `is_poisoned` and `into_inner`, can be
78    // provided here as needed.
79}
80
81impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
82    type Target = T;
83    fn deref(&self) -> &T {
84        self.1.deref()
85    }
86}
87
88impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
89    fn deref_mut(&mut self) -> &mut T {
90        self.1.deref_mut()
91    }
92}
93
94impl<T> RwLock<T> {
95    pub(crate) fn new(t: T) -> RwLock<T> {
96        RwLock(PhantomData, parking_lot::RwLock::new(t))
97    }
98
99    pub(crate) fn read(&self) -> RwLockReadGuard<'_, T> {
100        RwLockReadGuard(PhantomData, self.1.read())
101    }
102
103    pub(crate) fn try_read(&self) -> Option<RwLockReadGuard<'_, T>> {
104        self.1
105            .try_read()
106            .map(|guard| RwLockReadGuard(PhantomData, guard))
107    }
108
109    pub(crate) fn write(&self) -> RwLockWriteGuard<'_, T> {
110        RwLockWriteGuard(PhantomData, self.1.write())
111    }
112
113    pub(crate) fn try_write(&self) -> Option<RwLockWriteGuard<'_, T>> {
114        self.1
115            .try_write()
116            .map(|guard| RwLockWriteGuard(PhantomData, guard))
117    }
118}
119
120impl<'a, T: ?Sized> Deref for RwLockReadGuard<'a, T> {
121    type Target = T;
122    fn deref(&self) -> &T {
123        self.1.deref()
124    }
125}
126
127impl<'a, T: ?Sized> Deref for RwLockWriteGuard<'a, T> {
128    type Target = T;
129    fn deref(&self) -> &T {
130        self.1.deref()
131    }
132}
133
134impl<'a, T: ?Sized> DerefMut for RwLockWriteGuard<'a, T> {
135    fn deref_mut(&mut self) -> &mut T {
136        self.1.deref_mut()
137    }
138}
139
140impl Condvar {
141    #[inline]
142    pub(crate) fn new() -> Condvar {
143        Condvar(PhantomData, parking_lot::Condvar::new())
144    }
145
146    #[inline]
147    pub(crate) fn notify_one(&self) {
148        self.1.notify_one();
149    }
150
151    #[inline]
152    pub(crate) fn notify_all(&self) {
153        self.1.notify_all();
154    }
155
156    #[inline]
157    pub(crate) fn wait<'a, T>(
158        &self,
159        mut guard: MutexGuard<'a, T>,
160    ) -> LockResult<MutexGuard<'a, T>> {
161        self.1.wait(&mut guard.1);
162        Ok(guard)
163    }
164
165    #[inline]
166    pub(crate) fn wait_timeout<'a, T>(
167        &self,
168        mut guard: MutexGuard<'a, T>,
169        timeout: Duration,
170    ) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
171        let wtr = self.1.wait_for(&mut guard.1, timeout);
172        Ok((guard, wtr))
173    }
174
175    // Note: Additional methods `wait_timeout_ms`, `wait_timeout_until`,
176    // `wait_until` can be provided here as needed.
177}
178
179impl<'a, T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'a, T> {
180    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181        fmt::Display::fmt(&self.1, f)
182    }
183}
184
185impl<'a, T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'a, T> {
186    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187        fmt::Display::fmt(&self.1, f)
188    }
189}
190
191impl<'a, T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'a, T> {
192    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193        fmt::Display::fmt(&self.1, f)
194    }
195}