@@ -785,6 +785,98 @@ impl<T, A: Allocator> Arc<T, A> {
785
785
}
786
786
}
787
787
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
+
788
880
/// Constructs a new `Pin<Arc<T, A>>` in the provided allocator. If `T` does not implement `Unpin`,
789
881
/// then `data` will be pinned in memory and unable to be moved.
790
882
#[ cfg( not( no_global_oom_handling) ) ]
@@ -1322,99 +1414,6 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> {
1322
1414
}
1323
1415
}
1324
1416
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
-
1418
1417
impl < T : ?Sized > Arc < T > {
1419
1418
/// Constructs an `Arc<T>` from a raw pointer.
1420
1419
///
0 commit comments