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(¤t_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(¤t_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}