|
13 | 13 | #![warn(missing_docs)]
|
14 | 14 | #![deny(missing_debug_implementations)]
|
15 | 15 |
|
| 16 | +use core::cell::UnsafeCell; |
| 17 | +use core::sync::atomic::{AtomicBool, Ordering}; |
| 18 | + |
16 | 19 | pub use crate::addr::{align_down, align_up, PhysAddr, VirtAddr};
|
17 | 20 |
|
18 | 21 | /// Makes a function const only when `feature = "const_fn"` is enabled.
|
@@ -112,3 +115,60 @@ impl PrivilegeLevel {
|
112 | 115 | }
|
113 | 116 | }
|
114 | 117 | }
|
| 118 | + |
| 119 | +/// A wrapper that can be used to safely create one mutable reference `&'static mut T` from a static variable. |
| 120 | +/// |
| 121 | +/// `Singleton` is safe because it ensures that it only ever gives out one reference. |
| 122 | +/// |
| 123 | +/// ``Singleton<T>` is a safe alternative to `static mut` or a static `UnsafeCell<T>`. |
| 124 | +#[derive(Debug)] |
| 125 | +pub struct Singleton<T> { |
| 126 | + used: AtomicBool, |
| 127 | + value: UnsafeCell<T>, |
| 128 | +} |
| 129 | + |
| 130 | +impl<T> Singleton<T> { |
| 131 | + /// Construct a new singleton. |
| 132 | + pub const fn new(value: T) -> Self { |
| 133 | + Self { |
| 134 | + used: AtomicBool::new(false), |
| 135 | + value: UnsafeCell::new(value), |
| 136 | + } |
| 137 | + } |
| 138 | + |
| 139 | + /// Try to acquire a mutable reference to the wrapped value. |
| 140 | + /// This will only succeed the first time the function is |
| 141 | + /// called and fail on all following calls. |
| 142 | + /// |
| 143 | + /// ``` |
| 144 | + /// use x86_64::Singleton; |
| 145 | + /// |
| 146 | + /// static FOO: Singleton<i32> = Singleton::new(0); |
| 147 | + /// |
| 148 | + /// // Call `try_get_mut` for the first time and get a reference. |
| 149 | + /// let first: &'static mut i32 = FOO.try_get_mut().unwrap(); |
| 150 | + /// assert_eq!(first, &0); |
| 151 | + /// |
| 152 | + /// // Calling `try_get_mut` again will return `None`. |
| 153 | + /// assert_eq!(FOO.try_get_mut(), None); |
| 154 | + /// ``` |
| 155 | + pub fn try_get_mut(&self) -> Option<&mut T> { |
| 156 | + match self |
| 157 | + .used |
| 158 | + .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) |
| 159 | + { |
| 160 | + Ok(_) => Some(unsafe { |
| 161 | + // SAFETY: no reference has been given out yet and we won't give out another. |
| 162 | + &mut *self.value.get() |
| 163 | + }), |
| 164 | + Err(_) => None, |
| 165 | + } |
| 166 | + } |
| 167 | +} |
| 168 | + |
| 169 | +// SAFETY: Sharing a `Singleton<T>` between threads is safe regardless of whether `T` is `Sync` |
| 170 | +// because we only expose the inner value once to one thread. |
| 171 | +unsafe impl<T> Sync for Singleton<T> {} |
| 172 | + |
| 173 | +// SAFETY: It's safe to send a `Singleton<T>` to another thread if it's safe to send `T`. |
| 174 | +unsafe impl<T: Send> Send for Singleton<T> {} |
0 commit comments