add new_cyclic_in for Arc · qinheping/verify-rust-std@24eca28 (original) (raw)
`@@ -1322,6 +1322,99 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit], A> {
`
1322
1322
`}
`
1323
1323
`}
`
1324
1324
``
``
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(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::::uninit(),
`
``
1371
`+
},
`
``
1372
`+
alloc.clone(),
`
``
1373
`+
))
`
``
1374
`+
.into();
`
``
1375
`+
let init_ptr: NonNull<ArcInner> = 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
+
1325
1418
`impl<T: ?Sized> Arc {
`
1326
1419
`` /// Constructs an Arc<T> from a raw pointer.
``
1327
1420
`///
`