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(&current_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*/