twice_cell/
lib.rs

1#![warn(clippy::pedantic)]
2#![warn(clippy::undocumented_unsafe_blocks)]
3
4use std::cell::UnsafeCell;
5use std::fmt::{self, Debug, Formatter};
6use std::marker::PhantomData;
7use std::mem::{self, ManuallyDrop};
8use std::panic::{resume_unwind, AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
9use std::sync::Once;
10
11pub use either::Either;
12use void::{ResultVoidExt, Void};
13
14/// A cell which can nominally be modified only once.
15///
16/// The main difference between this struct and a [`OnceCell`] is that rather than operating on an [`Option`],
17/// this type operates on an [`Either`] -- meaning methods such as [`TwiceCell::get_or_init`] take a parameter
18/// that can be used to compute the `B` value of a `TwiceCell` based on its `A` value.
19///
20/// For a thread-safe version of this struct, see [`TwiceLock`].
21///
22/// [`OnceCell`]: std::cell::OnceCell
23///
24/// # Examples
25///
26/// ```
27/// use twice_cell::TwiceCell;
28///
29/// let cell = TwiceCell::new("an initial `A` value for the cell");
30/// assert!(cell.get().is_none());
31///
32/// let value = cell.get_or_init(|s| s.len()); // <- set a `B` value based on the inital `A` value!
33/// assert_eq!(*value, 33);
34/// assert!(cell.get().is_some());
35/// ```
36pub struct TwiceCell<A, B> {
37    // Invariant: modified at most once, and in the direction from `A` to `B`.
38    inner: UnsafeCell<Either<A, B>>,
39}
40
41impl<A, B> TwiceCell<A, B> {
42    /// Creates a new cell with the given `value`.
43    #[inline]
44    #[must_use]
45    pub const fn new(value: A) -> TwiceCell<A, B> {
46        TwiceCell {
47            inner: UnsafeCell::new(Either::Left(value)),
48        }
49    }
50
51    /// Gets the reference to the underlying value.
52    ///
53    /// Returns `None` if the cell hasn't been set.
54    #[inline]
55    pub fn get(&self) -> Option<&B> {
56        // Safety: we're handing out a reference to B
57        match unsafe { self.get_either() } {
58            Either::Left(_a) => None,
59            // Safety: this pointer is safe to dereference because we got it from `self.get_either`.
60            Either::Right(b) => Some(unsafe { &*b }),
61        }
62    }
63
64    /// Gets the mutable reference to the underlying value.
65    ///
66    /// Returns `None` if the cell hasn't been set.
67    #[inline]
68    pub fn get_mut(&mut self) -> Option<&mut B> {
69        self.get_either_mut().right()
70    }
71
72    /// Gets the reference to either underlying value
73    ///
74    /// Safety: We can't hand out references to `A` to the user because you could get a reference
75    /// to `A` and then mutate `self` through an immutable reference via e.g. `set`.
76    ///
77    /// However! Since `TwiceCell` is thread-local we _can_ use references to `A` for things like equality checking,
78    /// since we know that the single thread can't change the value and check equality at the same time.
79    ///
80    /// I think.
81    #[inline]
82    unsafe fn get_either(&self) -> Either<*const A, *const B> {
83        // Safety: the caller promises to only ever hand
84        // out references to B
85        match unsafe { &*self.inner.get() } {
86            Either::Left(a) => Either::Left(a),
87            Either::Right(b) => Either::Right(b),
88        }
89    }
90
91    /// Gets the mutable reference to either underlying value.
92    #[inline]
93    pub fn get_either_mut(&mut self) -> Either<&mut A, &mut B> {
94        self.inner.get_mut().as_mut()
95    }
96
97    /// Sets the contents of the cell to `value`.
98    ///
99    /// # Errors
100    ///
101    /// This method returns `Ok(())` if the cell was empty and `Err(value)` if
102    /// it was full.
103    ///
104    /// # Examples
105    ///
106    /// ```
107    /// use twice_cell::TwiceCell;
108    ///
109    /// let cell = TwiceCell::new(0);
110    /// assert!(cell.get().is_none());
111    ///
112    /// assert_eq!(cell.set(92), Ok(()));
113    /// assert_eq!(cell.set(62), Err(62));
114    ///
115    /// assert!(cell.get().is_some());
116    /// ```
117    #[inline]
118    pub fn set(&self, value: B) -> Result<(), B> {
119        match self.try_insert(value) {
120            Ok(_) => Ok(()),
121            Err((_, value)) => Err(value),
122        }
123    }
124
125    /// Sets the contents of the cell to `value` if the cell was empty, then
126    /// returns a reference to it.
127    ///
128    /// # Errors
129    ///
130    /// This method returns `Ok(&value)` if the cell was empty and
131    /// `Err(&current_value, value)` if it was full.
132    ///
133    /// # Examples
134    ///
135    /// ```
136    /// use twice_cell::TwiceCell;
137    ///
138    /// let cell = TwiceCell::new(0);
139    /// assert!(cell.get().is_none());
140    ///
141    /// assert_eq!(cell.try_insert(92), Ok(&92));
142    /// assert_eq!(cell.try_insert(62), Err((&92, 62)));
143    ///
144    /// assert!(cell.get().is_some());
145    /// ```
146    #[inline]
147    pub fn try_insert(&self, value: B) -> Result<&B, (&B, B)> {
148        if let Some(old) = self.get() {
149            return Err((old, value));
150        }
151
152        // SAFETY: This is the only place where we set the slot, no races
153        // due to reentrancy/concurrency are possible because we're thread-local,
154        // and we've checked that slot is currently `A`,
155        // so this write maintains the `inner`'s invariant.
156        let slot = unsafe { &mut *self.inner.get() };
157        *slot = Either::Right(value);
158
159        // Safety: we just set this value.
160        let b = unsafe { slot.as_ref().right().unwrap_unchecked() };
161        Ok(b)
162    }
163
164    /// Gets the contents of the cell, initializing it with `f`
165    /// if the cell was unset.
166    ///
167    /// # Panics
168    ///
169    /// If `f` panics, the panic is propagated to the caller, and the cell
170    /// remains uninitialized.
171    ///
172    /// It is an error to reentrantly initialize the cell from `f`. Doing
173    /// so results in a panic.
174    ///
175    /// # Examples
176    ///
177    /// ```
178    /// use twice_cell::TwiceCell;
179    ///
180    /// let cell = TwiceCell::new("hello");
181    /// let value = cell.get_or_init(|s| s.len());
182    /// assert_eq!(value, &5);
183    /// let value = cell.get_or_init(|_| unreachable!());
184    /// assert_eq!(value, &5);
185    /// ```
186    #[inline]
187    pub fn get_or_init<F>(&self, f: F) -> &B
188    where
189        F: FnOnce(&A) -> B,
190    {
191        self.get_or_try_init(|a| Ok::<B, Void>(f(a))).void_unwrap()
192    }
193
194    /// Gets the mutable reference of the contents of the cell,
195    /// initializing it with `f` if the cell was unset.
196    ///
197    /// # Panics
198    ///
199    /// If `f` panics, the panic is propagated to the caller, and the cell
200    /// remains uninitialized.
201    ///
202    /// # Examples
203    ///
204    /// ```
205    /// use twice_cell::TwiceCell;
206    ///
207    /// let mut cell = TwiceCell::new("twice_cell");
208    /// let value = cell.get_mut_or_init(|s| s.len());
209    /// assert_eq!(*value, 10);
210    ///
211    /// *value += 2;
212    /// assert_eq!(*value, 12);
213    ///
214    /// let value = cell.get_mut_or_init(|_| unreachable!());
215    /// assert_eq!(*value, 12);
216    /// ```
217    #[inline]
218    pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut B
219    where
220        F: FnOnce(&A) -> B,
221    {
222        self.get_mut_or_try_init(|a| Ok::<B, Void>(f(a)))
223            .void_unwrap()
224    }
225
226    /// Gets the contents of the cell, initializing it with `f` if
227    /// the cell was unset.
228    ///
229    /// # Panics
230    ///
231    /// If `f` panics, the panic is propagated to the caller, and the cell
232    /// remains uninitialized.
233    ///
234    /// It is an error to reentrantly initialize the cell from `f`. Doing
235    /// so results in a panic.
236    ///
237    /// # Errors
238    ///
239    /// If the cell was unset and `f` failed, an
240    /// error is returned.
241    ///
242    /// # Examples
243    ///
244    /// ```
245    /// use twice_cell::TwiceCell;
246    ///
247    /// let cell = TwiceCell::new(16);
248    /// assert_eq!(cell.get_or_try_init(|_| Err(())), Err(()));
249    /// assert!(cell.get().is_none());
250    /// let value = cell.get_or_try_init(|n| -> Result<i32, ()> {
251    ///     Ok(n * 4)
252    /// });
253    /// assert_eq!(value, Ok(&64));
254    /// assert_eq!(cell.get(), Some(&64))
255    /// ```
256    #[inline]
257    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&B, E>
258    where
259        F: FnOnce(&A) -> Result<B, E>,
260    {
261        // Safety: The reference to `A` is only live for the duration of this function.
262        match unsafe { self.get_either() } {
263            // Safety: this `a` came from `self`
264            Either::Left(a) => unsafe { self.try_init(f, a) },
265            // Safety: we can always dereference pointers from `self.get_either`
266            Either::Right(b) => Ok(unsafe { &*b }),
267        }
268    }
269
270    /// Gets the mutable reference of the contents of the cell, initializing
271    /// it with `f` if the cell was unset.
272    ///
273    /// # Panics
274    ///
275    /// If `f` panics, the panic is propagated to the caller, and the cell
276    /// remains uninitialized.
277    ///
278    /// # Errors
279    ///
280    /// If the cell was unset and `f` failed, an error is returned.
281    ///
282    /// # Examples
283    ///
284    /// ```
285    /// use twice_cell::TwiceCell;
286    ///
287    /// let mut cell = TwiceCell::new("not a number!");
288    ///
289    /// // Failed initializers do not change the value
290    /// assert!(cell.get_mut_or_try_init(|s| s.parse::<i32>()).is_err());
291    /// assert!(cell.get().is_none());
292    ///
293    /// let value = cell.get_mut_or_try_init(|_| "1234".parse());
294    /// assert_eq!(value, Ok(&mut 1234));
295    /// *value.unwrap() += 2;
296    /// assert_eq!(cell.get(), Some(&1236))
297    /// ```
298    #[inline]
299    pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut B, E>
300    where
301        F: FnOnce(&A) -> Result<B, E>,
302    {
303        // Safety: The reference to `A` is only live for this function call
304        if let Some(a) = unsafe { self.get_either() }.left() {
305            // Safety: this `a` came from `self`.
306            unsafe { self.try_init(f, a) }?;
307        }
308
309        // Safety: we just set this value
310        let b = unsafe { self.get_mut().unwrap_unchecked() };
311        Ok(b)
312    }
313
314    // Avoid inlining the initialization closure into the common path that fetches
315    // the already initialized value
316    /// Safety: `a` must be non-null and point to an `A` contained in `self`.
317    #[cold]
318    unsafe fn try_init<F, E>(&self, f: F, a: *const A) -> Result<&B, E>
319    where
320        F: FnOnce(&A) -> Result<B, E>,
321    {
322        // Safety: the caller guarantees we can dereference this pointer.
323        let val = f(unsafe { &*a })?;
324        if let Ok(val) = self.try_insert(val) {
325            Ok(val)
326        } else {
327            panic!("reentrant init")
328        }
329    }
330
331    /// Consumes the cell, returning the wrapped value.
332    ///
333    /// Returns `Either::Left(A)` if the cell was unset.
334    ///
335    /// # Examples
336    ///
337    /// ```
338    /// use twice_cell::TwiceCell;
339    /// use either::Either;
340    ///
341    /// let cell: TwiceCell<u8, &'static str> = TwiceCell::new(123);
342    /// assert_eq!(cell.into_inner(), Either::Left(123));
343    ///
344    /// let cell: TwiceCell<u8, &'static str> = TwiceCell::new(123);
345    /// cell.set("hello").unwrap();
346    /// assert_eq!(cell.into_inner(), Either::Right("hello"));
347    /// ```
348    #[inline]
349    pub fn into_inner(self) -> Either<A, B> {
350        self.inner.into_inner()
351    }
352
353    /// Replaces the value in this `TwiceCell`, moving it back to an unset state.
354    ///
355    /// Safety is guaranteed by requiring a mutable reference.
356    ///
357    /// # Examples
358    ///
359    /// ```
360    /// use twice_cell::TwiceCell;
361    /// use either::Either;
362    ///
363    /// let mut cell: TwiceCell<i32, &'static str> = TwiceCell::new(123);
364    /// assert_eq!(cell.replace(456), Either::Left(123));
365    ///
366    /// let mut cell = TwiceCell::new(123);
367    /// cell.set("goodbye").unwrap();
368    /// assert_eq!(cell.replace(456), Either::Right("goodbye"));
369    /// assert_eq!(cell.get(), None);
370    /// ```
371    #[inline]
372    pub fn replace(&mut self, a: A) -> Either<A, B> {
373        mem::replace(self, TwiceCell::new(a)).into_inner()
374    }
375}
376
377impl<A: Default, B> Default for TwiceCell<A, B> {
378    #[inline]
379    fn default() -> Self {
380        TwiceCell::new(A::default())
381    }
382}
383
384impl<A: Debug, B: Debug> Debug for TwiceCell<A, B> {
385    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
386        f.debug_tuple("TwiceCell")
387            // Safety: A borrow of `A` only lives until this function ends.
388            .field(&unsafe { self.get_either() })
389            .finish()
390    }
391}
392
393impl<A: Clone, B: Clone> Clone for TwiceCell<A, B> {
394    #[inline]
395    fn clone(&self) -> Self {
396        // Safety: The borrow only lives until mapped to `Clone::clone`
397        let inner = match unsafe { self.get_either() } {
398            // Safety: This pointer is non-null.
399            Either::Left(a) => Either::Left(A::clone(unsafe { &*a })),
400            // Safety: This pointer is non-null.
401            Either::Right(b) => Either::Right(B::clone(unsafe { &*b })),
402        };
403
404        TwiceCell {
405            inner: UnsafeCell::new(inner),
406        }
407    }
408
409    #[inline]
410    fn clone_from(&mut self, source: &Self) {
411        // Safety: the reference only lives for the rest of this function
412        // Note: we can't use `get_either` because we need `&Either<A, B>`, not `Either<&A, &B>`.
413        unsafe { &*source.inner.get() }.clone_into(self.inner.get_mut());
414    }
415}
416
417impl<A: PartialEq, B: PartialEq> PartialEq for TwiceCell<A, B> {
418    #[inline]
419    fn eq(&self, other: &Self) -> bool {
420        // Safety: the references only live for the duration of this function.
421        unsafe { self.get_either() == other.get_either() }
422    }
423}
424
425impl<A: Eq, B: Eq> Eq for TwiceCell<A, B> {}
426
427impl<A, B> From<B> for TwiceCell<A, B> {
428    /// Creates a new `TwiceCell<A, B>` which is already set to the given `value`.
429    #[inline]
430    fn from(value: B) -> Self {
431        TwiceCell {
432            inner: UnsafeCell::new(Either::Right(value)),
433        }
434    }
435}
436
437#[cfg(feature = "serde")]
438impl<A: serde::Serialize, B: serde::Serialize> serde::Serialize for TwiceCell<A, B> {
439    #[inline]
440    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
441    where
442        S: serde::Serializer,
443    {
444        // Safety: The reference only lives for the duration of this function.
445        either::for_both!(unsafe { self.get_either() }, ptr => unsafe { &*ptr }.serialize(serializer))
446    }
447}
448
449#[cfg(feature = "serde")]
450impl<'de, A: serde::Deserialize<'de>, B: serde::Deserialize<'de>> serde::Deserialize<'de>
451    for TwiceCell<A, B>
452{
453    #[inline]
454    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
455    where
456        D: serde::Deserializer<'de>,
457    {
458        let inner = Either::deserialize(deserializer)?;
459        Ok(TwiceCell {
460            inner: UnsafeCell::new(inner),
461        })
462    }
463}
464
465/// [`Either`], but without the tag on the union.
466///
467/// Requires some outside source of synchronization to figure out which field is currently set.
468/// In [`TwiceLock`], that's [`Once`].
469union UntaggedEither<A, B> {
470    a: ManuallyDrop<A>,
471    b: ManuallyDrop<B>,
472}
473
474impl<A, B> UntaggedEither<A, B> {
475    /// Construct a new `UntaggedEither` with the given value.
476    #[inline]
477    const fn new(value: A) -> UntaggedEither<A, B> {
478        UntaggedEither {
479            a: ManuallyDrop::new(value),
480        }
481    }
482
483    /// Take `A` out of this `UntaggedEither`, consuming it.
484    ///
485    /// Safety: The caller must guarantee that field `a` is currently set.
486    #[inline]
487    unsafe fn into_a(self) -> A {
488        ManuallyDrop::into_inner(self.a)
489    }
490
491    /// Take `B` out of this `UntaggedEither`, consuming it.
492    ///
493    /// Safety: The caller must guarantee that field `b` is currently set.
494    #[inline]
495    unsafe fn into_b(self) -> B {
496        ManuallyDrop::into_inner(self.b)
497    }
498}
499
500impl<A, B> From<B> for UntaggedEither<A, B> {
501    /// Construct a new `UntaggedEither` already set to `B`.
502    fn from(value: B) -> Self {
503        Self {
504            b: ManuallyDrop::new(value),
505        }
506    }
507}
508
509pub struct TwiceLock<A, B> {
510    /// Synchronization primitive used to enforce whether field `a` or `b` is set in `.value`.
511    once: Once,
512
513    // Whether or not the value is set is tracked by `once.is_completed()`,
514    // Invariant: modified at most once, and in the direction from `A` to `B`.
515    value: UnsafeCell<UntaggedEither<A, B>>,
516
517    // I don't understand this at all, but it's in stdlib.
518    /// `PhantomData` to make sure dropck understands we're dropping (A, B) in our Drop impl.
519    ///
520    /// ```compile_fail
521    /// use twice_cell::TwiceLock;
522    ///
523    /// struct A<'a>(&'a str);
524    ///
525    /// impl<'a> Drop for A<'a> {
526    ///     fn drop(&mut self) {}
527    /// }
528    ///
529    /// let cell = TwiceLock::new(0u8);
530    /// {
531    ///     let s = String::new();
532    ///     let _ = cell.set(A(&s));
533    /// }
534    /// ```
535    _marker: PhantomData<(A, B)>,
536}
537
538impl<A, B> TwiceLock<A, B> {
539    /// Creates a new empty cell.
540    #[inline]
541    #[must_use]
542    pub const fn new(value: A) -> TwiceLock<A, B> {
543        TwiceLock {
544            once: Once::new(),
545            value: UnsafeCell::new(UntaggedEither::new(value)),
546            _marker: PhantomData,
547        }
548    }
549
550    /// Gets the reference to the underlying value.
551    ///
552    /// Returns `None` if the cell is unset, or being set.
553    /// This method never blocks.
554    #[inline]
555    pub fn get(&self) -> Option<&B> {
556        if self.is_set() {
557            // Safety: we checked `is_set`.
558            Some(unsafe { &*self.get_b_unchecked() })
559        } else {
560            None
561        }
562    }
563
564    /// Gets the mutable reference to the underlying value.
565    ///
566    /// Returns `None` if the cell is unset. This method never blocks.
567    #[inline]
568    pub fn get_mut(&mut self) -> Option<&mut B> {
569        if self.is_set() {
570            // Safety: we checked `is_set`.
571            Some(unsafe { self.get_b_unchecked_mut() })
572        } else {
573            None
574        }
575    }
576
577    /// Get a reference to either underlying value.
578    ///
579    /// Safety: an `A` reference can only be used to initialize the value, since as soon as the value
580    /// is set the reference will be invalidated.
581    ///
582    /// Unlike `TwiceCell`, in which `A` references can be used for other purposes (e.g. equality checking),
583    /// we can _only_ use `&A` to set `self.value` inside of a `Once` closure. This is because if on
584    /// one thread we're using `A` to e.g. check equality, another thread could mutate `self` into `B`,
585    /// causing the reference to `A` to be invalidated.
586    #[inline]
587    unsafe fn get_either(&self) -> Either<*const A, *const B> {
588        if self.is_set() {
589            // Safety: we're initialized, therefore `b` is set.
590            Either::Right(unsafe { self.get_b_unchecked() })
591        } else {
592            // Safety: we're uninitialized, therefore `a` is set.
593            Either::Left(unsafe { self.get_a_unchecked() })
594        }
595    }
596
597    /// Gets the mutable reference to either underlying value.
598    //
599    // Unlike `get_either`, this function is perfectly safe because we have mutable access.
600    // No other threads can mutate this value while we hold a mutable reference.
601    #[inline]
602    pub fn get_either_mut(&mut self) -> Either<&mut A, &mut B> {
603        if self.is_set() {
604            // Safety: we're initialized, therefore `b` is set.
605            Either::Right(unsafe { self.get_b_unchecked_mut() })
606        } else {
607            // Safety: we're uninitialized, therefore `a` is set.
608            Either::Left(unsafe { self.get_a_unchecked_mut() })
609        }
610    }
611
612    /// Sets the contents of this cell to `value`.
613    ///
614    /// May block if another thread is currently attempting to initialize the cell. The cell is
615    /// guaranteed to contain a value when set returns, though not necessarily the one provided.
616    ///
617    /// # Errors
618    ///
619    /// Returns `Ok(())` if the cell's value was set by this call.
620    ///
621    /// # Examples
622    ///
623    /// ```
624    /// use twice_cell::TwiceLock;
625    ///
626    /// static CELL: TwiceLock<&str, i32> = TwiceLock::new("initial value");
627    ///
628    /// fn main() {
629    ///     assert!(CELL.get().is_none());
630    ///
631    ///     std::thread::spawn(|| {
632    ///         assert_eq!(CELL.set(92), Ok(()));
633    ///     }).join().unwrap();
634    ///
635    ///     assert_eq!(CELL.set(62), Err(62));
636    ///     assert_eq!(CELL.get(), Some(&92));
637    /// }
638    /// ```
639    pub fn set(&self, value: B) -> Result<(), B>
640    where
641        A: RefUnwindSafe,
642    {
643        match self.try_insert(value) {
644            Ok(_) => Ok(()),
645            Err((_, value)) => Err(value),
646        }
647    }
648
649    /// Sets the contents of this cell to `value` if the cell was empty, then
650    /// returns a reference to it.
651    ///
652    /// May block if another thread is currently attempting to initialize the cell. The cell is
653    /// guaranteed to contain a value when set returns, though not necessarily the one provided.
654    ///
655    /// # Errors
656    ///
657    /// Returns `Ok(&value)` if the cell was empty and `Err(&current_value, value)` if it was full.
658    ///
659    /// # Examples
660    ///
661    /// ```
662    ///
663    /// use twice_cell::TwiceLock;
664    ///
665    /// static CELL: TwiceLock<&'static str, i32> = TwiceLock::new("initial value");
666    ///
667    /// fn main() {
668    ///     assert!(CELL.get().is_none());
669    ///
670    ///     std::thread::spawn(|| {
671    ///         assert_eq!(CELL.try_insert(92), Ok(&92));
672    ///     }).join().unwrap();
673    ///
674    ///     assert_eq!(CELL.try_insert(62), Err((&92, 62)));
675    ///     assert_eq!(CELL.get(), Some(&92));
676    /// }
677    /// ```
678    #[inline]
679    pub fn try_insert(&self, value: B) -> Result<&B, (&B, B)>
680    where
681        A: RefUnwindSafe,
682    {
683        let mut value = Some(value);
684        let mut safe_value = AssertUnwindSafe(&mut value);
685        // Safety: the value is set to `Some` right above
686        let res = self.get_or_init(move |_| unsafe { safe_value.take().unwrap_unchecked() });
687
688        match value {
689            None => Ok(res),
690            Some(value) => Err((res, value)),
691        }
692    }
693
694    /// Gets the contents of the cell, initializing it with `f` if the cell
695    /// was empty.
696    ///
697    /// Many threads may call `get_or_init` concurrently with different
698    /// initializing functions, but it is guaranteed that only one function
699    /// will be executed.
700    ///
701    /// # Panics
702    ///
703    /// If `f` panics, the panic is propagated to the caller, and the cell
704    /// remains uninitialized.
705    ///
706    /// It is an error to reentrantly initialize the cell from `f`. The
707    /// exact outcome is unspecified. Current implementation deadlocks, but
708    /// this may be changed to a panic in the future.
709    ///
710    /// # Examples
711    ///
712    /// ```
713    /// use twice_cell::TwiceLock;
714    ///
715    /// let cell = TwiceLock::new("initial value");
716    /// let value = cell.get_or_init(|s| s.len());
717    /// assert_eq!(value, &13);
718    /// let value = cell.get_or_init(|_| unreachable!());
719    /// assert_eq!(value, &13);
720    /// ```
721    #[inline]
722    pub fn get_or_init<F>(&self, f: F) -> &B
723    where
724        F: UnwindSafe + FnOnce(&A) -> B,
725        A: RefUnwindSafe,
726    {
727        self.get_or_try_init(|a| Ok::<B, Void>(f(a))).void_unwrap()
728    }
729
730    /// Gets the mutable reference of the contents of the cell, initializing
731    /// it with `f` if the cell was empty.
732    ///
733    /// Many threads may call `get_mut_or_init` concurrently with different
734    /// initializing functions, but it is guaranteed that only one function
735    /// will be executed.
736    ///
737    /// # Panics
738    ///
739    /// If `f` panics, the panic is propagated to the caller, and the cell
740    /// remains uninitialized.
741    ///
742    /// # Examples
743    ///
744    /// ```
745    /// use twice_cell::TwiceLock;
746    ///
747    /// let mut cell = TwiceLock::new("initial value");
748    /// let value = cell.get_mut_or_init(|s| s.len());
749    /// assert_eq!(*value, 13);
750    ///
751    /// *value += 2;
752    /// assert_eq!(*value, 15);
753    ///
754    /// let value = cell.get_mut_or_init(|_| unreachable!());
755    /// assert_eq!(*value, 15);
756    /// ```
757    #[inline]
758    pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut B
759    where
760        F: UnwindSafe + FnOnce(&A) -> B,
761        A: RefUnwindSafe,
762    {
763        self.get_mut_or_try_init(|a| Ok::<B, Void>(f(a)))
764            .void_unwrap()
765    }
766
767    /// Gets the contents of the cell, initializing it with `f` if
768    /// the cell was empty.
769    ///
770    /// # Panics
771    ///
772    /// If `f` panics, the panic is propagated to the caller, and
773    /// the cell remains uninitialized.
774    ///
775    /// # Errors
776    ///
777    /// If the cell was empty and `f` failed, an error is returned.
778    ///
779    /// It is an error to reentrantly initialize the cell from `f`.
780    /// The exact outcome is unspecified. Current implementation
781    /// deadlocks, but this may be changed to a panic in the future.
782    ///
783    /// # Examples
784    ///
785    /// ```
786    /// use twice_cell::TwiceLock;
787    ///
788    /// let cell = TwiceLock::new("initial value");
789    ///
790    /// assert_eq!(cell.get_or_try_init(|_| Err(())), Err(()));
791    /// assert!(cell.get().is_none());
792    ///
793    /// let value = cell.get_or_try_init(|s| -> Result<usize, ()> {
794    ///     Ok(s.len())
795    /// });
796    /// assert_eq!(value, Ok(&13));
797    /// assert_eq!(cell.get(), Some(&13))
798    /// ```
799    #[inline]
800    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&B, E>
801    where
802        F: UnwindSafe + FnOnce(&A) -> Result<B, E>,
803        E: Send + 'static,
804        A: RefUnwindSafe,
805    {
806        // Fast path check
807        // NOTE: We need to perform an acquire on the state in this method
808        // in order to correctly synchronize `LazyLock::force`. This is
809        // currently done by calling `self.get_either()`, which in turn calls
810        // `self.is_initialized()`, which in turn performs the acquire.
811        //
812        // Safety: the `A` reference is used to initialize `self.value`
813        match unsafe { self.get_either() } {
814            // Safety: `a` came from `self`.
815            Either::Left(a) => unsafe { self.initialize(f, a) }?,
816            // Safety: This pointer is non-null because it came from `self.get_either()`
817            Either::Right(b) => return Ok(unsafe { &*b }),
818        };
819
820        debug_assert!(self.is_set());
821        // SAFETY: The inner value has been initialized
822        Ok(unsafe { &*self.get_b_unchecked() })
823    }
824
825    /// Gets the mutable reference of the contents of the cell, initializing
826    /// it with `f` if the cell was empty.
827    ///
828    /// # Panics
829    ///
830    /// If `f` panics, the panic is propagated to the caller, and
831    /// the cell remains uninitialized.
832    ///
833    /// # Errors
834    ///
835    /// If the cell was empty and `f` failed, an error is returned.
836    ///
837    /// # Examples
838    ///
839    /// ```
840    /// use twice_cell::TwiceLock;
841    ///
842    /// let mut cell: TwiceLock<&'static str, usize> = TwiceLock::new("not a number");
843    ///
844    /// // Failed initializers do not change the value
845    /// assert!(cell.get_mut_or_try_init(|s| s.parse()).is_err());
846    /// assert!(cell.get().is_none());
847    ///
848    /// let value = cell.get_mut_or_try_init(|_| "1234".parse());
849    /// assert_eq!(value, Ok(&mut 1234));
850    ///
851    /// *value.unwrap() += 2;
852    /// assert_eq!(cell.get(), Some(&1236));
853    /// ```
854    #[inline]
855    pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut B, E>
856    where
857        F: UnwindSafe + FnOnce(&A) -> Result<B, E>,
858        E: Send + 'static,
859        A: RefUnwindSafe,
860    {
861        // Safety: we're only using `a` to initialize
862        if let Some(a) = unsafe { self.get_either() }.left() {
863            // Safety: `a` came from `self`.
864            unsafe { self.initialize(f, a) }?;
865        }
866
867        debug_assert!(self.is_set());
868        // Safety: The inner value has been initialized
869        Ok(unsafe { self.get_b_unchecked_mut() })
870    }
871
872    /// Takes the value out of this `TwiceLock`, moving it back to an unset state.
873    ///
874    /// Returns `Either::Left` if the `TwiceLock` hasn't been set.
875    ///
876    /// Safety is guaranteed by requiring a mutable reference.
877    ///
878    /// # Examples
879    ///
880    /// ```
881    /// use twice_cell::TwiceLock;
882    /// use either::Either;
883    ///
884    /// let mut cell: TwiceLock<i32, String> = TwiceLock::new(123);
885    /// assert_eq!(cell.replace(456), Either::Left(123));
886    ///
887    /// let mut cell = TwiceLock::new(123);
888    /// cell.set("hello").unwrap();
889    ///
890    /// assert_eq!(cell.replace(456), Either::Right("hello"));
891    /// assert_eq!(cell.get(), None);
892    /// ```
893    #[inline]
894    pub fn replace(&mut self, value: A) -> Either<A, B> {
895        let inner = mem::replace(self.value.get_mut(), UntaggedEither::new(value));
896
897        if self.is_set() {
898            self.once = Once::new();
899            // SAFETY: `self.value` is initialized and contains a valid `B`.
900            // `self.once` is reset, so `is_initialized()` will be false again
901            // which prevents the value from being read twice.
902            Either::Right(unsafe { inner.into_b() })
903        } else {
904            // Safety: we know `self` is uninitialized
905            Either::Left(unsafe { inner.into_a() })
906        }
907    }
908
909    #[inline]
910    fn is_set(&self) -> bool {
911        self.once.is_completed()
912    }
913
914    /// Safety: `a` must be non-null and point to the value contained in `self`.
915    #[cold]
916    unsafe fn initialize<F, E>(&self, f: F, a: *const A) -> Result<(), E>
917    where
918        F: FnOnce(&A) -> Result<B, E>,
919        E: Send + 'static,
920        A: RefUnwindSafe,
921        F: UnwindSafe,
922    {
923        let slot = &self.value;
924
925        // Since we don't have access to `p.poison()`, we have to panic and then catch it explicitly.
926        std::panic::catch_unwind(AssertUnwindSafe(|| {
927            self.once.call_once_force(|_| {
928                // Safety: the caller guarantees this pointer is non-null.
929                match f(unsafe { &*a }) {
930                    Ok(value) => {
931                        // Safety: we have unique access to the slot because we're inside a `once` closure.
932                        unsafe { (*slot.get()).b = ManuallyDrop::new(value) };
933                    }
934                    Err(e) => resume_unwind(Box::new(e)),
935                }
936            });
937        }))
938        .map_err(|any| match any.downcast() {
939            Ok(e) => *e,
940            Err(any) => resume_unwind(any),
941        })
942    }
943
944    /// # Safety
945    ///
946    /// The value must be unset.
947    #[inline]
948    unsafe fn get_a_unchecked(&self) -> *const A {
949        debug_assert!(!self.is_set());
950
951        // Safety: The caller upholds the contract that the value is unset, and therefore `.a` is set.
952        unsafe { &*(*self.value.get()).a }
953    }
954
955    #[inline]
956    unsafe fn get_a_unchecked_mut(&mut self) -> &mut ManuallyDrop<A> {
957        debug_assert!(!self.is_set());
958
959        // Safety: the caller upholds the contract that the value is unset, and therefore `.a` is set.
960        unsafe { &mut self.value.get_mut().a }
961    }
962
963    /// # Safety
964    ///
965    /// The value must be set.
966    #[inline]
967    unsafe fn get_b_unchecked(&self) -> *const B {
968        debug_assert!(self.is_set());
969
970        // Safety: The caller upholds the contract that the value (and therefore `.b`) is set.
971        unsafe { &*(*self.value.get()).b }
972    }
973
974    /// # Safety
975    ///
976    /// The value must be set.
977    #[inline]
978    unsafe fn get_b_unchecked_mut(&mut self) -> &mut ManuallyDrop<B> {
979        debug_assert!(self.is_set());
980
981        // Safety: The caller upholds the contract that the value (and therefore `.b`) is set.
982        unsafe { &mut self.value.get_mut().b }
983    }
984}
985
986impl<A, B> Drop for TwiceLock<A, B> {
987    #[inline]
988    fn drop(&mut self) {
989        if self.is_set() {
990            // Safety: we know the data was initialized and therefore `b` is set.
991            let b = unsafe { self.get_b_unchecked_mut() };
992
993            // Safety: we're dropping in the destructor.
994            unsafe { ManuallyDrop::drop(b) };
995        } else {
996            // Safety: the data is uninitialized and therefore `a` is set.
997            let a = unsafe { self.get_a_unchecked_mut() };
998
999            // Safety: we're dropping in the destructor.
1000            unsafe { ManuallyDrop::drop(a) };
1001        }
1002    }
1003}
1004
1005/// Safety: The `UnsafeCell` exists to enforce borrow checking via the `Once` primitive instead of the compiler;
1006/// that is to say, we can override `UnsafeCell`'s `!Send`-ness if both `A` and `B` are `Send`.
1007unsafe impl<A: Send, B: Send> Send for TwiceLock<A, B> {}
1008
1009/// Safety: The same is true for `Sync`, except that we also need `A` and `B` to `impl Send` for the same reason
1010/// there's `Send` bounds on the [`OnceLock`](`std::sync::OnceLock`) implementation:
1011///
1012/// > Why do we need `T: Send`?
1013/// > Thread A creates a `OnceLock` and shares it with scoped thread B,
1014/// > which fills the cell, which is then destroyed by A.
1015/// > That is, destructor observes a sent value.
1016unsafe impl<A: Sync + Send, B: Sync + Send> Sync for TwiceLock<A, B> {}
1017
1018impl<A: Default, B> Default for TwiceLock<A, B> {
1019    #[inline]
1020    fn default() -> Self {
1021        TwiceLock::new(A::default())
1022    }
1023}
1024
1025impl<A: Debug, B: Debug> Debug for TwiceLock<A, B> {
1026    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1027        let mut d = f.debug_tuple("TwiceLock");
1028        match self.get() {
1029            Some(v) => d.field(v),
1030            None => d.field(&format_args!("<unset>")),
1031        };
1032
1033        d.finish()
1034    }
1035}
1036
1037impl<A, B> From<B> for TwiceLock<A, B> {
1038    /// Create a new cell with its contents set to `value`.
1039    ///
1040    /// # Example
1041    ///
1042    /// ```
1043    /// use std::sync::OnceLock;
1044    ///
1045    /// # fn main() -> Result<(), i32> {
1046    /// let a = OnceLock::from(3);
1047    /// let b = OnceLock::new();
1048    /// b.set(3)?;
1049    /// assert_eq!(a, b);
1050    /// Ok(())
1051    /// # }
1052    /// ```
1053    #[inline]
1054    fn from(value: B) -> Self {
1055        let once = Once::new();
1056        once.call_once(|| {});
1057
1058        let value = UnsafeCell::new(UntaggedEither::from(value));
1059
1060        TwiceLock {
1061            once,
1062            value,
1063            _marker: PhantomData,
1064        }
1065    }
1066}