|
1 | | -use std::cell::UnsafeCell; |
2 | | -use std::ops::{Deref, DerefMut}; |
3 | | -use std::sync::atomic::{AtomicBool, Ordering}; |
4 | | - |
5 | | -use crossbeam_utils::Backoff; |
6 | | - |
7 | 1 | /// Calls a function and aborts if it panics. |
8 | 2 | /// |
9 | 3 | /// This is useful in unsafe code where we can't recover from panics. |
@@ -58,71 +52,6 @@ pub fn random(n: u32) -> u32 { |
58 | 52 | }) |
59 | 53 | } |
60 | 54 |
|
61 | | -/// A simple spinlock. |
62 | | -pub struct Spinlock<T> { |
63 | | - flag: AtomicBool, |
64 | | - value: UnsafeCell<T>, |
65 | | -} |
66 | | - |
67 | | -unsafe impl<T: Send> Send for Spinlock<T> {} |
68 | | -unsafe impl<T: Send> Sync for Spinlock<T> {} |
69 | | - |
70 | | -impl<T> Spinlock<T> { |
71 | | - /// Returns a new spinlock initialized with `value`. |
72 | | - pub const fn new(value: T) -> Spinlock<T> { |
73 | | - Spinlock { |
74 | | - flag: AtomicBool::new(false), |
75 | | - value: UnsafeCell::new(value), |
76 | | - } |
77 | | - } |
78 | | - |
79 | | - /// Locks the spinlock. |
80 | | - pub fn lock(&self) -> SpinlockGuard<'_, T> { |
81 | | - let backoff = Backoff::new(); |
82 | | - while self.flag.swap(true, Ordering::Acquire) { |
83 | | - backoff.snooze(); |
84 | | - } |
85 | | - SpinlockGuard { parent: self } |
86 | | - } |
87 | | - |
88 | | - /// Attempts to lock the spinlock. |
89 | | - pub fn try_lock(&self) -> Option<SpinlockGuard<'_, T>> { |
90 | | - if self.flag.swap(true, Ordering::Acquire) { |
91 | | - None |
92 | | - } else { |
93 | | - Some(SpinlockGuard { parent: self }) |
94 | | - } |
95 | | - } |
96 | | -} |
97 | | - |
98 | | -/// A guard holding a spinlock locked. |
99 | | -pub struct SpinlockGuard<'a, T> { |
100 | | - parent: &'a Spinlock<T>, |
101 | | -} |
102 | | - |
103 | | -unsafe impl<T: Send> Send for SpinlockGuard<'_, T> {} |
104 | | -unsafe impl<T: Sync> Sync for SpinlockGuard<'_, T> {} |
105 | | - |
106 | | -impl<'a, T> Drop for SpinlockGuard<'a, T> { |
107 | | - fn drop(&mut self) { |
108 | | - self.parent.flag.store(false, Ordering::Release); |
109 | | - } |
110 | | -} |
111 | | - |
112 | | -impl<'a, T> Deref for SpinlockGuard<'a, T> { |
113 | | - type Target = T; |
114 | | - |
115 | | - fn deref(&self) -> &T { |
116 | | - unsafe { &*self.parent.value.get() } |
117 | | - } |
118 | | -} |
119 | | - |
120 | | -impl<'a, T> DerefMut for SpinlockGuard<'a, T> { |
121 | | - fn deref_mut(&mut self) -> &mut T { |
122 | | - unsafe { &mut *self.parent.value.get() } |
123 | | - } |
124 | | -} |
125 | | - |
126 | 55 | /// Add additional context to errors |
127 | 56 | pub(crate) trait Context { |
128 | 57 | fn context(self, message: impl Fn() -> String) -> Self; |
@@ -338,3 +267,76 @@ macro_rules! extension_trait { |
338 | 267 | extension_trait!($($tail)*); |
339 | 268 | }; |
340 | 269 | } |
| 270 | + |
| 271 | +cfg_default! { |
| 272 | + use std::cell::UnsafeCell; |
| 273 | + use std::ops::{Deref, DerefMut}; |
| 274 | + use std::sync::atomic::{AtomicBool, Ordering}; |
| 275 | + |
| 276 | + use crossbeam_utils::Backoff; |
| 277 | + |
| 278 | + /// A simple spinlock. |
| 279 | + pub struct Spinlock<T> { |
| 280 | + flag: AtomicBool, |
| 281 | + value: UnsafeCell<T>, |
| 282 | + } |
| 283 | + |
| 284 | + unsafe impl<T: Send> Send for Spinlock<T> {} |
| 285 | + unsafe impl<T: Send> Sync for Spinlock<T> {} |
| 286 | + |
| 287 | + impl<T> Spinlock<T> { |
| 288 | + /// Returns a new spinlock initialized with `value`. |
| 289 | + pub const fn new(value: T) -> Spinlock<T> { |
| 290 | + Spinlock { |
| 291 | + flag: AtomicBool::new(false), |
| 292 | + value: UnsafeCell::new(value), |
| 293 | + } |
| 294 | + } |
| 295 | + |
| 296 | + /// Locks the spinlock. |
| 297 | + pub fn lock(&self) -> SpinlockGuard<'_, T> { |
| 298 | + let backoff = Backoff::new(); |
| 299 | + while self.flag.swap(true, Ordering::Acquire) { |
| 300 | + backoff.snooze(); |
| 301 | + } |
| 302 | + SpinlockGuard { parent: self } |
| 303 | + } |
| 304 | + |
| 305 | + /// Attempts to lock the spinlock. |
| 306 | + pub fn try_lock(&self) -> Option<SpinlockGuard<'_, T>> { |
| 307 | + if self.flag.swap(true, Ordering::Acquire) { |
| 308 | + None |
| 309 | + } else { |
| 310 | + Some(SpinlockGuard { parent: self }) |
| 311 | + } |
| 312 | + } |
| 313 | + } |
| 314 | + |
| 315 | + /// A guard holding a spinlock locked. |
| 316 | + pub struct SpinlockGuard<'a, T> { |
| 317 | + parent: &'a Spinlock<T>, |
| 318 | + } |
| 319 | + |
| 320 | + unsafe impl<T: Send> Send for SpinlockGuard<'_, T> {} |
| 321 | + unsafe impl<T: Sync> Sync for SpinlockGuard<'_, T> {} |
| 322 | + |
| 323 | + impl<'a, T> Drop for SpinlockGuard<'a, T> { |
| 324 | + fn drop(&mut self) { |
| 325 | + self.parent.flag.store(false, Ordering::Release); |
| 326 | + } |
| 327 | + } |
| 328 | + |
| 329 | + impl<'a, T> Deref for SpinlockGuard<'a, T> { |
| 330 | + type Target = T; |
| 331 | + |
| 332 | + fn deref(&self) -> &T { |
| 333 | + unsafe { &*self.parent.value.get() } |
| 334 | + } |
| 335 | + } |
| 336 | + |
| 337 | + impl<'a, T> DerefMut for SpinlockGuard<'a, T> { |
| 338 | + fn deref_mut(&mut self) -> &mut T { |
| 339 | + unsafe { &mut *self.parent.value.get() } |
| 340 | + } |
| 341 | + } |
| 342 | +} |
0 commit comments