@@ -450,54 +450,7 @@ impl<T> Arc<T> {
450
450
where
451
451
F : FnOnce ( & Weak < T > ) -> T ,
452
452
{
453
- // Construct the inner in the "uninitialized" state with a single
454
- // weak reference.
455
- let uninit_ptr: NonNull < _ > = Box :: leak ( Box :: new ( ArcInner {
456
- strong : atomic:: AtomicUsize :: new ( 0 ) ,
457
- weak : atomic:: AtomicUsize :: new ( 1 ) ,
458
- data : mem:: MaybeUninit :: < T > :: uninit ( ) ,
459
- } ) )
460
- . into ( ) ;
461
- let init_ptr: NonNull < ArcInner < T > > = uninit_ptr. cast ( ) ;
462
-
463
- let weak = Weak { ptr : init_ptr, alloc : Global } ;
464
-
465
- // It's important we don't give up ownership of the weak pointer, or
466
- // else the memory might be freed by the time `data_fn` returns. If
467
- // we really wanted to pass ownership, we could create an additional
468
- // weak pointer for ourselves, but this would result in additional
469
- // updates to the weak reference count which might not be necessary
470
- // otherwise.
471
- let data = data_fn ( & weak) ;
472
-
473
- // Now we can properly initialize the inner value and turn our weak
474
- // reference into a strong reference.
475
- let strong = unsafe {
476
- let inner = init_ptr. as_ptr ( ) ;
477
- ptr:: write ( ptr:: addr_of_mut!( ( * inner) . data) , data) ;
478
-
479
- // The above write to the data field must be visible to any threads which
480
- // observe a non-zero strong count. Therefore we need at least "Release" ordering
481
- // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`.
482
- //
483
- // "Acquire" ordering is not required. When considering the possible behaviours
484
- // of `data_fn` we only need to look at what it could do with a reference to a
485
- // non-upgradeable `Weak`:
486
- // - It can *clone* the `Weak`, increasing the weak reference count.
487
- // - It can drop those clones, decreasing the weak reference count (but never to zero).
488
- //
489
- // These side effects do not impact us in any way, and no other side effects are
490
- // possible with safe code alone.
491
- let prev_value = ( * inner) . strong . fetch_add ( 1 , Release ) ;
492
- debug_assert_eq ! ( prev_value, 0 , "No prior strong references should exist" ) ;
493
-
494
- Arc :: from_inner ( init_ptr)
495
- } ;
496
-
497
- // Strong references should collectively own a shared weak reference,
498
- // so don't run the destructor for our old weak reference.
499
- mem:: forget ( weak) ;
500
- strong
453
+ Self :: new_cyclic_in ( data_fn, Global )
501
454
}
502
455
503
456
/// Constructs a new `Arc` with uninitialized contents.
@@ -781,6 +734,98 @@ impl<T, A: Allocator> Arc<T, A> {
781
734
}
782
735
}
783
736
737
+ /// Constructs a new `Arc<T, A>` in the given allocator while giving you a `Weak<T, A>` to the allocation,
738
+ /// to allow you to construct a `T` which holds a weak pointer to itself.
739
+ ///
740
+ /// Generally, a structure circularly referencing itself, either directly or
741
+ /// indirectly, should not hold a strong reference to itself to prevent a memory leak.
742
+ /// Using this function, you get access to the weak pointer during the
743
+ /// initialization of `T`, before the `Arc<T, A>` is created, such that you can
744
+ /// clone and store it inside the `T`.
745
+ ///
746
+ /// `new_cyclic_in` first allocates the managed allocation for the `Arc<T, A>`,
747
+ /// then calls your closure, giving it a `Weak<T, A>` to this allocation,
748
+ /// and only afterwards completes the construction of the `Arc<T, A>` by placing
749
+ /// the `T` returned from your closure into the allocation.
750
+ ///
751
+ /// Since the new `Arc<T, A>` is not fully-constructed until `Arc<T, A>::new_cyclic_in`
752
+ /// returns, calling [`upgrade`] on the weak reference inside your closure will
753
+ /// fail and result in a `None` value.
754
+ ///
755
+ /// # Panics
756
+ ///
757
+ /// If `data_fn` panics, the panic is propagated to the caller, and the
758
+ /// temporary [`Weak<T>`] is dropped normally.
759
+ ///
760
+ /// # Example
761
+ ///
762
+ /// See [`new_cyclic`]
763
+ ///
764
+ /// [`new_cyclic`]: Arc::new_cyclic
765
+ /// [`upgrade`]: Weak::upgrade
766
+ #[ cfg( not( no_global_oom_handling) ) ]
767
+ #[ inline]
768
+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
769
+ pub fn new_cyclic_in < F > ( data_fn : F , alloc : A ) -> Arc < T , A >
770
+ where
771
+ F : FnOnce ( & Weak < T , A > ) -> T ,
772
+ {
773
+ // Construct the inner in the "uninitialized" state with a single
774
+ // weak reference.
775
+ let ( uninit_raw_ptr, alloc) = Box :: into_raw_with_allocator ( Box :: new_in (
776
+ ArcInner {
777
+ strong : atomic:: AtomicUsize :: new ( 0 ) ,
778
+ weak : atomic:: AtomicUsize :: new ( 1 ) ,
779
+ data : mem:: MaybeUninit :: < T > :: uninit ( ) ,
780
+ } ,
781
+ alloc,
782
+ ) ) ;
783
+ let uninit_ptr: NonNull < _ > = ( unsafe { & mut * uninit_raw_ptr } ) . into ( ) ;
784
+ let init_ptr: NonNull < ArcInner < T > > = uninit_ptr. cast ( ) ;
785
+
786
+ let weak = Weak { ptr : init_ptr, alloc : alloc } ;
787
+
788
+ // It's important we don't give up ownership of the weak pointer, or
789
+ // else the memory might be freed by the time `data_fn` returns. If
790
+ // we really wanted to pass ownership, we could create an additional
791
+ // weak pointer for ourselves, but this would result in additional
792
+ // updates to the weak reference count which might not be necessary
793
+ // otherwise.
794
+ let data = data_fn ( & weak) ;
795
+
796
+ // Now we can properly initialize the inner value and turn our weak
797
+ // reference into a strong reference.
798
+ let strong = unsafe {
799
+ let inner = init_ptr. as_ptr ( ) ;
800
+ ptr:: write ( ptr:: addr_of_mut!( ( * inner) . data) , data) ;
801
+
802
+ // The above write to the data field must be visible to any threads which
803
+ // observe a non-zero strong count. Therefore we need at least "Release" ordering
804
+ // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`.
805
+ //
806
+ // "Acquire" ordering is not required. When considering the possible behaviours
807
+ // of `data_fn` we only need to look at what it could do with a reference to a
808
+ // non-upgradeable `Weak`:
809
+ // - It can *clone* the `Weak`, increasing the weak reference count.
810
+ // - It can drop those clones, decreasing the weak reference count (but never to zero).
811
+ //
812
+ // These side effects do not impact us in any way, and no other side effects are
813
+ // possible with safe code alone.
814
+ let prev_value = ( * inner) . strong . fetch_add ( 1 , Release ) ;
815
+ debug_assert_eq ! ( prev_value, 0 , "No prior strong references should exist" ) ;
816
+
817
+ // Strong references should collectively own a shared weak reference,
818
+ // so don't run the destructor for our old weak reference.
819
+ // Calling into_raw_with_allocator has the double effect of giving us back the allocator,
820
+ // and forgetting the weak reference.
821
+ let alloc = weak. into_raw_with_allocator ( ) . 1 ;
822
+
823
+ Arc :: from_inner_in ( init_ptr, alloc)
824
+ } ;
825
+
826
+ strong
827
+ }
828
+
784
829
/// Constructs a new `Pin<Arc<T, A>>` in the provided allocator. If `T` does not implement `Unpin`,
785
830
/// then `data` will be pinned in memory and unable to be moved.
786
831
#[ cfg( not( no_global_oom_handling) ) ]
0 commit comments