@@ -478,6 +478,97 @@ impl<T> Arc<T> {
478
478
unsafe { Pin :: new_unchecked ( Arc :: new ( data) ) }
479
479
}
480
480
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
+ }
481
572
/// Returns the inner value, if the `Arc` has exactly one strong reference.
482
573
///
483
574
/// Otherwise, an [`Err`] is returned with the same `Arc` that was
@@ -1009,6 +1100,37 @@ impl<T: ?Sized> Arc<T> {
1009
1100
inner
1010
1101
}
1011
1102
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
+
1012
1134
/// Allocates an `ArcInner<T>` with sufficient space for an unsized inner value.
1013
1135
unsafe fn allocate_for_ptr ( ptr : * const T ) -> * mut ArcInner < T > {
1014
1136
// Allocate for the `ArcInner<T>` using the given value.
0 commit comments