@@ -1322,6 +1322,99 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> {
13221322 }
13231323}
13241324
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+
13251418impl < T : ?Sized > Arc < T > {
13261419 /// Constructs an `Arc<T>` from a raw pointer.
13271420 ///
0 commit comments