use core::{
fmt,
marker::PhantomData,
mem::ManuallyDrop,
ops::{Deref, DerefMut},
pin::Pin,
sync::atomic::{AtomicPtr, Ordering},
};
use crate::{
inner,
traits::{Bucket, KineticWell, PotentialWell, StrongWell, StrongWellMut, WeakWell, Well},
};
#[repr(transparent)]
pub struct AtomicOption<W: Well> {
ptr: inner::AtomicOption<Bucket<W>>,
marker: PhantomData<Option<W>>,
}
impl<W: Well> Default for AtomicOption<W> {
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn default() -> Self {
AtomicOption::none()
}
}
impl<W: Well> AtomicOption<W> {
#[inline]
pub fn none() -> AtomicOption<W> {
AtomicOption::new(None)
}
#[inline]
pub fn some(well: W) -> AtomicOption<W> {
AtomicOption::new(Some(well))
}
#[inline]
pub fn new(well: Option<W>) -> AtomicOption<W> {
AtomicOption {
ptr: inner::AtomicOption::new(well.map(Well::remove)),
marker: PhantomData,
}
}
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
pub unsafe fn as_raw_unchecked(&self) -> &AtomicPtr<Bucket<W>> {
self.ptr.as_raw()
}
#[inline]
pub fn swap(&self, well: W, ordering: Ordering) -> Option<W> {
let ptr = self.ptr.swap(Some(well.remove()), ordering)?;
Some(unsafe { Well::insert(ptr) })
}
#[inline]
pub fn take(&self, ordering: Ordering) -> Option<W> {
let ptr = self.ptr.swap(None, ordering)?;
Some(unsafe { Well::insert(ptr) })
}
#[inline]
pub fn insert(&self, well: W, success: Ordering, failure: Ordering) -> Result<(), W> {
let ptr = well.remove();
if self
.ptr
.compare_exchange(None, Some(ptr), success, failure)
.is_ok()
{
Ok(())
} else {
Err(unsafe { Well::insert(ptr) })
}
}
#[inline]
pub fn insert_weak(&self, well: W, success: Ordering, failure: Ordering) -> Result<(), W> {
let ptr = well.remove();
if self
.ptr
.compare_exchange_weak(None, Some(ptr), success, failure)
.is_ok()
{
Ok(())
} else {
Err(unsafe { Well::insert(ptr) })
}
}
}
impl<W: WeakWell> AtomicOption<W> {
#[inline]
pub fn try_load(&self, ordering: Ordering) -> Option<<W as WeakWell>::Access> {
let ptr = self.ptr.load(ordering)?;
let ptr = unsafe { ManuallyDrop::new(W::insert(ptr)) };
WeakWell::access(&*ptr)
}
}
impl<W: StrongWell> AtomicOption<W> {
#[inline]
pub fn load(&self, ordering: Ordering) -> Option<&Bucket<W>> {
let ptr = self.ptr.load(ordering)?;
Some(unsafe { ptr.as_ref() })
}
#[inline]
pub fn swap_get(&self, well: W, ordering: Ordering) -> (Option<W>, &Bucket<W>) {
let new = well.remove();
let old = self.ptr.swap(Some(new), ordering);
let new = unsafe { new.as_ref() };
(
old.map(|old| unsafe { Well::insert(old) }),
new,
)
}
#[inline]
pub fn insert_get(
&self,
well: W,
success: Ordering,
failure: Ordering,
) -> Result<&Bucket<W>, W> {
let new = well.remove();
if self
.ptr
.compare_exchange(None, Some(new), success, failure)
.is_ok()
{
Ok(unsafe { new.as_ref() })
} else {
Err(unsafe { Well::insert(new) })
}
}
#[inline]
pub fn insert_weak_get(
&self,
well: W,
success: Ordering,
failure: Ordering,
) -> Result<&Bucket<W>, W> {
let new = well.remove();
if self
.ptr
.compare_exchange_weak(None, Some(new), success, failure)
.is_ok()
{
Ok(unsafe { new.as_ref() })
} else {
Err(unsafe { Well::insert(new) })
}
}
}
impl<W: StrongWellMut + DerefMut<Target: Unpin>> AtomicOption<W> {
#[inline]
pub fn load_mut(&mut self) -> Option<&mut Bucket<W>> {
Some(unsafe { self.ptr.get_mut()?.as_mut() })
}
}
impl<W: StrongWellMut> AtomicOption<Pin<W>> {
#[inline]
pub fn load_mut_pinned(&mut self) -> Option<Pin<&mut <Pin<W> as Well>::Target>> {
Some(unsafe { Pin::new_unchecked(self.ptr.get_mut()?.as_mut()) })
}
}
impl<W: Well> From<W> for AtomicOption<W> {
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn from(well: W) -> Self {
AtomicOption::some(well)
}
}
impl<W: Well> From<Option<W>> for AtomicOption<W> {
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn from(well: Option<W>) -> Self {
AtomicOption::new(well)
}
}
impl<W: Well + Clone> AtomicOption<W> {
#[inline]
pub fn load_clone(&self, ordering: Ordering) -> Option<W> {
let ptr = self.ptr.load(ordering)?;
let ptr = unsafe { ManuallyDrop::new(W::insert(ptr)) };
Some((*ptr).clone())
}
}
impl<W: Well> Drop for AtomicOption<W> {
#[inline]
fn drop(&mut self) {
if let Some(ptr) = self.ptr.load_drop() {
unsafe {
drop(W::insert(ptr));
}
}
}
}
impl<W: Well + fmt::Debug> fmt::Debug for AtomicOption<W> {
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut tuple = f.debug_tuple("AtomicOption");
let Some(ptr) = self.ptr.load_debug() else {
return tuple.field(&None::<W>).finish();
};
let ptr = unsafe { ManuallyDrop::new(W::insert(ptr)) };
tuple.field(&Some(&*ptr)).finish()
}
}
#[repr(transparent)]
pub struct Atomic<W: Well>(inner::Atomic<Bucket<W>>);
impl<W: Well + Default> Default for Atomic<W> {
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn default() -> Self {
Atomic::new(Default::default())
}
}
impl<W: Well> Atomic<W> {
#[inline]
pub fn new(well: W) -> Atomic<W> {
Atomic(inner::Atomic::new(well.remove()))
}
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
pub unsafe fn as_raw_unchecked(&self) -> &AtomicPtr<Bucket<W>> {
self.0.as_raw()
}
#[inline]
pub fn swap(&self, well: W, ordering: Ordering) -> W {
let ptr = self.0.swap(well.remove(), ordering);
unsafe { Well::insert(ptr) }
}
}
impl<W: WeakWell> Atomic<W> {
#[inline]
pub fn try_load(&self, ordering: Ordering) -> Option<<W as WeakWell>::Access> {
let ptr = self.0.load(ordering);
let ptr = unsafe { ManuallyDrop::new(W::insert(ptr)) };
WeakWell::access(&*ptr)
}
}
impl<W: StrongWell + Deref<Target: Sized>> Atomic<W> {
#[inline]
pub fn load(&self, ordering: Ordering) -> &Bucket<W> {
let ptr = self.0.load(ordering);
unsafe { ptr.as_ref() }
}
#[inline]
pub fn swap_get(&self, well: W, ordering: Ordering) -> (W, &Bucket<W>) {
let new = well.remove();
let old = self.0.swap(new, ordering);
let new = unsafe { new.as_ref() };
(
unsafe { Well::insert(old) },
new,
)
}
}
impl<W: StrongWellMut + DerefMut<Target: Unpin>> Atomic<W> {
#[inline]
pub fn load_mut(&mut self) -> &mut Bucket<W> {
let mut ptr = self.0.get_mut();
unsafe { ptr.as_mut() }
}
}
impl<W: StrongWellMut> Atomic<Pin<W>> {
#[inline]
pub fn load_mut_pinned(&mut self) -> Pin<&mut <Pin<W> as Well>::Target> {
let mut ptr = self.0.get_mut();
unsafe { Pin::new_unchecked(ptr.as_mut()) }
}
}
impl<W: Well> From<W> for Atomic<W> {
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn from(well: W) -> Self {
Atomic::new(well)
}
}
impl<W: Well + Clone> Atomic<W> {
#[inline]
pub fn load_clone(&self, ordering: Ordering) -> W {
let ptr = self.0.load(ordering);
let ptr = unsafe { ManuallyDrop::new(W::insert(ptr)) };
(*ptr).clone()
}
}
impl<W: Well> Drop for Atomic<W> {
#[inline]
fn drop(&mut self) {
let ptr = self.0.load_drop();
unsafe {
drop(W::insert(ptr));
}
}
}
impl<W: Well + fmt::Debug> fmt::Debug for Atomic<W> {
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ptr = self.0.load_debug();
let ptr = unsafe { ManuallyDrop::new(W::insert(ptr)) };
f.debug_tuple("Atomic").field(&*ptr).finish()
}
}
#[repr(transparent)]
pub struct PotentialAtomicOption<T, W: PotentialWell>(AtomicOption<KineticWell<T, W>>);
impl<T, W: PotentialWell> Default for PotentialAtomicOption<T, W> {
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn default() -> Self {
PotentialAtomicOption::none()
}
}
impl<T, W: PotentialWell> PotentialAtomicOption<T, W> {
#[inline]
pub fn none() -> PotentialAtomicOption<T, W> {
PotentialAtomicOption::new(None)
}
#[inline]
pub fn some(well: KineticWell<T, W>) -> PotentialAtomicOption<T, W> {
PotentialAtomicOption::new(Some(well))
}
pub fn new(well: Option<KineticWell<T, W>>) -> PotentialAtomicOption<T, W> {
PotentialAtomicOption(AtomicOption::new(well))
}
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
pub unsafe fn as_raw_unchecked(&self) -> &AtomicPtr<T> {
unsafe { self.0.as_raw_unchecked() }
}
#[inline]
pub fn swap(&self, well: KineticWell<T, W>, ordering: Ordering) -> Option<KineticWell<T, W>> {
self.0.swap(well, ordering)
}
#[inline]
pub fn take(&self, ordering: Ordering) -> Option<KineticWell<T, W>> {
self.0.take(ordering)
}
#[inline]
pub fn insert(
&self,
well: KineticWell<T, W>,
success: Ordering,
failure: Ordering,
) -> Result<(), KineticWell<T, W>> {
self.0.insert(well, success, failure)
}
#[inline]
pub fn insert_weak(
&self,
well: KineticWell<T, W>,
success: Ordering,
failure: Ordering,
) -> Result<(), KineticWell<T, W>> {
self.0.insert_weak(well, success, failure)
}
}
impl<T, W: PotentialWell> PotentialAtomicOption<T, W>
where
KineticWell<T, W>: StrongWell + Deref<Target = T>,
{
#[inline]
pub fn load(&self, ordering: Ordering) -> Option<&T> {
self.0.load(ordering)
}
#[inline]
pub fn swap_get(
&self,
well: KineticWell<T, W>,
ordering: Ordering,
) -> (Option<KineticWell<T, W>>, &T) {
self.0.swap_get(well, ordering)
}
#[inline]
pub fn insert_get(
&self,
well: KineticWell<T, W>,
success: Ordering,
failure: Ordering,
) -> Result<&T, KineticWell<T, W>> {
self.0.insert_get(well, success, failure)
}
#[inline]
pub fn insert_weak_get(
&self,
well: KineticWell<T, W>,
success: Ordering,
failure: Ordering,
) -> Result<&T, KineticWell<T, W>> {
self.0.insert_weak_get(well, success, failure)
}
}
impl<T: Unpin, W: PotentialWell> PotentialAtomicOption<T, W>
where
KineticWell<T, W>: StrongWellMut + Deref<Target = T>,
{
#[inline]
pub fn load_mut(&mut self) -> Option<&mut T> {
self.0.load_mut()
}
}
impl<T, W: PotentialWell> PotentialAtomicOption<T, Pin<W>>
where
KineticWell<T, W>: StrongWellMut + Deref<Target = T>,
Pin<W>: PotentialWell<Well<T> = Pin<KineticWell<T, W>>>,
{
#[inline]
pub fn load_mut_pinned(&mut self) -> Option<Pin<&mut T>> {
self.0.load_mut_pinned()
}
}
impl<T, W: PotentialWell> From<Option<KineticWell<T, W>>> for PotentialAtomicOption<T, W> {
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn from(well: Option<KineticWell<T, W>>) -> Self {
match well {
Some(well) => PotentialAtomicOption::some(well),
None => PotentialAtomicOption::none(),
}
}
}
impl<T, W: PotentialWell> PotentialAtomicOption<T, W>
where
KineticWell<T, W>: Clone,
{
#[inline]
pub fn load_clone(&self, ordering: Ordering) -> Option<KineticWell<T, W>> {
self.0.load_clone(ordering)
}
}
impl<T, W: PotentialWell> fmt::Debug for PotentialAtomicOption<T, W>
where
KineticWell<T, W>: fmt::Debug,
{
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
#[repr(transparent)]
pub struct PotentialAtomic<T, W: PotentialWell>(Atomic<KineticWell<T, W>>);
impl<T: Default, W: PotentialWell> Default for PotentialAtomic<T, W>
where
KineticWell<T, W>: Default,
{
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn default() -> Self {
PotentialAtomic::new(Default::default())
}
}
impl<T, W: PotentialWell> PotentialAtomic<T, W> {
#[inline]
pub fn new(well: KineticWell<T, W>) -> PotentialAtomic<T, W> {
PotentialAtomic(Atomic::new(well))
}
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
pub unsafe fn as_raw_unchecked(&self) -> &AtomicPtr<T> {
unsafe { self.0.as_raw_unchecked() }
}
#[inline]
pub fn swap(&self, well: KineticWell<T, W>, ordering: Ordering) -> KineticWell<T, W> {
self.0.swap(well, ordering)
}
}
impl<T, W: PotentialWell> PotentialAtomic<T, W>
where
KineticWell<T, W>: StrongWell + Deref<Target = T>,
{
#[inline]
pub fn load(&self, ordering: Ordering) -> &T {
self.0.load(ordering)
}
#[inline]
pub fn swap_get(&self, well: KineticWell<T, W>, ordering: Ordering) -> (KineticWell<T, W>, &T) {
self.0.swap_get(well, ordering)
}
}
impl<T: Unpin, W: PotentialWell> PotentialAtomic<T, W>
where
KineticWell<T, W>: StrongWellMut + Deref<Target = T>,
{
#[inline]
pub fn load_mut(&mut self) -> &mut T {
self.0.load_mut()
}
}
impl<T, W: PotentialWell> PotentialAtomic<T, Pin<W>>
where
KineticWell<T, W>: StrongWellMut + Deref<Target = T>,
Pin<W>: PotentialWell<Well<T> = Pin<KineticWell<T, W>>>,
{
#[inline]
pub fn load_mut_pinned(&mut self) -> Pin<&mut T> {
self.0.load_mut_pinned()
}
}
impl<T, W: PotentialWell> PotentialAtomic<T, W>
where
KineticWell<T, W>: Clone,
{
#[inline]
pub fn load_clone(&self, ordering: Ordering) -> KineticWell<T, W> {
self.0.load_clone(ordering)
}
}
impl<T, W: PotentialWell> fmt::Debug for PotentialAtomic<T, W>
where
KineticWell<T, W>: fmt::Debug,
{
#[inline]
#[cfg_attr(any(coverage_nightly, feature = "nightly"), coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}