Struct UniqueArc

pub struct UniqueArc<T: ?Sized, A: Allocator = Global> { pub(in ::rcs::arc) ptr: NonNull<ArcInner<T>>, pub(in ::rcs::arc) _marker: PhantomData<ArcInner<T>>, pub(in ::rcs::arc) _marker2: PhantomData<*mut T>, pub(in ::rcs::arc) alloc: A }

A uniquely owned Arc.

This represents an Arc that is known to be uniquely owned -- that is, have exactly one strong reference. Multiple weak pointers can be created, but attempts to upgrade those to strong references will fail unless the UniqueArc they point to has been converted into a regular Arc.

Because it is uniquely owned, the contents of a UniqueArc can be freely mutated. A common use case is to have an object be mutable during its initialization phase but then have it become immutable and converted to a normal Arc.

This can be used as a flexible way to create cyclic data structures, as in the example below.

#![feature(unique_rc_arc)]
use std::sync::{Arc, Weak, UniqueArc};

struct Gadget {
    me: Weak<Gadget>,
}

fn create_gadget() -> Option<Arc<Gadget>> {
    let mut rc = UniqueArc::new(Gadget {
        me: Weak::new(),
    });
    rc.me = UniqueArc::downgrade(&rc);
    Some(UniqueArc::into_arc(rc))
}

create_gadget().unwrap();

An advantage of using UniqueArc over Arc::new_cyclic to build cyclic data structures is that Arc::new_cyclic's data_fn parameter cannot be async or return a Result. As shown in the previous example, UniqueArc allows for more flexibility in the construction of cyclic data, including fallible or async constructors.

Fields

ptr: NonNull<ArcInner<T>>
_marker: PhantomData<ArcInner<T>>
_marker2: PhantomData<*mut T>
alloc: A

Implementations

impl<T> UniqueArc<T, Global>

fn new(value: T) -> Self

Creates a new UniqueArc.

Weak references to this UniqueArc can be created with UniqueArc::downgrade. Upgrading these weak references will fail before the UniqueArc has been converted into an Arc. After converting the UniqueArc into an Arc, any weak references created beforehand will point to the new Arc.

fn try_new(value: T) -> Result<Self, AllocError>

Like new, but returns an error if the allocation fails, instead of calling handle_alloc_error.

impl<T, A: Allocator> UniqueArc<MaybeUninit<T>, A>

fn write(this: Self, value: T) -> UniqueArc<T, A>

Writes the value and converts to UniqueArc<T, A>.

This method converts similarly to assume_init but writes value into it before conversion, thus guaranteeing safety.

unsafe fn assume_init(self) -> UniqueArc<T, A>

Converts to UniqueArc<T, A>.

Safety

As with MaybeUninit::assume_init, it is up to the caller to guarantee that the value really is in an initialized state. Calling this when the content is not yet fully initialized causes immediate undefined behavior.

impl<T, A: Allocator> UniqueArc<T, A>

fn new_in(data: T, alloc: A) -> Self

Creates a new UniqueArc in the provided allocator.

Weak references to this UniqueArc can be created with UniqueArc::downgrade. Upgrading these weak references will fail before the UniqueArc has been converted into an Arc. After converting the UniqueArc into an Arc, any weak references created beforehand will point to the new Arc.

fn try_new_in(data: T, alloc: A) -> Result<Self, AllocError>

Like new_in, but returns an error if the allocation fails, instead of calling handle_alloc_error.

fn unwrap_with_allocator(this: Self) -> (T, A)

Consumes the UniqueArc, returning its wrapped value and allocator.

fn unwrap(this: Self) -> T

Consumes the UniqueArc, returning its wrapped value.

fn map<U>(this: Self, f: impl FnOnce(T) -> U) -> UniqueArc<U, A>

Maps the value in a UniqueArc, reusing the allocation if possible.

f is called on a reference to the value in the UniqueArc, and the result is returned, also in a UniqueArc.

Note: this is an associated function, which means that you have to call it as UniqueArc::map(u, f) instead of u.map(f). This is so that there is no conflict with a method on the inner type.

Examples

#![feature(unique_rc_arc)]

use std::sync::UniqueArc;

let r = UniqueArc::new(7);
let new = UniqueArc::map(r, |i| i + 7);
assert_eq!(*new, 14);
fn try_map<R>(this: Self, f: impl FnOnce(T) -> R) -> <R::Residual as Residual<UniqueArc<R::Output, A>>>::TryType
where
    R: Try,
    R::Residual: Residual<UniqueArc<R::Output, A>>,

Attempts to map the value in a UniqueArc, reusing the allocation if possible.

f is called on a reference to the value in the UniqueArc, and if the operation succeeds, the result is returned, also in a UniqueArc.

Note: this is an associated function, which means that you have to call it as UniqueArc::try_map(u, f) instead of u.try_map(f). This is so that there is no conflict with a method on the inner type.

Examples

#![feature(smart_pointer_try_map)]
#![feature(unique_rc_arc)]

use std::sync::UniqueArc;

let b = UniqueArc::new(7);
let new = UniqueArc::try_map(b, u32::try_from).unwrap();
assert_eq!(*new, 7);

impl<T: ?Sized, A: Allocator> UniqueArc<T, A>

unsafe fn from_raw_with_allocator(ptr: *const T, alloc: A) -> Self
fn into_raw_with_allocator(this: Self) -> (*const T, A)
fn into_arc(this: Self) -> Arc<T, A>

Converts the UniqueArc into a regular Arc.

This consumes the UniqueArc and returns a regular Arc that contains the value that is passed to into_arc.

Any weak references created before this method is called can now be upgraded to strong references.

fn weak_count(this: &Self) -> usize
fn inner(&self) -> &ArcInner<T>
fn as_ptr(this: &Self) -> *const T
fn into_inner_with_allocator(this: Self) -> (NonNull<ArcInner<T>>, A)
unsafe fn from_inner_in(ptr: NonNull<ArcInner<T>>, alloc: A) -> Self

impl<T: ?Sized, A: AllocatorClone> UniqueArc<T, A>

fn downgrade(this: &Self) -> Weak<T, A>

Creates a new weak reference to the UniqueArc.

Attempting to upgrade this weak reference will fail before the UniqueArc has been converted to a Arc using UniqueArc::into_arc.

Trait Implementations

impl<T> From<T> for UniqueArc<T>

fn from(value: T) -> Self

impl<T: ?Sized + Debug, A: Allocator> Debug for UniqueArc<T, A>

fn fmt(&self, f: &mut Formatter<'_>) -> Result

impl<T: ?Sized + Display, A: Allocator> Display for UniqueArc<T, A>

fn fmt(&self, f: &mut Formatter<'_>) -> Result

impl<T: ?Sized + Eq, A: Allocator> Eq for UniqueArc<T, A>

impl<T: ?Sized + Hash, A: Allocator> Hash for UniqueArc<T, A>

fn hash<H: Hasher>(&self, state: &mut H)

impl<T: ?Sized + Ord, A: Allocator> Ord for UniqueArc<T, A>

fn cmp(&self, other: &UniqueArc<T, A>) -> Ordering

Comparison for two UniqueArcs.

The two are compared by calling cmp() on their inner values.

Examples

#![feature(unique_rc_arc)]
use std::sync::UniqueArc;
use std::cmp::Ordering;

let five = UniqueArc::new(5);

assert_eq!(Ordering::Less, five.cmp(&UniqueArc::new(6)));

impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for UniqueArc<T, A>

fn eq(&self, other: &Self) -> bool

Equality for two UniqueArcs.

Two UniqueArcs are equal if their inner values are equal.

Examples

#![feature(unique_rc_arc)]
use std::sync::UniqueArc;

let five = UniqueArc::new(5);

assert!(five == UniqueArc::new(5));

impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for UniqueArc<T, A>

fn partial_cmp(&self, other: &UniqueArc<T, A>) -> Option<Ordering>

Partial comparison for two UniqueArcs.

The two are compared by calling partial_cmp() on their inner values.

Examples

#![feature(unique_rc_arc)]
use std::sync::UniqueArc;
use std::cmp::Ordering;

let five = UniqueArc::new(5);

assert_eq!(Some(Ordering::Less), five.partial_cmp(&UniqueArc::new(6)));
fn lt(&self, other: &UniqueArc<T, A>) -> bool

Less-than comparison for two UniqueArcs.

The two are compared by calling < on their inner values.

Examples

#![feature(unique_rc_arc)]
use std::sync::UniqueArc;

let five = UniqueArc::new(5);

assert!(five < UniqueArc::new(6));
fn le(&self, other: &UniqueArc<T, A>) -> bool

'Less than or equal to' comparison for two UniqueArcs.

The two are compared by calling <= on their inner values.

Examples

#![feature(unique_rc_arc)]
use std::sync::UniqueArc;

let five = UniqueArc::new(5);

assert!(five <= UniqueArc::new(5));
fn gt(&self, other: &UniqueArc<T, A>) -> bool

Greater-than comparison for two UniqueArcs.

The two are compared by calling > on their inner values.

Examples

#![feature(unique_rc_arc)]
use std::sync::UniqueArc;

let five = UniqueArc::new(5);

assert!(five > UniqueArc::new(4));
fn ge(&self, other: &UniqueArc<T, A>) -> bool

'Greater than or equal to' comparison for two UniqueArcs.

The two are compared by calling >= on their inner values.

Examples

#![feature(unique_rc_arc)]
use std::sync::UniqueArc;

let five = UniqueArc::new(5);

assert!(five >= UniqueArc::new(5));

impl<T: ?Sized + Sync + Send, A: Allocator + Send + Sync> Send for UniqueArc<T, A>

impl<T: ?Sized + Sync + Send, A: Allocator + Send + Sync> Sync for UniqueArc<T, A>

impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<UniqueArc<U>> for UniqueArc<T>

impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<UniqueArc<U, A>> for UniqueArc<T, A>

impl<T: ?Sized, A: Allocator> AsMut<T> for UniqueArc<T, A>

fn as_mut(&mut self) -> &mut T

impl<T: ?Sized, A: Allocator> AsRef<T> for UniqueArc<T, A>

fn as_ref(&self) -> &T

impl<T: ?Sized, A: Allocator> Borrow<T> for UniqueArc<T, A>

fn borrow(&self) -> &T

impl<T: ?Sized, A: Allocator> BorrowMut<T> for UniqueArc<T, A>

fn borrow_mut(&mut self) -> &mut T

impl<T: ?Sized, A: Allocator> Deref for UniqueArc<T, A>

type Target = T;
fn deref(&self) -> &T

impl<T: ?Sized, A: Allocator> DerefMut for UniqueArc<T, A>

fn deref_mut(&mut self) -> &mut T

impl<T: ?Sized, A: Allocator> DerefPure for UniqueArc<T, A>

impl<T: ?Sized, A: Allocator> Drop for UniqueArc<T, A>

fn drop(&mut self)

impl<T: ?Sized, A: Allocator> Pointer for UniqueArc<T, A>

fn fmt(&self, f: &mut Formatter<'_>) -> Result

impl<T: ?Sized, A: Allocator> Unpin for UniqueArc<T, A>

impl<T: ?Sized, A: StaticAllocator> PinSafePointer for UniqueArc<T, A>

Auto Trait Implementations

impl<T, A> Freeze for UniqueArc<T, A> where NonNull<ArcInner<T>>: Freeze, PhantomData<ArcInner<T>>: Freeze, PhantomData<*mut T>: Freeze, A: Freeze, T: ?Sized,

impl<T, A> RefUnwindSafe for UniqueArc<T, A> where NonNull<ArcInner<T>>: RefUnwindSafe, PhantomData<ArcInner<T>>: RefUnwindSafe, PhantomData<*mut T>: RefUnwindSafe, A: RefUnwindSafe, T: ?Sized,

impl<T, A> UnsafeUnpin for UniqueArc<T, A> where NonNull<ArcInner<T>>: UnsafeUnpin, PhantomData<ArcInner<T>>: UnsafeUnpin, PhantomData<*mut T>: UnsafeUnpin, A: UnsafeUnpin, T: ?Sized,

impl<T, A> UnwindSafe for UniqueArc<T, A> where NonNull<ArcInner<T>>: UnwindSafe, PhantomData<ArcInner<T>>: UnwindSafe, PhantomData<*mut T>: UnwindSafe, A: UnwindSafe, T: ?Sized,

Blanket Implementations

impl<P, T> Receiver for UniqueArc<T, A> where P: Deref<Target = T> + ?Sized, T: ?Sized,

type Target = T;

impl<T> Any for UniqueArc<T, A> where T: 'static + ?Sized,

fn type_id(&self) -> TypeId

impl<T> Borrow<T> for UniqueArc<T, A> where T: ?Sized,

fn borrow(&self) -> &T

impl<T> BorrowMut<T> for UniqueArc<T, A> where T: ?Sized,

fn borrow_mut(&mut self) -> &mut T

impl<T> From<T> for UniqueArc<T, A>

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> SizeHint for UniqueArc<T, A> where T: ?Sized,

fn lower_bound(&self) -> usize
fn upper_bound(&self) -> Option<usize>

impl<T> SizedTypeProperties for UniqueArc<T, A>

impl<T> ToString for UniqueArc<T, A> where T: Display + ?Sized,

fn to_string(&self) -> String

impl<T, U> Into<U> for UniqueArc<T, A> where U: From<T>,

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom<U> for UniqueArc<T, A> where U: Into<T>,

type Error = never;
fn try_from(value: U) -> Result<T, never>

impl<T, U> TryInto<U> for UniqueArc<T, A> where U: TryFrom<T>,

type Error = <U as TryFrom<T>>::Error;
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>