@@ -478,6 +478,97 @@ impl<T> Arc<T> {
478478 unsafe { Pin :: new_unchecked ( Arc :: new ( data) ) }
479479 }
480480
481+ /// Constructs a new `Arc<T>`, returning an error if allocation fails.
482+ ///
483+ /// # Examples
484+ ///
485+ /// ```
486+ /// #![feature(allocator_api)]
487+ /// use std::sync::Arc;
488+ ///
489+ /// let five = Arc::try_new(5)?;
490+ /// # Ok::<(), std::alloc::AllocError>(())
491+ /// ```
492+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
493+ #[ inline]
494+ pub fn try_new ( data : T ) -> Result < Arc < T > , AllocError > {
495+ // Start the weak pointer count as 1 which is the weak pointer that's
496+ // held by all the strong pointers (kinda), see std/rc.rs for more info
497+ let x: Box < _ > = Box :: try_new ( ArcInner {
498+ strong : atomic:: AtomicUsize :: new ( 1 ) ,
499+ weak : atomic:: AtomicUsize :: new ( 1 ) ,
500+ data,
501+ } ) ?;
502+ Ok ( Self :: from_inner ( Box :: leak ( x) . into ( ) ) )
503+ }
504+
505+ /// Constructs a new `Arc` with uninitialized contents, returning an error
506+ /// if allocation fails.
507+ ///
508+ /// # Examples
509+ ///
510+ /// ```
511+ /// #![feature(new_uninit, allocator_api)]
512+ /// #![feature(get_mut_unchecked)]
513+ ///
514+ /// use std::sync::Arc;
515+ ///
516+ /// let mut five = Arc::<u32>::try_new_uninit()?;
517+ ///
518+ /// let five = unsafe {
519+ /// // Deferred initialization:
520+ /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
521+ ///
522+ /// five.assume_init()
523+ /// };
524+ ///
525+ /// assert_eq!(*five, 5);
526+ /// # Ok::<(), std::alloc::AllocError>(())
527+ /// ```
528+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
529+ // #[unstable(feature = "new_uninit", issue = "63291")]
530+ pub fn try_new_uninit ( ) -> Result < Arc < mem:: MaybeUninit < T > > , AllocError > {
531+ unsafe {
532+ Ok ( Arc :: from_ptr ( Arc :: try_allocate_for_layout (
533+ Layout :: new :: < T > ( ) ,
534+ |layout| Global . allocate ( layout) ,
535+ |mem| mem as * mut ArcInner < mem:: MaybeUninit < T > > ,
536+ ) ?) )
537+ }
538+ }
539+
540+ /// Constructs a new `Arc` with uninitialized contents, with the memory
541+ /// being filled with `0` bytes, returning an error if allocation fails.
542+ ///
543+ /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
544+ /// of this method.
545+ ///
546+ /// # Examples
547+ ///
548+ /// ```
549+ /// #![feature(new_uninit, allocator_api)]
550+ ///
551+ /// use std::sync::Arc;
552+ ///
553+ /// let zero = Arc::<u32>::try_new_zeroed()?;
554+ /// let zero = unsafe { zero.assume_init() };
555+ ///
556+ /// assert_eq!(*zero, 0);
557+ /// # Ok::<(), std::alloc::AllocError>(())
558+ /// ```
559+ ///
560+ /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
561+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
562+ // #[unstable(feature = "new_uninit", issue = "63291")]
563+ pub fn try_new_zeroed ( ) -> Result < Arc < mem:: MaybeUninit < T > > , AllocError > {
564+ unsafe {
565+ Ok ( Arc :: from_ptr ( Arc :: try_allocate_for_layout (
566+ Layout :: new :: < T > ( ) ,
567+ |layout| Global . allocate_zeroed ( layout) ,
568+ |mem| mem as * mut ArcInner < mem:: MaybeUninit < T > > ,
569+ ) ?) )
570+ }
571+ }
481572 /// Returns the inner value, if the `Arc` has exactly one strong reference.
482573 ///
483574 /// Otherwise, an [`Err`] is returned with the same `Arc` that was
@@ -1009,6 +1100,37 @@ impl<T: ?Sized> Arc<T> {
10091100 inner
10101101 }
10111102
1103+ /// Allocates an `ArcInner<T>` with sufficient space for
1104+ /// a possibly-unsized inner value where the value has the layout provided,
1105+ /// returning an error if allocation fails.
1106+ ///
1107+ /// The function `mem_to_arcinner` is called with the data pointer
1108+ /// and must return back a (potentially fat)-pointer for the `ArcInner<T>`.
1109+ unsafe fn try_allocate_for_layout (
1110+ value_layout : Layout ,
1111+ allocate : impl FnOnce ( Layout ) -> Result < NonNull < [ u8 ] > , AllocError > ,
1112+ mem_to_arcinner : impl FnOnce ( * mut u8 ) -> * mut ArcInner < T > ,
1113+ ) -> Result < * mut ArcInner < T > , AllocError > {
1114+ // Calculate layout using the given value layout.
1115+ // Previously, layout was calculated on the expression
1116+ // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
1117+ // reference (see #54908).
1118+ let layout = Layout :: new :: < ArcInner < ( ) > > ( ) . extend ( value_layout) . unwrap ( ) . 0 . pad_to_align ( ) ;
1119+
1120+ let ptr = allocate ( layout) ?;
1121+
1122+ // Initialize the ArcInner
1123+ let inner = mem_to_arcinner ( ptr. as_non_null_ptr ( ) . as_ptr ( ) ) ;
1124+ debug_assert_eq ! ( unsafe { Layout :: for_value( & * inner) } , layout) ;
1125+
1126+ unsafe {
1127+ ptr:: write ( & mut ( * inner) . strong , atomic:: AtomicUsize :: new ( 1 ) ) ;
1128+ ptr:: write ( & mut ( * inner) . weak , atomic:: AtomicUsize :: new ( 1 ) ) ;
1129+ }
1130+
1131+ Ok ( inner)
1132+ }
1133+
10121134 /// Allocates an `ArcInner<T>` with sufficient space for an unsized inner value.
10131135 unsafe fn allocate_for_ptr ( ptr : * const T ) -> * mut ArcInner < T > {
10141136 // Allocate for the `ArcInner<T>` using the given value.
0 commit comments