use alloc::vec::Vec;
use alloc::{alloc::Layout, boxed::Box};
use core::convert::TryFrom;
use core::iter::FromIterator;
use core::marker::PhantomData;
use core::mem::{ManuallyDrop, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::ptr::{self, addr_of_mut, NonNull};
use core::sync::atomic::AtomicUsize;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::iterator_as_exact_size_iterator::IteratorAsExactSizeIterator;
use crate::HeaderSlice;
use super::{Arc, ArcInner};
#[repr(transparent)]
pub struct UniqueArc<T: ?Sized>(Arc<T>);
unsafe impl<T: ?Sized + Send> Send for UniqueArc<T> {}
unsafe impl<T: ?Sized + Sync> Sync for UniqueArc<T> {}
impl<T> UniqueArc<T> {
#[inline]
pub fn new(data: T) -> Self {
UniqueArc(Arc::new(data))
}
#[inline]
pub fn new_uninit() -> UniqueArc<MaybeUninit<T>> {
unsafe {
let layout = Layout::new::<ArcInner<MaybeUninit<T>>>();
let ptr = alloc::alloc::alloc(layout);
let mut p = NonNull::new(ptr)
.unwrap_or_else(|| alloc::alloc::handle_alloc_error(layout))
.cast::<ArcInner<MaybeUninit<T>>>();
ptr::write(&mut p.as_mut().count, AtomicUsize::new(1));
UniqueArc(Arc {
p,
phantom: PhantomData,
})
}
}
pub fn into_inner(this: Self) -> T {
let this = ManuallyDrop::new(this.0);
debug_assert!(
this.is_unique(),
"attempted to call `.into_inner()` on a `UniqueArc` with a non-zero ref count",
);
unsafe { Box::from_raw(this.ptr()).data }
}
}
impl<T: ?Sized> UniqueArc<T> {
#[inline]
pub fn shareable(self) -> Arc<T> {
self.0
}
pub(crate) unsafe fn from_arc(arc: Arc<T>) -> Self {
debug_assert_eq!(Arc::count(&arc), 1);
Self(arc)
}
pub(crate) unsafe fn from_arc_ref(arc: &mut Arc<T>) -> &mut Self {
debug_assert_eq!(Arc::count(arc), 1);
&mut *(arc as *mut Arc<T> as *mut UniqueArc<T>)
}
}
impl<T> UniqueArc<MaybeUninit<T>> {
pub fn write(&mut self, val: T) -> &mut T {
unsafe {
let ptr = self.as_mut_ptr() as *mut T;
ptr.write(val);
&mut *ptr
}
}
pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit<T> {
unsafe { &mut (*self.0.ptr()).data }
}
#[inline]
pub unsafe fn assume_init(this: Self) -> UniqueArc<T> {
UniqueArc(Arc {
p: ManuallyDrop::new(this).0.p.cast(),
phantom: PhantomData,
})
}
}
impl<T> UniqueArc<[MaybeUninit<T>]> {
pub fn new_uninit_slice(len: usize) -> Self {
let arc: Arc<HeaderSlice<(), [MaybeUninit<T>]>> =
UniqueArc::from_header_and_uninit_slice((), len).0;
let arc: Arc<[MaybeUninit<T>]> = arc.into();
UniqueArc(arc)
}
#[inline]
pub unsafe fn assume_init_slice(Self(this): Self) -> UniqueArc<[T]> {
UniqueArc(this.assume_init())
}
}
impl<H, T> UniqueArc<HeaderSlice<H, [MaybeUninit<T>]>> {
#[inline]
pub fn from_header_and_uninit_slice(header: H, len: usize) -> Self {
let inner = Arc::<HeaderSlice<H, [MaybeUninit<T>]>>::allocate_for_header_and_slice(len);
unsafe {
let dst = addr_of_mut!((*inner.as_ptr()).data.header);
ptr::write(dst, header);
}
Self(Arc {
p: inner,
phantom: PhantomData,
})
}
#[inline]
pub unsafe fn assume_init_slice_with_header(self) -> UniqueArc<HeaderSlice<H, [T]>> {
unsafe { core::mem::transmute(self) }
}
}
impl<T: ?Sized> TryFrom<Arc<T>> for UniqueArc<T> {
type Error = Arc<T>;
fn try_from(arc: Arc<T>) -> Result<Self, Self::Error> {
Arc::try_unique(arc)
}
}
impl<T: ?Sized> Deref for UniqueArc<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.0
}
}
impl<T: ?Sized> DerefMut for UniqueArc<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut (*self.0.ptr()).data }
}
}
impl<A> FromIterator<A> for UniqueArc<[A]> {
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
let iter = iter.into_iter();
let (lower, upper) = iter.size_hint();
let arc: Arc<[A]> = if Some(lower) == upper {
let iter = IteratorAsExactSizeIterator::new(iter);
Arc::from_header_and_iter((), iter).into()
} else {
let vec = iter.collect::<Vec<_>>();
Arc::from(vec)
};
unsafe { UniqueArc::from_arc(arc) }
}
}
#[cfg(feature = "unsize")]
unsafe impl<T, U: ?Sized> unsize::CoerciblePtr<U> for UniqueArc<T> {
type Pointee = T;
type Output = UniqueArc<U>;
fn as_sized_ptr(&mut self) -> *mut T {
unsize::CoerciblePtr::<U>::as_sized_ptr(&mut self.0)
}
unsafe fn replace_ptr(self, new: *mut U) -> UniqueArc<U> {
let inner = ManuallyDrop::new(self);
UniqueArc(ptr::read(&inner.0).replace_ptr(new))
}
}
#[cfg(feature = "serde")]
impl<'de, T: Deserialize<'de>> Deserialize<'de> for UniqueArc<T> {
fn deserialize<D>(deserializer: D) -> Result<UniqueArc<T>, D::Error>
where
D: ::serde::de::Deserializer<'de>,
{
T::deserialize(deserializer).map(UniqueArc::new)
}
}
#[cfg(feature = "serde")]
impl<T: Serialize> Serialize for UniqueArc<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ::serde::ser::Serializer,
{
(**self).serialize(serializer)
}
}
#[cfg(test)]
mod tests {
use crate::{Arc, HeaderSliceWithLengthUnchecked, HeaderWithLength, UniqueArc};
use core::{convert::TryFrom, mem::MaybeUninit};
#[test]
fn unique_into_inner() {
let unique = UniqueArc::new(10u64);
assert_eq!(UniqueArc::into_inner(unique), 10);
}
#[test]
fn try_from_arc() {
let x = Arc::new(10_000);
let y = x.clone();
assert!(UniqueArc::try_from(x).is_err());
assert_eq!(
UniqueArc::into_inner(UniqueArc::try_from(y).unwrap()),
10_000,
);
}
#[test]
#[allow(deprecated)]
fn maybeuninit_smoke() {
let mut arc: UniqueArc<MaybeUninit<_>> = UniqueArc::new_uninit();
arc.write(999);
let arc = unsafe { UniqueArc::assume_init(arc) };
assert_eq!(*arc, 999);
}
#[test]
fn from_header_and_uninit_slice() {
let mut uarc: UniqueArc<HeaderSliceWithLengthUnchecked<u8, MaybeUninit<u16>>> =
UniqueArc::from_header_and_uninit_slice(HeaderWithLength::new(1, 3), 3);
uarc.slice.fill(MaybeUninit::new(2));
let arc = unsafe { uarc.assume_init_slice_with_header() }.shareable();
assert!(arc.is_unique());
let arcs = [
arc.clone(),
arc.clone(),
arc.clone(),
arc.clone(),
arc.clone(),
];
let thin = Arc::into_thin(arc.clone());
assert_eq!(7, Arc::count(&arc));
assert_eq!(arc.header.header, 1);
assert_eq!(&arc.slice, [2, 2, 2]);
assert_eq!(thin.header.header, 1);
assert_eq!(&thin.slice, [2, 2, 2]);
drop(arcs);
drop(thin);
assert!(arc.is_unique());
assert_eq!(arc.header.header, 1);
assert_eq!(&arc.slice, [2, 2, 2]);
}
}