rustix_futex_sync/once_lock.rs
1//! The following is derived from Rust's
2//! library/std/src/sync/once_lock.rs at revision
3//! ee04e0f35ed516e4f1cc6a12c28838eaf98a16d1.
4
5use core::cell::UnsafeCell;
6use core::fmt;
7use core::marker::PhantomData;
8use core::mem::MaybeUninit;
9use core::panic::{RefUnwindSafe, UnwindSafe};
10use crate::generic::Once;
11
12/// A synchronization primitive which can nominally be written to only once.
13///
14/// This type is a thread-safe [`OnceCell`], and can be used in statics.
15/// In many simple cases, you can use [`LazyLock<T, F>`] instead to get the benefits of this type
16/// with less effort: `LazyLock<T, F>` "looks like" `&T` because it initializes with `F` on deref!
17/// Where OnceLock shines is when LazyLock is too simple to support a given case, as LazyLock
18/// doesn't allow additional inputs to its function after you call [`LazyLock::new(|| ...)`].
19///
20/// [`OnceCell`]: core::cell::OnceCell
21/// [`LazyLock<T, F>`]: https://doc.rust-lang.org/std/sync/struct.LazyLock.html
22/// [`LazyLock::new(|| ...)`]: https://doc.rust-lang.org/std/sync/struct.LazyLock.html#method.new
23///
24/// # Examples
25///
26/// Writing to a `OnceLock` from a separate thread:
27///
28/// ```
29/// use rustix_futex_sync::OnceLock;
30///
31/// static CELL: OnceLock<usize> = OnceLock::new();
32///
33/// // `OnceLock` has not been written to yet.
34/// assert!(CELL.get().is_none());
35///
36/// // Spawn a thread and write to `OnceLock`.
37/// std::thread::spawn(|| {
38/// let value = CELL.get_or_init(|| 12345);
39/// assert_eq!(value, &12345);
40/// })
41/// .join()
42/// .unwrap();
43///
44/// // `OnceLock` now contains the value.
45/// assert_eq!(
46/// CELL.get(),
47/// Some(&12345),
48/// );
49/// ```
50///
51/// You can use `OnceLock` to implement a type that requires "append-only" logic:
52///
53/// ```
54/// use std::sync::atomic::{AtomicU32, Ordering};
55/// use rustix_futex_sync::OnceLock;
56/// use std::thread;
57///
58/// struct OnceList<T> {
59/// data: OnceLock<T>,
60/// next: OnceLock<Box<OnceList<T>>>,
61/// }
62/// impl<T> OnceList<T> {
63/// const fn new() -> OnceList<T> {
64/// OnceList { data: OnceLock::new(), next: OnceLock::new() }
65/// }
66/// fn push(&self, value: T) {
67/// // FIXME: this impl is concise, but is also slow for long lists or many threads.
68/// // as an exercise, consider how you might improve on it while preserving the behavior
69/// if let Err(value) = self.data.set(value) {
70/// let next = self.next.get_or_init(|| Box::new(OnceList::new()));
71/// next.push(value)
72/// };
73/// }
74/// fn contains(&self, example: &T) -> bool
75/// where
76/// T: PartialEq,
77/// {
78/// self.data.get().map(|item| item == example).filter(|v| *v).unwrap_or_else(|| {
79/// self.next.get().map(|next| next.contains(example)).unwrap_or(false)
80/// })
81/// }
82/// }
83///
84/// // Let's exercise this new Sync append-only list by doing a little counting
85/// static LIST: OnceList<u32> = OnceList::new();
86/// static COUNTER: AtomicU32 = AtomicU32::new(0);
87///
88/// let vec = (0..thread::available_parallelism().unwrap().get()).map(|_| thread::spawn(|| {
89/// while let i @ 0..=1000 = COUNTER.fetch_add(1, Ordering::Relaxed) {
90/// LIST.push(i);
91/// }
92/// })).collect::<Vec<thread::JoinHandle<_>>>();
93/// vec.into_iter().for_each(|handle| handle.join().unwrap());
94///
95/// for i in 0..=1000 {
96/// assert!(LIST.contains(&i));
97/// }
98///
99/// ```
100//#[stable(feature = "once_cell", since = "1.70.0")]
101pub struct OnceLock<T, const SHM: bool> {
102 once: Once<SHM>,
103 // Whether or not the value is initialized is tracked by `once.is_completed()`.
104 value: UnsafeCell<MaybeUninit<T>>,
105 /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
106 ///
107 /// ```compile_fail,E0597
108 /// use rustix_futex_sync::OnceLock;
109 ///
110 /// struct A<'a>(&'a str);
111 ///
112 /// impl<'a> Drop for A<'a> {
113 /// fn drop(&mut self) {}
114 /// }
115 ///
116 /// let cell = OnceLock::new();
117 /// {
118 /// let s = String::new();
119 /// let _ = cell.set(A(&s));
120 /// }
121 /// ```
122 _marker: PhantomData<T>,
123}
124
125impl<T, const SHM: bool> OnceLock<T, SHM> {
126 /// Creates a new empty cell.
127 #[inline]
128 #[must_use]
129 //#[stable(feature = "once_cell", since = "1.70.0")]
130 //#[rustc_const_stable(feature = "once_cell", since = "1.70.0")]
131 pub const fn new() -> Self {
132 OnceLock {
133 once: Once::new(),
134 value: UnsafeCell::new(MaybeUninit::uninit()),
135 _marker: PhantomData,
136 }
137 }
138
139 /// Gets the reference to the underlying value.
140 ///
141 /// Returns `None` if the cell is empty, or being initialized. This
142 /// method never blocks.
143 #[inline]
144 //#[stable(feature = "once_cell", since = "1.70.0")]
145 pub fn get(&self) -> Option<&T> {
146 if self.is_initialized() {
147 // Safe b/c checked is_initialized
148 Some(unsafe { self.get_unchecked() })
149 } else {
150 None
151 }
152 }
153
154 /// Gets the mutable reference to the underlying value.
155 ///
156 /// Returns `None` if the cell is empty. This method never blocks.
157 #[inline]
158 //#[stable(feature = "once_cell", since = "1.70.0")]
159 pub fn get_mut(&mut self) -> Option<&mut T> {
160 if self.is_initialized() {
161 // Safe b/c checked is_initialized and we have a unique access
162 Some(unsafe { self.get_unchecked_mut() })
163 } else {
164 None
165 }
166 }
167
168 /// Sets the contents of this cell to `value`.
169 ///
170 /// May block if another thread is currently attempting to initialize the cell. The cell is
171 /// guaranteed to contain a value when set returns, though not necessarily the one provided.
172 ///
173 /// Returns `Ok(())` if the cell's value was set by this call.
174 ///
175 /// # Examples
176 ///
177 /// ```
178 /// use rustix_futex_sync::OnceLock;
179 ///
180 /// static CELL: OnceLock<i32> = OnceLock::new();
181 ///
182 /// fn main() {
183 /// assert!(CELL.get().is_none());
184 ///
185 /// std::thread::spawn(|| {
186 /// assert_eq!(CELL.set(92), Ok(()));
187 /// }).join().unwrap();
188 ///
189 /// assert_eq!(CELL.set(62), Err(62));
190 /// assert_eq!(CELL.get(), Some(&92));
191 /// }
192 /// ```
193 #[inline]
194 //#[stable(feature = "once_cell", since = "1.70.0")]
195 pub fn set(&self, value: T) -> Result<(), T> {
196 match self.try_insert(value) {
197 Ok(_) => Ok(()),
198 Err((_, value)) => Err(value),
199 }
200 }
201
202 /// Sets the contents of this cell to `value` if the cell was empty, then
203 /// returns a reference to it.
204 ///
205 /// May block if another thread is currently attempting to initialize the cell. The cell is
206 /// guaranteed to contain a value when set returns, though not necessarily the one provided.
207 ///
208 /// Returns `Ok(&value)` if the cell was empty and `Err(¤t_value, value)` if it was full.
209 ///
210 /// # Examples
211 ///
212 /// ```
213 /// //#![feature(once_cell_try_insert)]
214 ///
215 /// use rustix_futex_sync::OnceLock;
216 ///
217 /// static CELL: OnceLock<i32> = OnceLock::new();
218 ///
219 /// fn main() {
220 /// assert!(CELL.get().is_none());
221 ///
222 /// std::thread::spawn(|| {
223 /// assert_eq!(CELL.try_insert(92), Ok(&92));
224 /// }).join().unwrap();
225 ///
226 /// assert_eq!(CELL.try_insert(62), Err((&92, 62)));
227 /// assert_eq!(CELL.get(), Some(&92));
228 /// }
229 /// ```
230 #[inline]
231 //#[unstable(feature = "once_cell_try_insert", issue = "116693")]
232 pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
233 let mut value = Some(value);
234 let res = self.get_or_init(|| value.take().unwrap());
235 match value {
236 None => Ok(res),
237 Some(value) => Err((res, value)),
238 }
239 }
240
241 /// Gets the contents of the cell, initializing it with `f` if the cell
242 /// was empty.
243 ///
244 /// Many threads may call `get_or_init` concurrently with different
245 /// initializing functions, but it is guaranteed that only one function
246 /// will be executed.
247 ///
248 /// # Panics
249 ///
250 /// If `f` panics, the panic is propagated to the caller, and the cell
251 /// remains uninitialized.
252 ///
253 /// It is an error to reentrantly initialize the cell from `f`. The
254 /// exact outcome is unspecified. Current implementation deadlocks, but
255 /// this may be changed to a panic in the future.
256 ///
257 /// # Examples
258 ///
259 /// ```
260 /// use rustix_futex_sync::OnceLock;
261 ///
262 /// let cell = OnceLock::new();
263 /// let value = cell.get_or_init(|| 92);
264 /// assert_eq!(value, &92);
265 /// let value = cell.get_or_init(|| unreachable!());
266 /// assert_eq!(value, &92);
267 /// ```
268 #[inline]
269 //#[stable(feature = "once_cell", since = "1.70.0")]
270 pub fn get_or_init<F>(&self, f: F) -> &T
271 where
272 F: FnOnce() -> T,
273 {
274 //match self.get_or_try_init(|| Ok::<T, !>(f())) {
275 match self.get_or_try_init(|| Ok::<T, ()>(f())) {
276 Ok(val) => val,
277 Err(()) => panic!(),
278 }
279 }
280
281 /// Gets the mutable reference of the contents of the cell, initializing
282 /// it with `f` if the cell was empty.
283 ///
284 /// Many threads may call `get_mut_or_init` concurrently with different
285 /// initializing functions, but it is guaranteed that only one function
286 /// will be executed.
287 ///
288 /// # Panics
289 ///
290 /// If `f` panics, the panic is propagated to the caller, and the cell
291 /// remains uninitialized.
292 ///
293 /// # Examples
294 ///
295 /// ```
296 /// //#![feature(once_cell_get_mut)]
297 ///
298 /// use rustix_futex_sync::OnceLock;
299 ///
300 /// let mut cell = OnceLock::new();
301 /// let value = cell.get_mut_or_init(|| 92);
302 /// assert_eq!(*value, 92);
303 ///
304 /// *value += 2;
305 /// assert_eq!(*value, 94);
306 ///
307 /// let value = cell.get_mut_or_init(|| unreachable!());
308 /// assert_eq!(*value, 94);
309 /// ```
310 #[inline]
311 //#[unstable(feature = "once_cell_get_mut", issue = "121641")]
312 pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T
313 where
314 F: FnOnce() -> T,
315 {
316 //match self.get_mut_or_try_init(|| Ok::<T, !>(f())) {
317 match self.get_mut_or_try_init(|| Ok::<T, ()>(f())) {
318 Ok(val) => val,
319 Err(()) => panic!(),
320 }
321 }
322
323 /// Gets the contents of the cell, initializing it with `f` if
324 /// the cell was empty. If the cell was empty and `f` failed, an
325 /// error is returned.
326 ///
327 /// # Panics
328 ///
329 /// If `f` panics, the panic is propagated to the caller, and
330 /// the cell remains uninitialized.
331 ///
332 /// It is an error to reentrantly initialize the cell from `f`.
333 /// The exact outcome is unspecified. Current implementation
334 /// deadlocks, but this may be changed to a panic in the future.
335 ///
336 /// # Examples
337 ///
338 /// ```
339 /// //#![feature(once_cell_try)]
340 ///
341 /// use rustix_futex_sync::OnceLock;
342 ///
343 /// let cell = OnceLock::new();
344 /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
345 /// assert!(cell.get().is_none());
346 /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
347 /// Ok(92)
348 /// });
349 /// assert_eq!(value, Ok(&92));
350 /// assert_eq!(cell.get(), Some(&92))
351 /// ```
352 #[inline]
353 //#[unstable(feature = "once_cell_try", issue = "109737")]
354 pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
355 where
356 F: FnOnce() -> Result<T, E>,
357 {
358 // Fast path check
359 // NOTE: We need to perform an acquire on the state in this method
360 // in order to correctly synchronize `LazyLock::force`. This is
361 // currently done by calling `self.get()`, which in turn calls
362 // `self.is_initialized()`, which in turn performs the acquire.
363 if let Some(value) = self.get() {
364 return Ok(value);
365 }
366 self.initialize(f)?;
367
368 debug_assert!(self.is_initialized());
369
370 // SAFETY: The inner value has been initialized
371 Ok(unsafe { self.get_unchecked() })
372 }
373
374 /// Gets the mutable reference of the contents of the cell, initializing
375 /// it with `f` if the cell was empty. If the cell was empty and `f` failed,
376 /// an error is returned.
377 ///
378 /// # Panics
379 ///
380 /// If `f` panics, the panic is propagated to the caller, and
381 /// the cell remains uninitialized.
382 ///
383 /// # Examples
384 ///
385 /// ```
386 /// //#![feature(once_cell_get_mut)]
387 ///
388 /// use rustix_futex_sync::OnceLock;
389 ///
390 /// let mut cell: OnceLock<u32> = OnceLock::new();
391 ///
392 /// // Failed initializers do not change the value
393 /// assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err());
394 /// assert!(cell.get().is_none());
395 ///
396 /// let value = cell.get_mut_or_try_init(|| "1234".parse());
397 /// assert_eq!(value, Ok(&mut 1234));
398 /// *value.unwrap() += 2;
399 /// assert_eq!(cell.get(), Some(&1236))
400 /// ```
401 #[inline]
402 //#[unstable(feature = "once_cell_get_mut", issue = "121641")]
403 pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
404 where
405 F: FnOnce() -> Result<T, E>,
406 {
407 if self.get().is_none() {
408 self.initialize(f)?;
409 }
410 debug_assert!(self.is_initialized());
411 // SAFETY: The inner value has been initialized
412 Ok(unsafe { self.get_unchecked_mut() })
413 }
414
415 /// Consumes the `OnceLock`, returning the wrapped value. Returns
416 /// `None` if the cell was empty.
417 ///
418 /// # Examples
419 ///
420 /// ```
421 /// use rustix_futex_sync::OnceLock;
422 ///
423 /// let cell: OnceLock<String> = OnceLock::new();
424 /// assert_eq!(cell.into_inner(), None);
425 ///
426 /// let cell = OnceLock::new();
427 /// cell.set("hello".to_string()).unwrap();
428 /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
429 /// ```
430 #[inline]
431 //#[stable(feature = "once_cell", since = "1.70.0")]
432 pub fn into_inner(mut self) -> Option<T> {
433 self.take()
434 }
435
436 /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
437 ///
438 /// Has no effect and returns `None` if the `OnceLock` hasn't been initialized.
439 ///
440 /// Safety is guaranteed by requiring a mutable reference.
441 ///
442 /// # Examples
443 ///
444 /// ```
445 /// use rustix_futex_sync::OnceLock;
446 ///
447 /// let mut cell: OnceLock<String> = OnceLock::new();
448 /// assert_eq!(cell.take(), None);
449 ///
450 /// let mut cell = OnceLock::new();
451 /// cell.set("hello".to_string()).unwrap();
452 /// assert_eq!(cell.take(), Some("hello".to_string()));
453 /// assert_eq!(cell.get(), None);
454 /// ```
455 #[inline]
456 //#[stable(feature = "once_cell", since = "1.70.0")]
457 pub fn take(&mut self) -> Option<T> {
458 if self.is_initialized() {
459 self.once = Once::new();
460 // SAFETY: `self.value` is initialized and contains a valid `T`.
461 // `self.once` is reset, so `is_initialized()` will be false again
462 // which prevents the value from being read twice.
463 unsafe { Some((&mut *self.value.get()).assume_init_read()) }
464 } else {
465 None
466 }
467 }
468
469 #[inline]
470 fn is_initialized(&self) -> bool {
471 self.once.is_completed()
472 }
473
474 #[cold]
475 fn initialize<F, E>(&self, f: F) -> Result<(), E>
476 where
477 F: FnOnce() -> Result<T, E>,
478 {
479 let mut res: Result<(), E> = Ok(());
480 let slot = &self.value;
481
482 // Ignore poisoning from other threads
483 // If another thread panics, then we'll be able to run our closure
484 self.once.call_once_force(|p| {
485 match f() {
486 Ok(value) => {
487 unsafe { (&mut *slot.get()).write(value) };
488 }
489 Err(e) => {
490 res = Err(e);
491
492 // The call failed, so reset the once state back to
493 // incomplete.
494 p.set_incomplete();
495
496 /*
497 // Treat the underlying `Once` as poisoned since we
498 // failed to initialize our value. Calls
499 p.poison();
500 */
501 }
502 }
503 });
504 res
505 }
506
507 /// # Safety
508 ///
509 /// The value must be initialized
510 #[inline]
511 unsafe fn get_unchecked(&self) -> &T {
512 debug_assert!(self.is_initialized());
513 (&*self.value.get()).assume_init_ref()
514 }
515
516 /// # Safety
517 ///
518 /// The value must be initialized
519 #[inline]
520 unsafe fn get_unchecked_mut(&mut self) -> &mut T {
521 debug_assert!(self.is_initialized());
522 (&mut *self.value.get()).assume_init_mut()
523 }
524}
525
526// Why do we need `T: Send`?
527// Thread A creates a `OnceLock` and shares it with
528// scoped thread B, which fills the cell, which is
529// then destroyed by A. That is, destructor observes
530// a sent value.
531//#[stable(feature = "once_cell", since = "1.70.0")]
532unsafe impl<T: Sync + Send, const SHM: bool> Sync for OnceLock<T, SHM> {}
533//#[stable(feature = "once_cell", since = "1.70.0")]
534unsafe impl<T: Send, const SHM: bool> Send for OnceLock<T, SHM> {}
535
536//#[stable(feature = "once_cell", since = "1.70.0")]
537impl<T: RefUnwindSafe + UnwindSafe, const SHM: bool> RefUnwindSafe for OnceLock<T, SHM> {}
538//#[stable(feature = "once_cell", since = "1.70.0")]
539impl<T: UnwindSafe, const SHM: bool> UnwindSafe for OnceLock<T, SHM> {}
540
541//#[stable(feature = "once_cell", since = "1.70.0")]
542impl<T, const SHM: bool> Default for OnceLock<T, SHM> {
543 /// Creates a new empty cell.
544 ///
545 /// # Example
546 ///
547 /// ```
548 /// use rustix_futex_sync::OnceLock;
549 ///
550 /// fn main() {
551 /// assert_eq!(OnceLock::<()>::new(), OnceLock::default());
552 /// }
553 /// ```
554 #[inline]
555 fn default() -> Self {
556 OnceLock::new()
557 }
558}
559
560//#[stable(feature = "once_cell", since = "1.70.0")]
561impl<T: fmt::Debug, const SHM: bool> fmt::Debug for OnceLock<T, SHM> {
562 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563 let mut d = f.debug_tuple("OnceLock");
564 match self.get() {
565 Some(v) => d.field(v),
566 None => d.field(&format_args!("<uninit>")),
567 };
568 d.finish()
569 }
570}
571
572//#[stable(feature = "once_cell", since = "1.70.0")]
573impl<T: Clone, const SHM: bool> Clone for OnceLock<T, SHM> {
574 #[inline]
575 fn clone(&self) -> Self {
576 let cell = Self::new();
577 if let Some(value) = self.get() {
578 match cell.set(value.clone()) {
579 Ok(()) => (),
580 Err(_) => unreachable!(),
581 }
582 }
583 cell
584 }
585}
586
587//#[stable(feature = "once_cell", since = "1.70.0")]
588impl<T, const SHM: bool> From<T> for OnceLock<T, SHM> {
589 /// Create a new cell with its contents set to `value`.
590 ///
591 /// # Example
592 ///
593 /// ```
594 /// use rustix_futex_sync::OnceLock;
595 ///
596 /// # fn main() -> Result<(), i32> {
597 /// let a = OnceLock::from(3);
598 /// let b = OnceLock::new();
599 /// b.set(3)?;
600 /// assert_eq!(a, b);
601 /// Ok(())
602 /// # }
603 /// ```
604 #[inline]
605 fn from(value: T) -> Self {
606 let cell = Self::new();
607 match cell.set(value) {
608 Ok(()) => cell,
609 Err(_) => unreachable!(),
610 }
611 }
612}
613
614//#[stable(feature = "once_cell", since = "1.70.0")]
615impl<T: PartialEq, const SHM: bool> PartialEq for OnceLock<T, SHM> {
616 #[inline]
617 fn eq(&self, other: &Self) -> bool {
618 self.get() == other.get()
619 }
620}
621
622//#[stable(feature = "once_cell", since = "1.70.0")]
623impl<T: Eq, const SHM: bool> Eq for OnceLock<T, SHM> {}
624
625//#[stable(feature = "once_cell", since = "1.70.0")]
626/*unsafe*/ impl</*#[may_dangle]*/ T, const SHM: bool> Drop for OnceLock<T, SHM> {
627 #[inline]
628 fn drop(&mut self) {
629 if self.is_initialized() {
630 // SAFETY: The cell is initialized and being dropped, so it can't
631 // be accessed again. We also don't touch the `T` other than
632 // dropping it, which validates our usage of #[may_dangle].
633 unsafe { (&mut *self.value.get()).assume_init_drop() };
634 }
635 }
636}
637
638/*
639#[cfg(test)]
640mod tests;
641*/