@@ -785,6 +785,98 @@ impl<T, A: Allocator> Arc<T, A> {
785785 }
786786 }
787787
788+ /// Constructs a new `Arc<T, A>` in the given allocator while giving you a `Weak<T, A>` to the allocation,
789+ /// to allow you to construct a `T` which holds a weak pointer to itself.
790+ ///
791+ /// Generally, a structure circularly referencing itself, either directly or
792+ /// indirectly, should not hold a strong reference to itself to prevent a memory leak.
793+ /// Using this function, you get access to the weak pointer during the
794+ /// initialization of `T`, before the `Arc<T, A>` is created, such that you can
795+ /// clone and store it inside the `T`.
796+ ///
797+ /// `new_cyclic_in` first allocates the managed allocation for the `Arc<T, A>`,
798+ /// then calls your closure, giving it a `Weak<T, A>` to this allocation,
799+ /// and only afterwards completes the construction of the `Arc<T, A>` by placing
800+ /// the `T` returned from your closure into the allocation.
801+ ///
802+ /// Since the new `Arc<T, A>` is not fully-constructed until `Arc<T, A>::new_cyclic_in`
803+ /// returns, calling [`upgrade`] on the weak reference inside your closure will
804+ /// fail and result in a `None` value.
805+ ///
806+ /// # Panics
807+ ///
808+ /// If `data_fn` panics, the panic is propagated to the caller, and the
809+ /// temporary [`Weak<T>`] is dropped normally.
810+ ///
811+ /// # Example
812+ ///
813+ /// See [`new_cyclic`]
814+ ///
815+ /// [`new_cyclic`]: Arc::new_cyclic
816+ /// [`upgrade`]: Weak::upgrade
817+ #[ cfg( not( no_global_oom_handling) ) ]
818+ #[ inline]
819+ #[ stable( feature = "arc_new_cyclic" , since = "1.60.0" ) ]
820+ pub fn new_cyclic_in < F > ( data_fn : F , alloc : A ) -> Arc < T , A >
821+ where
822+ F : FnOnce ( & Weak < T , A > ) -> T ,
823+ {
824+ // Note: these comments and much of the implementation is copied from Arc::new_cyclic.
825+
826+ // Construct the inner in the "uninitialized" state with a single
827+ // weak reference.
828+ let ( uninit_raw_ptr, alloc) = Box :: into_raw_with_allocator ( Box :: new_in (
829+ ArcInner {
830+ strong : atomic:: AtomicUsize :: new ( 0 ) ,
831+ weak : atomic:: AtomicUsize :: new ( 1 ) ,
832+ data : mem:: MaybeUninit :: < T > :: uninit ( ) ,
833+ } ,
834+ alloc,
835+ ) ) ;
836+ let uninit_ptr: NonNull < _ > = ( unsafe { & mut * uninit_raw_ptr } ) . into ( ) ;
837+ let init_ptr: NonNull < ArcInner < T > > = uninit_ptr. cast ( ) ;
838+
839+ let weak = Weak { ptr : init_ptr, alloc : alloc } ;
840+
841+ // It's important we don't give up ownership of the weak pointer, or
842+ // else the memory might be freed by the time `data_fn` returns. If
843+ // we really wanted to pass ownership, we could create an additional
844+ // weak pointer for ourselves, but this would result in additional
845+ // updates to the weak reference count which might not be necessary
846+ // otherwise.
847+ let data = data_fn ( & weak) ;
848+
849+ // Now we can properly initialize the inner value and turn our weak
850+ // reference into a strong reference.
851+ let strong = unsafe {
852+ let inner = init_ptr. as_ptr ( ) ;
853+ ptr:: write ( ptr:: addr_of_mut!( ( * inner) . data) , data) ;
854+
855+ // The above write to the data field must be visible to any threads which
856+ // observe a non-zero strong count. Therefore we need at least "Release" ordering
857+ // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`.
858+ //
859+ // "Acquire" ordering is not required. When considering the possible behaviours
860+ // of `data_fn` we only need to look at what it could do with a reference to a
861+ // non-upgradeable `Weak`:
862+ // - It can *clone* the `Weak`, increasing the weak reference count.
863+ // - It can drop those clones, decreasing the weak reference count (but never to zero).
864+ //
865+ // These side effects do not impact us in any way, and no other side effects are
866+ // possible with safe code alone.
867+ let prev_value = ( * inner) . strong . fetch_add ( 1 , Release ) ;
868+ debug_assert_eq ! ( prev_value, 0 , "No prior strong references should exist" ) ;
869+
870+ // Strong references should collectively own a shared weak reference,
871+ // so don't run the destructor for our old weak reference.
872+ let alloc = weak. into_raw_with_allocator ( ) . 1 ;
873+
874+ Arc :: from_inner_in ( init_ptr, alloc)
875+ } ;
876+
877+ strong
878+ }
879+
788880 /// Constructs a new `Pin<Arc<T, A>>` in the provided allocator. If `T` does not implement `Unpin`,
789881 /// then `data` will be pinned in memory and unable to be moved.
790882 #[ cfg( not( no_global_oom_handling) ) ]
@@ -1322,99 +1414,6 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> {
13221414 }
13231415}
13241416
1325- impl < T , A : Allocator + Clone > Arc < T , A > {
1326- /// Constructs a new `Arc<T, A>` in the given allocator while giving you a `Weak<T, A>` to the allocation,
1327- /// to allow you to construct a `T` which holds a weak pointer to itself.
1328- ///
1329- /// Generally, a structure circularly referencing itself, either directly or
1330- /// indirectly, should not hold a strong reference to itself to prevent a memory leak.
1331- /// Using this function, you get access to the weak pointer during the
1332- /// initialization of `T`, before the `Arc<T, A>` is created, such that you can
1333- /// clone and store it inside the `T`.
1334- ///
1335- /// `new_cyclic` first allocates the managed allocation for the `Arc<T, A>`,
1336- /// then calls your closure, giving it a `Weak<T, A>` to this allocation,
1337- /// and only afterwards completes the construction of the `Arc<T, A>` by placing
1338- /// the `T` returned from your closure into the allocation.
1339- ///
1340- /// Since the new `Arc<T, A>` is not fully-constructed until `Arc<T, A>::new_cyclic_in`
1341- /// returns, calling [`upgrade`] on the weak reference inside your closure will
1342- /// fail and result in a `None` value.
1343- ///
1344- /// # Panics
1345- ///
1346- /// If `data_fn` panics, the panic is propagated to the caller, and the
1347- /// temporary [`Weak<T>`] is dropped normally.
1348- ///
1349- /// # Example
1350- ///
1351- /// See [`new_cyclic`]
1352- ///
1353- /// [`new_cyclic`]: Arc::new_cyclic
1354- /// [`upgrade`]: Weak::upgrade
1355- #[ cfg( not( no_global_oom_handling) ) ]
1356- #[ inline]
1357- #[ stable( feature = "arc_new_cyclic" , since = "1.60.0" ) ]
1358- pub fn new_cyclic_in < F > ( data_fn : F , alloc : A ) -> Arc < T , A >
1359- where
1360- F : FnOnce ( & Weak < T , A > ) -> T ,
1361- {
1362- // Note: these comments and much of the implementation is copied from Arc::new_cyclic.
1363-
1364- // Construct the inner in the "uninitialized" state with a single
1365- // weak reference.
1366- let uninit_ptr: NonNull < _ > = Box :: leak ( Box :: new_in (
1367- ArcInner {
1368- strong : atomic:: AtomicUsize :: new ( 0 ) ,
1369- weak : atomic:: AtomicUsize :: new ( 1 ) ,
1370- data : mem:: MaybeUninit :: < T > :: uninit ( ) ,
1371- } ,
1372- alloc. clone ( ) ,
1373- ) )
1374- . into ( ) ;
1375- let init_ptr: NonNull < ArcInner < T > > = uninit_ptr. cast ( ) ;
1376-
1377- let weak = Weak { ptr : init_ptr, alloc : alloc. clone ( ) } ;
1378-
1379- // It's important we don't give up ownership of the weak pointer, or
1380- // else the memory might be freed by the time `data_fn` returns. If
1381- // we really wanted to pass ownership, we could create an additional
1382- // weak pointer for ourselves, but this would result in additional
1383- // updates to the weak reference count which might not be necessary
1384- // otherwise.
1385- let data = data_fn ( & weak) ;
1386-
1387- // Now we can properly initialize the inner value and turn our weak
1388- // reference into a strong reference.
1389- let strong = unsafe {
1390- let inner = init_ptr. as_ptr ( ) ;
1391- ptr:: write ( ptr:: addr_of_mut!( ( * inner) . data) , data) ;
1392-
1393- // The above write to the data field must be visible to any threads which
1394- // observe a non-zero strong count. Therefore we need at least "Release" ordering
1395- // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`.
1396- //
1397- // "Acquire" ordering is not required. When considering the possible behaviours
1398- // of `data_fn` we only need to look at what it could do with a reference to a
1399- // non-upgradeable `Weak`:
1400- // - It can *clone* the `Weak`, increasing the weak reference count.
1401- // - It can drop those clones, decreasing the weak reference count (but never to zero).
1402- //
1403- // These side effects do not impact us in any way, and no other side effects are
1404- // possible with safe code alone.
1405- let prev_value = ( * inner) . strong . fetch_add ( 1 , Release ) ;
1406- debug_assert_eq ! ( prev_value, 0 , "No prior strong references should exist" ) ;
1407-
1408- Arc :: from_inner_in ( init_ptr, alloc)
1409- } ;
1410-
1411- // Strong references should collectively own a shared weak reference,
1412- // so don't run the destructor for our old weak reference.
1413- mem:: forget ( weak) ;
1414- strong
1415- }
1416- }
1417-
14181417impl < T : ?Sized > Arc < T > {
14191418 /// Constructs an `Arc<T>` from a raw pointer.
14201419 ///
0 commit comments