atomic_ptr_cell/
lib.rs

1//! # `atomic_ptr_cell`
2//! Safe `no_std` repr(transparent) wrapper for `AtomicPtr` and &`AtomicPtr` with an api similar to a cell.
3//!
4//! The crate requires an allocator using `extern crate alloc;` if used without std.
5//! # Example using owned `AtomicPtr`:
6//! ```rust
7//! use std::thread;
8//! use atomic_ptr_cell::*;
9//!
10//! static CELL: AtomicPointerCell<String> = AtomicPointerCell::new();
11//!
12//! fn test() {
13//!  CELL.set("Hello".to_string());
14//!  let guard = CELL.borrow().unwrap();
15//!  assert_eq!("Hello", guard.as_str());
16//!  let jh = thread::spawn(|| {
17//!     CELL.set("World".to_string());
18//!     let guard = CELL.borrow().unwrap();
19//!     assert!("Hello" == guard.as_str() || "World" == guard.as_str());
20//!     drop(guard);
21//!
22//!  });
23//!  drop(guard);
24//!
25//!  //This small example already has a surprising amount of possible outcomes :D
26//!
27//!  let Some(value) = CELL.take() else {
28//!     _= jh.join();
29//!     let value = CELL.take().unwrap();
30//!     assert!("Hello" == value.as_str() || "World" == value.as_str());
31//!     return;
32//!  };
33//!
34//!  assert!("Hello" == value.as_str() || "World" == value.as_str());
35//!  _= jh.join();
36//!  if let Some(value2) = CELL.take() {
37//!     //Depending on the order of execution CELL.take() may return None here.
38//!     assert_ne!(value, value2);
39//!  }
40//! }
41//! ```
42//!
43//! # Example using `&AtomicPtr` reference
44//! ```rust
45//! use atomic_ptr_cell::*;
46//! use std::ptr::null_mut;
47//! use std::sync::atomic::AtomicPtr;
48//! use std::thread;
49//!
50//! static CELL: AtomicPtr<String> = AtomicPtr::new(null_mut());
51//!
52//! fn test() {
53//!     // Safety: Caller must guarantee that the AtomicPtr never contains a non-null pointer that is not from Box::into_raw
54//!     let cell: AtomicPtrCell<String> = unsafe { AtomicPtrCell::new(&CELL) };
55//!     cell.set("Hello".to_string());
56//!     let guard = cell.borrow().unwrap();
57//!     assert_eq!("Hello", guard.as_str());
58//!     let jh = thread::spawn(move || {
59//!         //The AtomicPtrCell is copy as its layout is equivalent to &AtomicPtr
60//!         // making it easy to use in closures and threads.
61//!         // You just need to ensure the lifetime of &AtomicPtr outlives the scope.
62//!         // In this example the lifetime is static.
63//!         cell.set("World".to_string());
64//!         let guard = cell.borrow().unwrap();
65//!         assert!("Hello" == guard.as_str() || "World" == guard.as_str());
66//!         drop(guard);
67//!     });
68//!     drop(guard);
69//!
70//!     //This small example already has a surprising amount of possible outcomes :D
71//!
72//!     let Some(value) = cell.take() else {
73//!         _ = jh.join();
74//!         let value = cell.take().unwrap();
75//!         assert!("Hello" == value.as_str() || "World" == value.as_str());
76//!         return;
77//!     };
78//!
79//!     assert!("Hello" == value.as_str() || "World" == value.as_str());
80//!     _ = jh.join();
81//!     if let Some(value2) = cell.take() {
82//!         //Depending on the order of execution CELL.take() may return None here.
83//!         assert_ne!(value, value2);
84//!     }
85//! }
86//! ```
87#![no_std]
88#![deny(clippy::correctness)]
89#![deny(
90    clippy::perf,
91    clippy::complexity,
92    clippy::style,
93    clippy::nursery,
94    clippy::pedantic,
95    clippy::clone_on_ref_ptr,
96    clippy::decimal_literal_representation,
97    clippy::float_cmp_const,
98    clippy::missing_docs_in_private_items,
99    clippy::multiple_inherent_impl,
100    clippy::unwrap_used,
101    clippy::cargo_common_metadata,
102    clippy::used_underscore_binding
103)]
104
105#[cfg(target_has_atomic = "ptr")]
106pub use inner::*;
107
108/// inner module that contains the actual implementation.
109#[cfg(target_has_atomic = "ptr")]
110mod inner {
111    extern crate alloc;
112    use alloc::boxed::Box;
113    use core::fmt::{Debug, Formatter};
114    use core::ops::{Deref, DerefMut};
115    use core::ptr::null_mut;
116    use core::sync::atomic::Ordering::SeqCst;
117    use core::sync::atomic::{AtomicPtr, Ordering};
118
119    /// Result enum to indicate the outcomes of a `borrow_swap` operation.
120    pub enum BorrowSwapResult<'a, T: Sync + Send + 'static, E: Sync + Send + 'static> {
121        /// Borrow swap succeeded and the returned guard should be used.
122        BorrowSwapped(BorrowGuard<'a, T>),
123        /// Cell was empty when the borrow swap operation was performed
124        CellWasEmpty(E),
125    }
126
127    impl<T: Sync + Send + Debug + 'static, E: Sync + Send + Debug + 'static> Debug
128        for BorrowSwapResult<'_, T, E>
129    {
130        fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
131            match self {
132                BorrowSwapResult::BorrowSwapped(inner) => {
133                    f.write_fmt(format_args!("BorrowSwapped({inner:?})"))
134                }
135                BorrowSwapResult::CellWasEmpty(inner) => {
136                    f.write_fmt(format_args!("CellWasEmpty({inner:?})"))
137                }
138            }
139        }
140    }
141
142    impl<'a, T: Sync + Send + 'static, E: Sync + Send + 'static> BorrowSwapResult<'a, T, E> {
143        /// Unwraps the borrow guard
144        /// # Panics
145        /// if `CellWasEmpty`
146        pub fn unwrap(self) -> BorrowGuard<'a, T> {
147            match self {
148                BorrowSwapResult::BorrowSwapped(inner) => inner,
149                BorrowSwapResult::CellWasEmpty(_) => {
150                    panic!("unwrap called on BorrowSwapResult::CellWasEmpty()")
151                }
152            }
153        }
154
155        pub const fn is_ok(&self) -> bool {
156            matches!(self, BorrowSwapResult::BorrowSwapped(_))
157        }
158
159        pub const fn is_err(&self) -> bool {
160            matches!(self, BorrowSwapResult::CellWasEmpty(_))
161        }
162
163        /// Unwraps the value intended as replacement as result of a failed operation.
164        /// # Panics
165        /// if `BorrowSwapped`
166        pub fn unwrap_err(self) -> E {
167            match self {
168                BorrowSwapResult::BorrowSwapped(_) => {
169                    panic!("unwrap_err called on BorrowSwapResult::BorrowSwapped()")
170                }
171                BorrowSwapResult::CellWasEmpty(inner) => inner,
172            }
173        }
174
175        /// Maps the type in the `CellWasEmpty` case. Does nothing for `BorrowSwapped`.
176        pub fn map_err<X: Sync + Send + 'static>(
177            self,
178            f: impl FnOnce(E) -> X,
179        ) -> BorrowSwapResult<'a, T, X> {
180            match self {
181                BorrowSwapResult::BorrowSwapped(inner) => {
182                    BorrowSwapResult::BorrowSwapped::<T, X>(inner)
183                }
184                BorrowSwapResult::CellWasEmpty(inner) => BorrowSwapResult::CellWasEmpty(f(inner)),
185            }
186        }
187
188        /// Transforms this into a `core::Result` type.
189        /// # Errors
190        /// In case of `CellWasEmpty`
191        pub fn into_result(self) -> Result<BorrowGuard<'a, T>, E> {
192            match self {
193                BorrowSwapResult::BorrowSwapped(inner) => Ok(inner),
194                BorrowSwapResult::CellWasEmpty(inner) => Err(inner),
195            }
196        }
197    }
198
199    impl<'a, T: Sync + Send + 'static, E: Sync + Send + 'static> From<BorrowSwapResult<'a, T, E>>
200        for Result<BorrowGuard<'a, T>, E>
201    {
202        fn from(value: BorrowSwapResult<'a, T, E>) -> Self {
203            value.into_result()
204        }
205    }
206
207    pub enum PresentResult<T: Sync + Send + 'static> {
208        /// The cell had a value when the operation was performed
209        CellHadValue(T),
210        /// The cell did not have a value when the operation was performed.
211        CellWasEmpty(T),
212    }
213
214    impl<T: Sync + Send + Debug + 'static> Debug for PresentResult<T> {
215        fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
216            match self {
217                Self::CellHadValue(inner) => f.write_fmt(format_args!("CellHadValue({inner:?})")),
218                Self::CellWasEmpty(inner) => f.write_fmt(format_args!("CellWasEmpty({inner:?})")),
219            }
220        }
221    }
222
223    impl<T: Sync + Send + 'static> PresentResult<T> {
224        /// Unwraps the `PresentResult`, this call never fails but the information what type of value is referred to is lost.
225        pub fn unwrap(self) -> T {
226            match self {
227                Self::CellHadValue(inner) | Self::CellWasEmpty(inner) => inner,
228            }
229        }
230
231        /// Unwraps the `PresentResult::CellWasEmpty` result.
232        /// # Panics
233        /// if called on `PresentResult::CellHadValue`
234        pub fn unwrap_empty(self) -> T {
235            match self {
236                Self::CellHadValue(_) => {
237                    panic!("unwrap_empty() on PresentResult::CellHadValue")
238                }
239                Self::CellWasEmpty(inner) => inner,
240            }
241        }
242
243        /// Unwraps the `PresentResult::CellHadValue` result.
244        /// # Panics
245        /// if called on `PresentResult::CellWasEmpty`
246        pub fn unwrap_value(self) -> T {
247            match self {
248                Self::CellHadValue(inner) => inner,
249                Self::CellWasEmpty(_) => {
250                    panic!("unwrap_value() on PresentResult::CellWasEmpty")
251                }
252            }
253        }
254
255        /// Returns true if the result is a result from a Cell value.
256        pub const fn is_value(&self) -> bool {
257            matches!(self, Self::CellHadValue(_))
258        }
259
260        /// Returns true if the result contains data not from the cell because the cell was empty.
261        pub const fn is_empty(&self) -> bool {
262            matches!(self, Self::CellWasEmpty(_))
263        }
264
265        /// Maps the value in the `PresentResult`
266        pub fn map<X: Sync + Send + 'static>(self, f: impl FnOnce(T) -> X) -> PresentResult<X> {
267            match self {
268                Self::CellHadValue(inner) => PresentResult::CellHadValue(f(inner)),
269                Self::CellWasEmpty(inner) => PresentResult::CellWasEmpty(f(inner)),
270            }
271        }
272    }
273
274    ///
275    /// This is a helper struct that is guaranteed to have the exact same layout as `AtomicPtr<T>`.
276    ///
277    /// It offers high level safe manipulation functions to move data in and out of the pointer.
278    /// It offers boxed and non-boxed variants for operation.
279    /// In general all boxed operations are marginally faster because the "Box" is already on the heap
280    /// and the data must not be moved from the stack to the heap and vice versa.
281    ///
282    #[repr(transparent)]
283    #[derive(Debug)]
284    pub struct AtomicPointerCell<T: Sync + Send + 'static>(AtomicPtr<T>);
285
286    impl<T: Sync + Send + 'static> AtomicPointerCell<T> {
287        /// Constructs a new `AtomicPointerCell` without a value.
288        #[must_use]
289        pub const fn new() -> Self {
290            Self(AtomicPtr::new(null_mut()))
291        }
292
293        ///
294        /// # Safety
295        /// The ptr must contain 0 or a pointer created by `Box::into_raw`
296        /// Any external write to the pointer may also not violate this constraint
297        /// during the lifetime of the returned `AtomicPointerCell`.
298        #[must_use]
299        pub const unsafe fn from_ptr(ptr: AtomicPtr<T>) -> Self {
300            Self(ptr)
301        }
302
303        ///
304        /// # Safety
305        /// Every pointer in the slice must either be null or crated by `Box::into_raw` and be of type T.
306        /// Any external writes to the pointers may also not violate this constraint during the lifetime of the returned slice.
307        #[must_use]
308        pub const unsafe fn from_ptr_slice(value: &mut [*mut T]) -> &mut [Self] {
309            core::slice::from_raw_parts_mut(value.as_mut_ptr().cast::<Self>(), value.len())
310        }
311
312        ///
313        /// # Safety
314        /// Every `AtomicPtr` in the slice must either contain null or a pointer crated by `Box::into_raw` and be of type T.
315        /// Any external writes to the pointers may also not violate this constraint during the lifetime of the returned slice.
316        #[must_use]
317        pub const unsafe fn from_slice(value: &[AtomicPtr<T>]) -> &[Self] {
318            core::slice::from_raw_parts(value.as_ptr().cast::<Self>(), value.len())
319        }
320
321        /// Constructs a new `AtomicPointerCell` with a value.
322        #[must_use]
323        pub fn from_value(value: T) -> Self {
324            Self(AtomicPtr::new(Box::into_raw(Box::new(value))))
325        }
326
327        /// Constructs a new `AtomicPointerCell` with a boxed value.
328        #[must_use]
329        pub fn from_box(value: Box<T>) -> Self {
330            Self(AtomicPtr::new(Box::into_raw(value)))
331        }
332
333        /// Deconstructs this `AtomicPointerCell` into its raw `AtomicPtr`.
334        #[must_use]
335        pub const fn into_inner(self) -> AtomicPtr<T> {
336            self.0
337        }
338
339        /// Gets an unowned `AtomicPtrCell`.
340        /// It is subject to the lifetime of this `AtomicPointerCell`,
341        /// but otherwise refers to the same underlying `AtomicPtr`
342        ///
343        /// The layout of the `AtomicPtrCell` is guaranteed to be equivalent to that of a `&AtomicPtr`.
344        #[must_use]
345        pub const fn as_ptr_cell(&self) -> AtomicPtrCell<'_, T> {
346            AtomicPtrCell::from_internal(&self.0)
347        }
348
349        /// returns true if the cell is currently observed to be empty according to the given ordering.
350        pub fn is_empty(&self) -> bool {
351            self.as_ptr_cell().is_empty()
352        }
353
354        /// Atomically swap the current value with the given value.
355        /// returns None if the pointer was null
356        pub fn swap(&self, value: T) -> Option<T> {
357            self.as_ptr_cell().swap(value)
358        }
359
360        /// Atomically swap the current value with the given value.
361        /// returns None if the pointer was null
362        pub fn swap_boxed(&self, value: Box<T>) -> Option<Box<T>> {
363            self.as_ptr_cell().swap_boxed(value)
364        }
365
366        /// Atomically Take T out of the pointer or return None if the pointer was null.
367        pub fn take(&self) -> Option<T> {
368            self.take_boxed().map(|v| *v)
369        }
370
371        /// Atomically Take T out of the pointer or return None if the pointer was null.
372        pub fn take_boxed(&self) -> Option<Box<T>> {
373            self.as_ptr_cell().take_boxed()
374        }
375
376        /// Atomically sets the value of the pointer to T.
377        /// This fn is also guaranteed to invoke the Drop
378        /// of a previous value if one was present before returning.
379        pub fn set(&self, value: T) {
380            self.as_ptr_cell().set(value);
381        }
382
383        /// Atomically sets the value of the pointer to T.
384        /// This fn is also guaranteed to invoke the Drop
385        /// of a previous value if one was present before returning.
386        pub fn set_boxed(&self, value: Box<T>) {
387            self.as_ptr_cell().set_boxed(value);
388        }
389
390        /// Atomically sets the value in the cell if the cell was empty.
391        /// If the Cell was not empty then Some is returned containing
392        /// the value that was intended to be written into the cell.
393        pub fn set_if_absent(&self, value: T) -> Option<T> {
394            self.as_ptr_cell().set_if_absent(value)
395        }
396
397        /// Atomically sets the value in the cell if the cell was empty.
398        /// If the Cell was not empty then Some is returned containing
399        /// the value that was intended to be written into the cell.
400        pub fn set_if_absent_boxed(&self, value: Box<T>) -> Option<Box<T>> {
401            self.as_ptr_cell().set_if_absent_boxed(value)
402        }
403
404        /// Atomically replaces the value in a Cell if the Cell is not empty.
405        /// If the cell is empty then this fn does not modify the cell and instead returns `PresetResult::CellWasEmpty` with the value that would have been stored in the cell otherwise.
406        /// If the cell was not empty then `PresetResult::WasPresent` is returned containing the value that was atomically replaced.
407        pub fn set_if_present(&self, value: T) -> PresentResult<T> {
408            self.as_ptr_cell().set_if_present(value)
409        }
410
411        /// Atomically replaces the value in a Cell if the Cell is not empty.
412        /// If the cell is empty then this fn does not modify the cell and instead returns `PresetResult::CellWasEmpty` with the value that would have been stored in the cell otherwise.
413        /// If the cell was not empty then `PresetResult::WasPresent` is returned containing the value that was atomically replaced.
414        pub fn set_if_present_boxed(&self, value: Box<T>) -> PresentResult<Box<T>> {
415            self.as_ptr_cell().set_if_present_boxed(value)
416        }
417
418        /// Moves the value out of the cell and put it in a `BorrowGuard`.
419        /// The returned guard Deref's the value.
420        /// Once the guard is dropped the value is moved back
421        /// into the cell if it is empty at that time.
422        /// Otherwise, dropping the guard drops the value.
423        pub fn borrow(&self) -> Option<BorrowGuard<'_, T>> {
424            self.as_ptr_cell().borrow()
425        }
426
427        /// Moves the value out of the cell and put it in a `BorrowGuard`.
428        /// The returned guard Deref's the value.
429        /// Once the guard is dropped the value is moved back
430        /// into the cell if it is empty at that time.
431        /// Otherwise, dropping the guard drops the value.
432        ///
433        /// If the cell is empty this fn calls the `FnOnce` to create a value to put into the `BorrowGuard`.
434        /// The value will be moved into the Cell once the
435        ///
436        pub fn borrow_or_else(&self, f: impl FnOnce() -> T) -> BorrowGuard<'_, T> {
437            self.as_ptr_cell().borrow_or_else(f)
438        }
439
440        /// Moves the value out of the cell and put it in a `BorrowGuard`.
441        /// The returned guard Deref's the value.
442        /// Once the guard is dropped the value is moved back
443        /// into the cell if it is empty at that time.
444        /// Otherwise, dropping the guard drops the value.
445        ///
446        /// If the cell is empty this fn calls the `FnOnce` to create a value to put into the `BorrowGuard`.
447        /// The value will be moved into the Cell once the
448        ///
449        pub fn borrow_or_else_boxed(&self, f: impl FnOnce() -> Box<T>) -> BorrowGuard<'_, T> {
450            self.as_ptr_cell().borrow_or_else_boxed(f)
451        }
452
453        /// Borrows the current value in the cell and in doing so atomically replaces the value with the given value.
454        /// If the cell was empty then this fn returns `CellWasEmpty` with value that should
455        /// have been stored in the cell and the cell is left empty.
456        pub fn borrow_swap(&self, value: T) -> BorrowSwapResult<T, T> {
457            self.as_ptr_cell().borrow_swap(value)
458        }
459
460        /// Borrows the current value in the cell and in doing so atomically replaces the value with the given value.
461        /// If the cell was empty then this fn returns `CellWasEmpty` with value that should
462        /// have been stored in the cell and the cell is left empty.
463        pub fn borrow_swap_boxed(&self, value: Box<T>) -> BorrowSwapResult<T, Box<T>> {
464            self.as_ptr_cell().borrow_swap_boxed(value)
465        }
466
467        ///
468        /// Get the inner ptr.
469        /// # Safety
470        /// The caller must guarantee that no values other than pointers created by `Box::into_raw` or null can be read from the underlying pointer.
471        /// The easiest way to guarantee this is to never write those "garbage" values into the pointer.
472        ///
473        /// In addition, the caller can assume that any invocation of any fn of this crate in any thread may move the value behind the pointer or drop it making the pointer dangling.
474        /// If the caller wants to get a "ref" to the underlying value of the pointer then it must therefore ensure that no such calls occur
475        ///
476        pub const unsafe fn inner(&self) -> &AtomicPtr<T> {
477            &self.0
478        }
479
480        ///
481        /// Get the inner ptr as a mut.
482        ///
483        /// # Safety
484        /// The caller must guarantee that no values other than pointers created by `Box::into_raw` or null can be read from the underlying pointer.
485        /// The easiest way to guarantee this is to never write those "garbage" values into the pointer.
486        ///
487        /// In addition, the caller can assume that any invocation of any fn of this crate may move the value behind the pointer or drop it making the pointer dangling.
488        /// If the caller wants to get a "ref" to the underlying value of the pointer then it must therefore ensure that no such calls occur
489        ///
490        pub const unsafe fn inner_mut(&mut self) -> &mut AtomicPtr<T> {
491            &mut self.0
492        }
493    }
494
495    ///
496    /// This is a helper struct that is guaranteed to have the exact same layout as `&AtomicPtr<T>`.
497    ///
498    /// It offers high level safe manipulation functions to move data in and out of the pointer.
499    /// It offers boxed and non-boxed variants for operation.
500    /// In general all boxed operations are marginally faster because the "Box" is already on the heap
501    /// and the data must not be moved from the stack to the heap and vice versa.
502    ///
503    #[repr(transparent)]
504    #[derive(Debug)]
505    pub struct AtomicPtrCell<'a, T: Sync + Send + 'static>(&'a AtomicPtr<T>);
506
507    impl<'a, T: Sync + Send + 'static> AtomicPtrCell<'a, T> {
508        ///
509        /// Construct a new non-owned `AtomicPtrCell` from a given `AtomicPtr`.
510        /// # Safety
511        /// `AtomicPtr` must contain null or a pointer made by `Box<T>::into_raw`
512        ///
513        pub const unsafe fn new(value: &'a AtomicPtr<T>) -> Self {
514            Self(value)
515        }
516
517        ///
518        /// # Safety
519        /// The pointer must contain null or a pointer made by `Box<T>::into_raw`
520        /// Pointer must be valid for the lifetime `'a`.
521        ///
522        pub const unsafe fn from_ptr(value: *mut *mut T) -> Self {
523            Self(AtomicPtr::from_ptr(value))
524        }
525
526        ///
527        /// # Safety
528        /// Each `AtomicPtr` in the slice must either contain null or a pointer made by `Box<T>::into_raw`
529        ///
530        pub const unsafe fn from_slice<'b>(value: &'b [&'a AtomicPtr<T>]) -> &'b [Self] {
531            core::slice::from_raw_parts(value.as_ptr().cast::<AtomicPtrCell<T>>(), value.len())
532        }
533
534        ///
535        /// # Safety
536        /// The slice must not contain null elements.
537        /// Each Pointer in the slice must point to a pointer which is either null or was made by `Box<T>::into_raw`
538        /// The pointers must be valid for the lifetime 'a.
539        ///
540        pub const unsafe fn from_ptr_slice(value: &[*mut *mut T]) -> &[Self] {
541            core::slice::from_raw_parts(value.as_ptr().cast::<AtomicPtrCell<T>>(), value.len())
542        }
543
544        /// Internal constructor where safety guarantees can be made.
545        pub(crate) const fn from_internal(value: &'a AtomicPtr<T>) -> Self {
546            Self(value)
547        }
548
549        /// Helper fn to turn the moved raw ptr into a Box if it was not null.
550        fn inner_from_raw(value: *mut T) -> Option<Box<T>> {
551            if value.is_null() {
552                return None;
553            }
554
555            Some(unsafe { Box::from_raw(value) })
556        }
557
558        /// returns true if the cell is currently observed to be empty according to the given ordering.
559        #[must_use]
560        pub fn is_empty(&self) -> bool {
561            self.0.load(SeqCst).is_null()
562        }
563
564        /// Atomically swaps the value out of the cell returning the previous value if there was one.
565        #[must_use]
566        pub fn swap(&self, value: T) -> Option<T> {
567            self.swap_boxed(Box::new(value)).map(|v| *v)
568        }
569
570        /// Atomically swaps the value out of the cell returning the previous value if there was one.
571        #[must_use]
572        pub fn swap_boxed(&self, value: Box<T>) -> Option<Box<T>> {
573            Self::inner_from_raw(self.0.swap(Box::into_raw(value), SeqCst))
574        }
575
576        /// Atomically moves the value out of the cell leaving it empty.
577        /// returns none if the cell was already empty.
578        #[must_use = "use take_boxed() instead if you want to just discard the value as it is just slightly faster."]
579        pub fn take(&self) -> Option<T> {
580            self.take_boxed().map(|v| *v)
581        }
582
583        /// Atomically moves the value out of the cell leaving it empty.
584        /// returns none if the cell was already empty.
585        #[allow(clippy::must_use_candidate)]
586        pub fn take_boxed(&self) -> Option<Box<T>> {
587            Self::inner_from_raw(self.0.swap(null_mut(), SeqCst))
588        }
589
590        /// Atomically sets the value in the cell.
591        /// If the cell was not empty then the previous value is dropped in the current thread before this fn returns.
592        pub fn set(&self, value: T) {
593            self.set_boxed(Box::new(value));
594        }
595
596        /// Atomically sets the value in the cell.
597        /// If the cell was not empty then the previous value is dropped in the current thread before this fn returns.
598        pub fn set_boxed(&self, value: Box<T>) {
599            _ = self.swap_boxed(value);
600        }
601
602        /// Atomically sets the value in the cell if the cell was empty.
603        /// If the Cell was not empty then Some is returned containing
604        /// the value that was intended to be written into the cell.
605        #[allow(clippy::must_use_candidate)]
606        pub fn set_if_absent(&self, value: T) -> Option<T> {
607            self.set_if_absent_boxed(Box::new(value)).map(|v| *v)
608        }
609
610        /// Atomically sets the value in the cell if the cell was empty.
611        /// If the Cell was not empty then Some is returned containing
612        /// the value that was intended to be written into the cell.
613        #[allow(clippy::must_use_candidate)]
614        pub fn set_if_absent_boxed(&self, value: Box<T>) -> Option<Box<T>> {
615            let raw = Box::into_raw(value);
616            if self
617                .0
618                .compare_exchange(null_mut(), raw, SeqCst, Ordering::Acquire)
619                .is_err()
620            {
621                return Some(unsafe { Box::from_raw(raw) });
622            };
623
624            None
625        }
626
627        /// Atomically replaces the value in a Cell if the Cell is not empty.
628        /// If the cell is empty then this fn does not modify the cell and instead returns `PresetResult::CellWasEmpty` with the value that would have been stored in the cell otherwise.
629        /// If the cell was not empty then `PresetResult::WasPresent` is returned containing the value that was atomically replaced.
630        #[allow(clippy::must_use_candidate)]
631        pub fn set_if_present(&self, value: T) -> PresentResult<T> {
632            self.set_if_present_boxed(Box::new(value)).map(|v| *v)
633        }
634
635        /// Atomically replaces the value in a Cell if the Cell is not empty.
636        /// If the cell is empty then this fn does not modify the cell and instead returns `PresetResult::CellWasEmpty` with the value that would have been stored in the cell otherwise.
637        /// If the cell was not empty then `PresetResult::WasPresent` is returned containing the value that was atomically replaced.
638        #[allow(clippy::must_use_candidate)]
639        pub fn set_if_present_boxed(&self, value: Box<T>) -> PresentResult<Box<T>> {
640            let raw = Box::into_raw(value);
641
642            let mut cur = self.0.load(SeqCst);
643            loop {
644                if cur.is_null() {
645                    return PresentResult::CellWasEmpty(unsafe { Box::from_raw(raw) });
646                }
647
648                cur = match self.0.compare_exchange(cur, raw, SeqCst, SeqCst) {
649                    Ok(actual) => {
650                        return PresentResult::CellHadValue(unsafe { Box::from_raw(actual) })
651                    }
652                    Err(actual) => actual,
653                };
654            }
655        }
656
657        /// Moves the value out of the cell and put it in a `BorrowGuard`.
658        /// The returned guard Deref's the value.
659        /// Once the guard is dropped the value is moved back
660        /// into the cell if it is empty at that time.
661        /// Otherwise, dropping the guard drops the value.
662        ///
663        /// This fn returns none if the cell is empty.
664        #[must_use]
665        pub fn borrow(&self) -> Option<BorrowGuard<'a, T>> {
666            self.take_boxed().map(|b| BorrowGuard(Some(b), self.0))
667        }
668
669        /// Moves the value out of the cell and put it in a `BorrowGuard`.
670        /// The returned guard Deref's the value.
671        /// Once the guard is dropped the value is moved back
672        /// into the cell if it is empty at that time.
673        /// Otherwise, dropping the guard drops the value.
674        ///
675        /// If the cell is empty this fn calls the `FnOnce` to create a value to put into the `BorrowGuard`.
676        /// The value will be moved into the Cell once the
677        ///
678        pub fn borrow_or_else(&self, f: impl FnOnce() -> T) -> BorrowGuard<'a, T> {
679            self.borrow_or_else_boxed(|| Box::new(f()))
680        }
681
682        /// Moves the value out of the cell and put it in a `BorrowGuard`.
683        /// The returned guard Deref's the value.
684        /// Once the guard is dropped the value is moved back
685        /// into the cell if it is empty at that time.
686        /// Otherwise, dropping the guard drops the value.
687        ///
688        /// If the cell is empty this fn calls the `FnOnce` to create a value to put into the `BorrowGuard`.
689        /// The value will be moved into the Cell once the
690        ///
691        pub fn borrow_or_else_boxed(&self, f: impl FnOnce() -> Box<T>) -> BorrowGuard<'a, T> {
692            self.borrow()
693                .unwrap_or_else(|| BorrowGuard(Some(f()), self.0))
694        }
695
696        /// Borrows the current value in the cell and in doing so atomically replaces the value with the given value.
697        /// If the cell was empty then this fn returns `CellWasEmpty` with value that should
698        /// have been stored in the cell and the cell is left empty.
699        pub fn borrow_swap(&self, value: T) -> BorrowSwapResult<'a, T, T> {
700            self.borrow_swap_boxed(Box::new(value)).map_err(|v| *v)
701        }
702
703        /// Borrows the current value in the cell and in doing so atomically replaces the value with the given value.
704        /// If the cell was empty then this fn returns `CellWasEmpty` with value that should
705        /// have been stored in the cell and the cell is left empty.
706        #[must_use]
707        pub fn borrow_swap_boxed(&self, value: Box<T>) -> BorrowSwapResult<'a, T, Box<T>> {
708            match self.set_if_present_boxed(value) {
709                PresentResult::CellHadValue(value) => {
710                    BorrowSwapResult::BorrowSwapped(BorrowGuard(Some(value), self.0))
711                }
712                PresentResult::CellWasEmpty(np) => BorrowSwapResult::CellWasEmpty(np),
713            }
714        }
715
716        ///
717        /// Get the inner ptr.
718        /// # Safety
719        /// The caller must guarantee that no values other than pointers created by `Box::into_raw` or null can be read from the underlying pointer.
720        /// The easiest way to guarantee this is to never write those "garbage" values into the pointer.
721        ///
722        /// In addition, the caller can assume that any invocation of any fn of this crate in any thread may move the value behind the pointer or drop it making the pointer dangling.
723        /// If the caller wants to get a "ref" to the underlying value of the pointer then it must therefore ensure that no such calls occur
724        #[must_use]
725        pub const unsafe fn inner(&self) -> &'a AtomicPtr<T> {
726            self.0
727        }
728    }
729
730    /// Borrow guard of a `AtomicCell`. Once this cell is dropped the value is moved back into the cell
731    /// if the cell is empty at that time.
732    ///
733    /// This guard has no knowledge of what is happening to the cell in the meantime.
734    /// It is entirely possible that during the lifetime of the guard the cell is filled and emptied multiple times.
735    /// This has no effect on the behavior of the guard.
736    /// The guard and its fn's only care about the state it can atomically observe when an action occurs, not what happened in the meantime.
737    /// Essentially it does not solve the ABA problem and cannot be used for use cases where solving the ABA Problem is required.
738    ///
739    pub struct BorrowGuard<'a, T: Sync + Send + 'static>(Option<Box<T>>, &'a AtomicPtr<T>);
740    impl<T: Sync + Send + 'static> BorrowGuard<'_, T> {
741        /// Drop the borrow guard while discarding the value
742        pub fn discard(mut self) {
743            self.0 = None;
744            //DROP IT
745        }
746
747        /// Drop the borrow guard and discard the value if the cell is empty.
748        pub fn discard_if_absent(mut self) {
749            _ = AtomicPtrCell::from_internal(self.1)
750                .set_if_present_boxed(unsafe { self.0.take().unwrap_unchecked() });
751            self.0 = None;
752            //DROP IT
753        }
754
755        /// Try to swap the borrowed value with the value in the cell.
756        /// Returns true if the value was swapped. false if the cell was empty.
757        pub fn try_swap(&mut self) -> bool {
758            let boxed = unsafe { self.0.take().unwrap_unchecked() };
759            match AtomicPtrCell::from_internal(self.1).set_if_present_boxed(boxed) {
760                PresentResult::CellHadValue(bx) => {
761                    self.0 = Some(bx);
762                    true
763                }
764                PresentResult::CellWasEmpty(bx) => {
765                    self.0 = Some(bx);
766                    false
767                }
768            }
769        }
770
771        /// Drop the borrow guard and write the value back into the cell.
772        /// This may also drop the value in the cell that is replaced.
773        pub fn force(mut self) {
774            AtomicPtrCell::from_internal(self.1)
775                .set_boxed(unsafe { self.0.take().unwrap_unchecked() });
776            self.0 = None;
777            //DROP IT
778        }
779
780        /// Drops the borrow guard if the value can be written back into the cell (i.e. the cell was empty)
781        /// Returns Some(self) if the cell was not empty.
782        #[allow(clippy::must_use_candidate)]
783        pub fn try_drop(mut self) -> Option<Self> {
784            if let Some(me) = AtomicPtrCell::from_internal(self.1)
785                .set_if_absent_boxed(unsafe { self.0.take().unwrap_unchecked() })
786            {
787                self.0 = Some(me);
788                return Some(self);
789            }
790
791            None
792        }
793
794        /// Drops the Borrow guard while yielding the inner value to the caller. The Cell is left untouched by this call.
795        #[must_use]
796        pub fn into_inner(mut self) -> T {
797            unsafe { *self.0.take().unwrap_unchecked() }
798        }
799
800        /// Drops the Borrow guard while yielding the inner value to the caller. The Cell is left untouched by this call.
801        #[must_use]
802        pub fn into_inner_box(mut self) -> Box<T> {
803            unsafe { self.0.take().unwrap_unchecked() }
804        }
805    }
806
807    impl<T: Sync + Send + 'static> Drop for BorrowGuard<'_, T> {
808        fn drop(&mut self) {
809            if let Some(boxed) = self.0.take() {
810                _ = AtomicPtrCell::from_internal(self.1).set_if_absent_boxed(boxed);
811            }
812        }
813    }
814
815    impl<T: Sync + Send + 'static> Deref for BorrowGuard<'_, T> {
816        type Target = T;
817
818        fn deref(&self) -> &Self::Target {
819            unsafe { self.0.as_ref().unwrap_unchecked() }
820        }
821    }
822
823    impl<T: Sync + Send + 'static> DerefMut for BorrowGuard<'_, T> {
824        fn deref_mut(&mut self) -> &mut Self::Target {
825            unsafe { self.0.as_mut().unwrap_unchecked() }
826        }
827    }
828
829    impl<T: Sync + Send + Debug + 'static> Debug for BorrowGuard<'_, T> {
830        fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
831            f.write_fmt(format_args!("BorrowGuard({:?}, {:?})", self.0, self.1))
832        }
833    }
834
835    impl<T: Sync + Send + 'static> From<T> for AtomicPointerCell<T> {
836        fn from(value: T) -> Self {
837            Self::from_value(value)
838        }
839    }
840
841    impl<T: Sync + Send + 'static> Default for AtomicPointerCell<T> {
842        fn default() -> Self {
843            Self::new()
844        }
845    }
846
847    impl<T: Sync + Send + 'static> From<AtomicPointerCell<T>> for AtomicPtr<T> {
848        fn from(value: AtomicPointerCell<T>) -> Self {
849            value.into_inner()
850        }
851    }
852
853    impl<'a, T: Sync + Send + 'static> From<&'a AtomicPointerCell<T>> for AtomicPtrCell<'a, T> {
854        fn from(value: &'a AtomicPointerCell<T>) -> Self {
855            value.as_ptr_cell()
856        }
857    }
858
859    impl<T: Sync + Send + 'static> Clone for AtomicPtrCell<'_, T> {
860        fn clone(&self) -> Self {
861            *self
862        }
863    }
864
865    impl<T: Sync + Send + 'static> Copy for AtomicPtrCell<'_, T> {}
866}