poly_once/transform_once.rs
1//! Parameterized once cell with transformation support.
2//!
3//! This module provides the [`TOnce<P, T>`] type, a thread-safe cell that stores
4//! a parameter of type `P` and transforms it into a value of type `T` on first access.
5//! This is useful when you need to defer expensive initialization that requires
6//! input data, or when the initialization parameters are known at construction
7//! but the computation should be lazy.
8//!
9//! The key difference from `Once<T>` is that `TOnce<P, T>` stores the parameter
10//! until initialization, then replaces it with the computed value. This allows
11//! for more flexible initialization patterns where the initialization logic
12//! needs access to stored state.
13//!
14//! Like `Once`, it uses atomic operations for the fast path and futex-based
15//! synchronization for the slow path.
16
17use core::cell::UnsafeCell;
18use core::future::Future;
19use core::sync::atomic::Ordering;
20use core::{fmt, mem};
21
22use super::state::OnceLock;
23use crate::state::OnceGuard;
24
25/// Internal enum to hold either the parameter or the initialized value.
26union TOnceState<P, T> {
27 pending: mem::ManuallyDrop<P>,
28 init: mem::ManuallyDrop<T>,
29}
30
31impl<P, T> TOnceState<P, T> {
32 #[inline(always)]
33 const fn pending(value: P) -> Self {
34 Self {
35 pending: mem::ManuallyDrop::new(value),
36 }
37 }
38 #[inline(always)]
39 const fn init(value: T) -> Self {
40 Self {
41 init: mem::ManuallyDrop::new(value),
42 }
43 }
44 #[inline(always)]
45 unsafe fn drop_pending(&mut self) -> P {
46 mem::ManuallyDrop::take(unsafe { &mut self.pending })
47 }
48
49 #[inline(always)]
50 unsafe fn drop_init(&mut self) -> T {
51 mem::ManuallyDrop::take(unsafe { &mut self.init })
52 }
53}
54
55struct EditSanitizer<'a, P, T> {
56 state: &'a mut TOnceState<P, T>,
57 guard: OnceGuard<'a>,
58 taken: bool,
59}
60
61impl<'a, P, T> EditSanitizer<'a, P, T> {
62 #[inline(always)]
63 fn new(state: &'a UnsafeCell<TOnceState<P, T>>, guard: OnceGuard<'a>) -> Self {
64 Self {
65 state: unsafe { &mut *state.get() },
66 taken: false,
67 guard,
68 }
69 }
70
71 #[inline(always)]
72 unsafe fn take_parameter(&mut self) -> P {
73 debug_assert!(!self.taken, "Parameter already taken");
74 self.taken = true;
75 unsafe { self.state.drop_pending() }
76 }
77 #[inline(always)]
78 unsafe fn ref_parameter(&self) -> &P {
79 unsafe { &self.state.pending }
80 }
81 #[inline(always)]
82 unsafe fn commit(self, value: T) -> &'a mut T {
83 unsafe {
84 if !self.taken {
85 _ = self.state.drop_pending();
86 }
87 *self.state = TOnceState::init(value);
88 self.guard.commit_forgotten();
89 let ptr = self.state as *mut TOnceState<P, T>;
90 mem::forget(self);
91 &mut (*ptr).init
92 }
93 }
94}
95
96#[cfg(debug_assertions)]
97impl<P, T> Drop for EditSanitizer<'_, P, T> {
98 #[inline(always)]
99 fn drop(&mut self) {
100 assert!(!self.taken, "Parameter taken on return, no value in cell");
101 }
102}
103
104/// A thread-safe cell which can be written to only once using a parameterized initializer.
105///
106/// This structure provides safe initialization for values that might be accessed
107/// concurrently by multiple threads. It ensures that the initialization logic
108/// runs only once, even if multiple threads attempt to initialize the value simultaneously.
109///
110/// It uses atomic operations and `parking_lot`'s futex-based synchronization for
111/// efficient blocking when necessary.
112pub struct TOnce<P, T> {
113 value: UnsafeCell<TOnceState<P, T>>,
114 lock: OnceLock,
115}
116
117impl<P, T> TOnce<P, T> {
118 /// Creates a new, uninitialized `TOnce` cell with the given parameter.
119 #[inline]
120 #[must_use]
121 pub const fn new(param: P) -> Self {
122 Self {
123 lock: OnceLock::new(),
124 value: UnsafeCell::new(TOnceState::pending(param)),
125 }
126 }
127
128 /// Creates a new `TOnce` cell that is already initialized with the given value, bypassing the parameter.
129 #[inline]
130 #[must_use]
131 pub const fn with_value(value: T) -> Self {
132 Self {
133 lock: OnceLock::done(),
134 value: UnsafeCell::new(TOnceState::init(value)),
135 }
136 }
137
138 /// Checks if the cell has been initialized.
139 ///
140 /// This method never blocks.
141 #[inline]
142 pub fn is_done(&self) -> bool {
143 self.lock.is_done(Ordering::Relaxed)
144 }
145
146 /// Returns a reference to the contained value if initialized.
147 ///
148 /// Returns `None` if the cell is uninitialized or currently being initialized.
149 /// This method never blocks.
150 #[inline]
151 pub fn get(&self) -> Option<&T> {
152 if self.is_done() {
153 // SAFETY: is_done() returned true, so the value is initialized.
154 Some(unsafe { self.get_unchecked() })
155 } else {
156 None
157 }
158 }
159
160 /// Returns a mutable reference to the contained value if initialized.
161 ///
162 /// Returns `None` if the cell is uninitialized or currently being initialized.
163 /// This method requires exclusive access (`&mut self`) and never blocks.
164 #[inline]
165 pub fn get_mut(&mut self) -> Option<&mut T> {
166 if self.is_done() {
167 // SAFETY: is_done() returned true and we have exclusive access (`&mut self`).
168 Some(unsafe { self.get_unchecked_mut() })
169 } else {
170 None
171 }
172 }
173
174 /// Attempts to initialize the cell with `value` without blocking, ignoring the parameter.
175 ///
176 /// - If the cell is uninitialized and not locked, initializes it with `value` and returns `Ok(&value)`.
177 /// - If the cell is already initialized, returns `Err(value)`.
178 /// - If the cell is currently locked by another thread, returns `Err(value)`.
179 #[inline]
180 pub fn try_set(&self, value: T) -> Result<&T, T> {
181 let Some(guard) = self.lock.try_lock() else {
182 return Err(value);
183 };
184 // SAFETY: We hold the lock, so we have exclusive access to initialize the value.
185 unsafe {
186 let edit = EditSanitizer::new(&self.value, guard);
187 let v = edit.commit(value);
188 Ok(v)
189 }
190 }
191
192 /// Replaces the cell's value, returning the old value if initialized.
193 ///
194 /// - If uninitialized, discards the parameter, sets the value to `value` and returns `None`.
195 /// - If initialized, replaces the existing value with `value` and returns the old value.
196 ///
197 /// Requires exclusive access (`&mut self`), so it never blocks.
198 #[inline]
199 pub fn replace_mut(&mut self, value: T) -> Option<T> {
200 if self.lock.set_done() {
201 // Was uninitialized, now set to done. Replace with the new value.
202 unsafe {
203 mem::replace(self.value.get_mut(), TOnceState::init(value)).drop_pending();
204 }
205 None
206 } else {
207 // Was already initialized. Replace the existing value.
208 Some(unsafe { mem::replace(self.get_unchecked_mut(), value) })
209 }
210 }
211
212 /// Gets a mutable reference, initializing with `value` if needed.
213 ///
214 /// - If initialized, returns a mutable reference to the existing value.
215 /// - If uninitialized, discards the parameter, initializes it with `value` and returns a mutable reference.
216 ///
217 /// Requires exclusive access (`&mut self`), so it never blocks.
218 #[inline]
219 pub fn get_mut_or_set(&mut self, value: T) -> &mut T {
220 if self.lock.set_done() {
221 // Was uninitialized, now set to done. Replace with the new value.
222 unsafe {
223 mem::replace(self.value.get_mut(), TOnceState::init(value)).drop_pending();
224 }
225 }
226 // SAFETY: The cell is guaranteed to be initialized here, either previously
227 // or by the call above, and we have exclusive access.
228 unsafe { self.get_unchecked_mut() }
229 }
230
231 /// Gets a mutable reference, initializing with `Default::default()` if needed.
232 ///
233 /// - If initialized, returns a mutable reference to the existing value.
234 /// - If uninitialized, discards the parameter, initializes it with `T::default()` and returns a mutable reference.
235 ///
236 /// Requires exclusive access (`&mut self`), so it never blocks.
237 #[inline]
238 pub fn get_mut_or_default(&mut self) -> &mut T
239 where
240 T: Default,
241 {
242 if self.lock.set_done() {
243 // Was uninitialized, now set to done. Replace with the default value.
244 unsafe {
245 mem::replace(self.value.get_mut(), TOnceState::init(T::default())).drop_pending();
246 }
247 }
248 // SAFETY: The cell is guaranteed to be initialized here, either previously
249 // or by the call above, and we have exclusive access.
250 unsafe { self.get_unchecked_mut() }
251 }
252
253 /// Returns a reference to the value without checking if it's initialized.
254 ///
255 /// # Safety
256 ///
257 /// Calling this method on an uninitialized `TOnce` cell is *undefined behavior*.
258 /// The caller must ensure the cell is initialized, e.g., by calling `is_done()` or `get()`.
259 #[inline]
260 pub unsafe fn get_unchecked(&self) -> &T {
261 debug_assert!(self.is_done(), "get_unchecked called on uninitialized Once");
262 // SAFETY: The caller guarantees that the cell is initialized.
263 unsafe { &(*self.value.get()).init }
264 }
265
266 /// Returns a mutable reference to the value without checking if it's initialized.
267 ///
268 /// # Safety
269 ///
270 /// Calling this method on an uninitialized `TOnce` cell is *undefined behavior*.
271 /// The caller must ensure the cell is initialized and that they have exclusive access.
272 #[inline]
273 pub unsafe fn get_unchecked_mut(&mut self) -> &mut T {
274 debug_assert!(
275 self.is_done(),
276 "get_unchecked_mut called on uninitialized Once"
277 );
278 // SAFETY: The caller guarantees that the cell is initialized and we have exclusive access.
279 unsafe { &mut (*self.value.get()).init }
280 }
281
282 /// Takes the value out of the cell, leaving it uninitialized with the given parameter.
283 ///
284 /// Returns `Some(value)` if the cell was initialized, `None` otherwise.
285 /// Requires exclusive access (`&mut self`), so it never blocks.
286 #[inline]
287 pub fn take(&mut self, param: P) -> Result<T, P> {
288 if !self.lock.set_uninit() {
289 return Err(param);
290 }
291 let mut mref = mem::replace(self.value.get_mut(), TOnceState::pending(param));
292 Ok(unsafe { mref.drop_init() })
293 }
294
295 /// Initializes the cell with `value`, ignoring the parameter. Blocks if another thread is initializing.
296 ///
297 /// - If uninitialized, discards the parameter, initializes it with `value` and returns `Ok(())`.
298 /// - If already initialized, returns `Err(value)`.
299 ///
300 /// Guarantees the cell is initialized upon return, but not necessarily with `value`
301 /// if another thread completed initialization first.
302 #[inline]
303 pub fn set(&self, value: T) -> Result<(), T> {
304 match self.try_insert(value) {
305 Ok(_) => Ok(()), // Successfully inserted our value
306 Err((_current_value, original_value)) => Err(original_value), // Already initialized by someone else
307 }
308 }
309
310 /// Initializes the cell with `value` if uninitialized, returning a reference. Blocks if needed.
311 ///
312 /// - If uninitialized, discards the parameter, initializes with `value` and returns `Ok(&value)`.
313 /// - If already initialized, returns `Err((¤t_value, value))`.
314 ///
315 /// Guarantees the cell is initialized upon return.
316 #[inline]
317 pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
318 // `get_or_init` ensures initialization. We use `value` only if the cell was empty.
319 let mut value_opt = Some(value);
320 let res_ref = self.get_or_init(|_p| value_opt.take().unwrap());
321 match value_opt {
322 None => Ok(res_ref), // Our value was used for initialization
323 Some(original_value) => Err((res_ref, original_value)), // Someone else initialized it first
324 }
325 }
326
327 /// Gets the value, initializing with `f(param)` if needed. Blocks if needed.
328 ///
329 /// - If initialized, returns a reference to the existing value.
330 /// - If uninitialized, calls `f(param)`, stores the result, and returns a reference.
331 ///
332 /// If multiple threads call this concurrently, only one `f(param)` execution happens.
333 #[inline]
334 pub fn get_or_init<F>(&self, f: F) -> &T
335 where
336 F: FnOnce(P) -> T,
337 {
338 if let Some(value) = self.get() {
339 return value;
340 }
341 // Cold path: needs initialization
342 self.initialize(f);
343 // SAFETY: initialize ensures the value is now initialized.
344 unsafe { self.get_unchecked() }
345 }
346
347 /// Gets a mutable reference, initializing with `f(param)` if needed.
348 ///
349 /// - If initialized, returns a mutable reference to the existing value.
350 /// - If uninitialized, calls `f(param)`, stores the result, and returns a mutable reference.
351 ///
352 /// Requires exclusive access (`&mut self`), so it never blocks.
353 #[inline]
354 pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T
355 where
356 F: FnOnce(P) -> T,
357 {
358 if self.is_done() {
359 // Already initialized.
360 } else if let Some(guard) = self.lock.try_lock() {
361 // We got the lock (because is_done was false and no one else had it). Initialize it.
362 // SAFETY: We hold the lock, exclusive access to initialize.
363 unsafe {
364 let mut edit = EditSanitizer::new(&self.value, guard);
365 let value = f(edit.take_parameter());
366 edit.commit(value);
367 }
368 } else {
369 // This case should theoretically not happen with &mut self,
370 // as try_lock should succeed if !is_done().
371 // If it did, it implies a logic error or unexpected concurrent access.
372 unreachable!("Could not lock for init despite having exclusive access");
373 }
374
375 // SAFETY: The cell is guaranteed to be initialized now, and we have exclusive access.
376 unsafe { self.get_unchecked_mut() }
377 }
378
379 /// Gets the value, initializing with fallible `f(param)` if needed. Blocks if needed.
380 ///
381 /// - If initialized, returns `Ok(&value)`.
382 /// - If uninitialized, calls `f(param)`:
383 /// - On `Ok(value)`, initializes the cell and returns `Ok(&value)`.
384 /// - On `Err(e)`, returns `Err(e)` and leaves the cell uninitialized.
385 ///
386 /// If multiple threads call this concurrently, only one `f(param)` execution happens.
387 pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
388 where
389 F: FnOnce(&P) -> Result<T, E>,
390 {
391 if let Some(value) = self.get() {
392 return Ok(value);
393 }
394 // Cold path: needs initialization attempt
395 self.try_initialize(f)?;
396 // If try_initialize succeeded, it's now initialized.
397 debug_assert!(self.is_done());
398 // SAFETY: try_initialize succeeded, so the value is initialized.
399 Ok(unsafe { self.get_unchecked() })
400 }
401
402 /// Gets a mutable reference, initializing with fallible `f(param)` if needed.
403 ///
404 /// - If initialized, returns `Ok(&mut value)`.
405 /// - If uninitialized, calls `f(param)`:
406 /// - On `Ok(value)`, initializes the cell and returns `Ok(&mut value)`.
407 /// - On `Err(e)`, returns `Err(e)` and leaves the cell uninitialized.
408 ///
409 /// Requires exclusive access (`&mut self`), so it never blocks (initialization happens inline).
410 pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
411 where
412 F: FnOnce(&P) -> Result<T, E>,
413 {
414 if let Some(guard) = self.lock.try_lock() {
415 // We got the lock. Try to initialize.
416 unsafe {
417 let edit = EditSanitizer::new(&self.value, guard);
418 let value = f(edit.ref_parameter())?;
419 edit.commit(value);
420 }
421 }
422 // SAFETY: The cell is guaranteed to be initialized now (or we returned Err),
423 // and we have exclusive access.
424 Ok(unsafe { self.get_unchecked_mut() })
425 }
426
427 /// Gets the value, initializing asynchronously with `f(param)` if needed. Blocks if needed.
428 ///
429 /// - If initialized, returns a reference to the existing value.
430 /// - If uninitialized, awaits `f(param)`, stores the result, and returns a reference.
431 ///
432 /// If multiple tasks call this concurrently, only one `f(param)` execution happens.
433 #[inline]
434 pub async fn get_or_init_async<F, Fut>(&self, f: F) -> &T
435 where
436 F: FnOnce(&P) -> Fut,
437 Fut: Future<Output = T>,
438 {
439 if let Some(value) = self.get() {
440 return value;
441 }
442 // Cold path: needs async initialization
443 self.initialize_async(f).await;
444 // SAFETY: initialize_async ensures the value is now initialized.
445 unsafe { self.get_unchecked() }
446 }
447
448 /// Gets a mutable reference, initializing asynchronously with `f(param)` if needed.
449 ///
450 /// - If initialized, returns a mutable reference to the existing value.
451 /// - If uninitialized, awaits `f(param)`, stores the result, and returns a mutable reference.
452 ///
453 /// Requires exclusive access (`&mut self`), so it never blocks (initialization happens inline).
454 #[inline]
455 pub async fn get_mut_or_init_async<F, Fut>(&mut self, f: F) -> &mut T
456 where
457 F: FnOnce(&P) -> Fut,
458 Fut: Future<Output = T>,
459 {
460 if let Some(guard) = self.lock.try_lock() {
461 // We got the lock. Try to initialize.
462 unsafe {
463 let edit = EditSanitizer::new(&self.value, guard);
464 let value = f(edit.ref_parameter()).await;
465 edit.commit(value);
466 }
467 }
468 // SAFETY: The cell is guaranteed to be initialized now (or we returned Err),
469 // and we have exclusive access.
470 unsafe { self.get_unchecked_mut() }
471 }
472
473 /// Gets the value, initializing asynchronously with fallible `f(param)` if needed. Blocks if needed.
474 ///
475 /// - If initialized, returns `Ok(&value)`.
476 /// - If uninitialized, awaits `f(param)`:
477 /// - On `Ok(value)`, initializes the cell and returns `Ok(&value)`.
478 /// - On `Err(e)`, returns `Err(e)` and leaves the cell uninitialized.
479 ///
480 /// If multiple tasks call this concurrently, only one `f(param)` execution happens.
481 pub async fn get_or_try_init_async<F, Fut, E>(&self, f: F) -> Result<&T, E>
482 where
483 F: FnOnce(&P) -> Fut,
484 Fut: Future<Output = Result<T, E>>,
485 {
486 if let Some(value) = self.get() {
487 return Ok(value);
488 }
489 // Cold path: needs async initialization attempt
490 self.try_initialize_async(f).await?;
491 // If try_initialize_async succeeded, it's now initialized.
492 debug_assert!(self.is_done());
493 // SAFETY: try_initialize_async succeeded, so the value is initialized.
494 Ok(unsafe { self.get_unchecked() })
495 }
496
497 /// Gets a mutable reference, initializing asynchronously with fallible `f(param)` if needed.
498 ///
499 /// - If initialized, returns `Ok(&mut value)`.
500 /// - If uninitialized, awaits `f(param)`:
501 /// - On `Ok(value)`, initializes the cell and returns `Ok(&mut value)`.
502 /// - On `Err(e)`, returns `Err(e)` and leaves the cell uninitialized.
503 ///
504 /// Requires exclusive access (`&mut self`), so it never blocks (initialization happens inline).
505 pub async fn get_mut_or_try_init_async<F, Fut, E>(&mut self, f: F) -> Result<&mut T, E>
506 where
507 F: FnOnce(&P) -> Fut,
508 Fut: Future<Output = Result<T, E>>,
509 {
510 if let Some(guard) = self.lock.try_lock() {
511 // We got the lock. Try to initialize.
512 unsafe {
513 let edit = EditSanitizer::new(&self.value, guard);
514 let value = f(edit.ref_parameter()).await?;
515 edit.commit(value);
516 }
517 }
518
519 // SAFETY: The cell is guaranteed to be initialized now (or we returned Err),
520 // and we have exclusive access.
521 Ok(unsafe { self.get_unchecked_mut() })
522 }
523
524 // --- Internal Initialization Helpers ---
525
526 /// Cold path for `get_or_init_async`. Acquires lock asynchronously and awaits initializer.
527 #[cold]
528 async fn initialize_async<F, Fut>(&self, f: F)
529 where
530 F: FnOnce(&P) -> Fut,
531 Fut: Future<Output = T>,
532 {
533 let Some(guard) = self.lock.lock_async().await else {
534 return; // Another task initialized it while we waited
535 };
536 // SAFETY: We hold the lock, exclusive access to initialize the value.
537 unsafe {
538 let edit = EditSanitizer::new(&self.value, guard);
539 let value = f(edit.ref_parameter()).await;
540 edit.commit(value);
541 }
542 }
543
544 /// Cold path for `get_or_try_init_async`. Acquires lock asynchronously and awaits fallible initializer.
545 #[cold]
546 async fn try_initialize_async<Fn, Fut, E>(&self, f: Fn) -> Result<(), E>
547 where
548 Fn: FnOnce(&P) -> Fut,
549 Fut: Future<Output = Result<T, E>>,
550 {
551 let Some(guard) = self.lock.lock_async().await else {
552 return Ok(()); // Another task initialized it while we waited
553 };
554 unsafe {
555 let edit = EditSanitizer::new(&self.value, guard);
556 let value = f(edit.ref_parameter()).await?;
557 edit.commit(value);
558 }
559 Ok(())
560 }
561
562 /// Cold path for `get_or_init`. Acquires lock and calls initializer.
563 #[cold]
564 fn initialize<F>(&self, f: F)
565 where
566 F: FnOnce(P) -> T,
567 {
568 let Some(guard) = self.lock.lock() else {
569 return; // Another thread initialized it while we waited for the lock
570 };
571 // SAFETY: We hold the lock, exclusive access to initialize the value.
572 unsafe {
573 let mut edit = EditSanitizer::new(&self.value, guard);
574 let value = f(edit.take_parameter());
575 edit.commit(value);
576 }
577 }
578
579 /// Cold path for `get_or_try_init`. Acquires lock and calls fallible initializer.
580 #[cold]
581 fn try_initialize<F, E>(&self, f: F) -> Result<(), E>
582 where
583 F: FnOnce(&P) -> Result<T, E>,
584 {
585 let Some(guard) = self.lock.lock() else {
586 return Ok(()); // Another thread initialized it while we waited for the lock
587 };
588 unsafe {
589 let edit = EditSanitizer::new(&self.value, guard);
590 let value = f(edit.ref_parameter())?;
591 edit.commit(value);
592 }
593 Ok(())
594 }
595}
596
597// --- Trait Implementations ---
598
599impl<P, T> From<Option<T>> for TOnce<P, T>
600where
601 P: Default,
602{
603 /// Creates an initialized `TOnce` from `Some(value)` or an uninitialized one from `None` with a default parameter.
604 fn from(value: Option<T>) -> Self {
605 match value {
606 Some(value) => Self::with_value(value),
607 None => Self::new(P::default()),
608 }
609 }
610}
611
612impl<P, T> From<Result<T, P>> for TOnce<P, T> {
613 /// Creates an initialized `TOnce` from `Ok(value)` or an uninitialized one from `Err(param)` with the parameter.
614 fn from(value: Result<T, P>) -> Self {
615 match value {
616 Ok(value) => Self::with_value(value),
617 Err(param) => Self::new(param),
618 }
619 }
620}
621
622// SAFETY:
623// `&TOnce<P, T>` is `Sync` if `&T` is `Sync` (requiring `T: Sync`)
624// and if the initialization mechanism is thread-safe (which it is).
625// `T: Send` is also required because a value provided by one thread
626// might be read or dropped by another.
627// `P: Sync` is required because the parameter might be accessed by multiple threads.
628unsafe impl<P: Sync + Send, T: Send> Sync for TOnce<P, T> {}
629// SAFETY:
630// `TOnce<P, T>` is `Send` if both `P` and `T` are `Send`, as the ownership of both
631// can be transferred across threads via initialization or `take()`.
632unsafe impl<P: Send, T: Send> Send for TOnce<P, T> {}
633
634impl<P: Default, T> Default for TOnce<P, T> {
635 /// Creates a new, uninitialized `TOnce` cell with default parameter.
636 #[inline]
637 fn default() -> Self {
638 Self::new(P::default())
639 }
640}
641
642impl<P, T: fmt::Display> fmt::Display for TOnce<P, T> {
643 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
644 match self.get() {
645 Some(v) => fmt::Display::fmt(v, f),
646 None => f.write_str("<uninit>"),
647 }
648 }
649}
650
651impl<P, T: fmt::Debug> fmt::Debug for TOnce<P, T> {
652 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653 let mut d = f.debug_tuple("Once");
654 match self.get() {
655 Some(v) => d.field(v),
656 None => d.field(&format_args!("<uninit>")),
657 };
658 d.finish()
659 }
660}
661
662impl<P: Clone, T: Clone> Clone for TOnce<P, T> {
663 /// Clones the `TOnce` cell.
664 ///
665 /// If the original cell is initialized, the clone will be initialized
666 /// with a cloned value. If the original is uninitialized, the clone
667 /// will also be uninitialized with a cloned parameter.
668 #[inline]
669 fn clone(&self) -> Self {
670 if let Some(value) = self.get() {
671 Self::with_value(value.clone())
672 } else {
673 let Some(_guard) = self.lock.lock() else {
674 return Self::with_value(
675 self
676 .get()
677 .expect("is_done() was false but value is init")
678 .clone(),
679 );
680 };
681 Self::new(unsafe { (*(*self.value.get()).pending).clone() })
682 }
683 }
684}
685
686impl<T> From<T> for TOnce<(), T> {
687 /// Creates a new, initialized `TOnce` cell from the given value.
688 #[inline]
689 fn from(value: T) -> Self {
690 Self::with_value(value)
691 }
692}
693
694impl<P, T: PartialEq> PartialEq for TOnce<P, T> {
695 /// Checks if two `TOnce` cells are equal.
696 ///
697 /// They are equal if both are uninitialized, or if both are initialized
698 /// and their contained values are equal according to `PartialEq`.
699 #[inline]
700 fn eq(&self, other: &Self) -> bool {
701 self.get() == other.get()
702 }
703}
704
705impl<P, T: Eq> Eq for TOnce<P, T> {}
706
707impl<P, T> Drop for TOnce<P, T> {
708 #[inline]
709 fn drop(&mut self) {
710 unsafe {
711 if self.is_done() {
712 self.value.get_mut().drop_init();
713 } else {
714 self.value.get_mut().drop_pending();
715 }
716 }
717 }
718}