@@ -328,6 +328,79 @@ impl<T> Arc<T> {
328
328
Self::from_inner(Box::leak(x).into())
329
329
}
330
330
331
+ /// Constructs a new `Arc<T>` using a weak reference to itself. Attempting
332
+ /// to upgrade the weak reference before this function returns will result
333
+ /// in a `None` value. However, the weak reference may be cloned freely and
334
+ /// stored for use at a later time.
335
+ ///
336
+ /// # Examples
337
+ /// ```
338
+ /// #![feature(arc_new_cyclic)]
339
+ /// #![allow(dead_code)]
340
+ ///
341
+ /// use std::sync::{Arc, Weak};
342
+ ///
343
+ /// struct Foo {
344
+ /// me: Weak<Foo>,
345
+ /// }
346
+ ///
347
+ /// let foo = Arc::new_cyclic(|me| Foo {
348
+ /// me: me.clone(),
349
+ /// });
350
+ /// ```
351
+ #[inline]
352
+ #[unstable(feature = "arc_new_cyclic", issue = "none")]
353
+ pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Arc<T> {
354
+ // Construct the inner in the "uninitialized" state with a single
355
+ // weak reference.
356
+ let uninit_ptr: NonNull<_> = Box::leak(box ArcInner {
357
+ strong: atomic::AtomicUsize::new(0),
358
+ weak: atomic::AtomicUsize::new(1),
359
+ data: mem::MaybeUninit::<T>::uninit(),
360
+ })
361
+ .into();
362
+ let init_ptr: NonNull<ArcInner<T>> = uninit_ptr.cast();
363
+
364
+ let weak = Weak { ptr: init_ptr };
365
+
366
+ // It's important we don't give up ownership of the weak pointer, or
367
+ // else the memory might be freed by the time `data_fn` returns. If
368
+ // we really wanted to pass ownership, we could create an additional
369
+ // weak pointer for ourselves, but this would result in additional
370
+ // updates to the weak reference count which might not be necessary
371
+ // otherwise.
372
+ let data = data_fn(&weak);
373
+
374
+ // Now we can properly initialize the inner value and turn our weak
375
+ // reference into a strong reference.
376
+ unsafe {
377
+ let inner = init_ptr.as_ptr();
378
+ ptr::write(&raw mut (*inner).data, data);
379
+
380
+ // The above write to the data field must be visible to any threads which
381
+ // observe a non-zero strong count. Therefore we need at least "Release" ordering
382
+ // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`.
383
+ //
384
+ // "Acquire" ordering is not required. When considering the possible behaviours
385
+ // of `data_fn` we only need to look at what it could do with a reference to a
386
+ // non-upgradeable `Weak`:
387
+ // - It can *clone* the `Weak`, increasing the weak reference count.
388
+ // - It can drop those clones, decreasing the weak reference count (but never to zero).
389
+ //
390
+ // These side effects do not impact us in any way, and no other side effects are
391
+ // possible with safe code alone.
392
+ let prev_value = (*inner).strong.fetch_add(1, Release);
393
+ debug_assert_eq!(prev_value, 0, "No prior strong references should exist");
394
+ }
395
+
396
+ let strong = Arc::from_inner(init_ptr);
397
+
398
+ // Strong references should collectively own a shared weak reference,
399
+ // so don't run the destructor for our old weak reference.
400
+ mem::forget(weak);
401
+ strong
402
+ }
403
+
331
404
/// Constructs a new `Arc` with uninitialized contents.
332
405
///
333
406
/// # Examples
@@ -1589,7 +1662,8 @@ impl<T: ?Sized> Weak<T> {
1589
1662
#[stable(feature = "arc_weak", since = "1.4.0")]
1590
1663
pub fn upgrade(&self) -> Option<Arc<T>> {
1591
1664
// We use a CAS loop to increment the strong count instead of a
1592
- // fetch_add because once the count hits 0 it must never be above 0.
1665
+ // fetch_add as this function should never take the reference count
1666
+ // from zero to one.
1593
1667
let inner = self.inner()?;
1594
1668
1595
1669
// Relaxed load because any write of 0 that we can observe
@@ -1608,8 +1682,11 @@ impl<T: ?Sized> Weak<T> {
1608
1682
abort();
1609
1683
}
1610
1684
1611
- // Relaxed is valid for the same reason it is on Arc's Clone impl
1612
- match inner.strong.compare_exchange_weak(n, n + 1, Relaxed, Relaxed) {
1685
+ // Relaxed is fine for the failure case because we don't have any expectations about the new state.
1686
+ // Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner
1687
+ // value can be initialized after `Weak` references have already been created. In that case, we
1688
+ // expect to observe the fully initialized value.
1689
+ match inner.strong.compare_exchange_weak(n, n + 1, Acquire, Relaxed) {
1613
1690
Ok(_) => return Some(Arc::from_inner(self.ptr)), // null checked above
1614
1691
Err(old) => n = old,
1615
1692
}
0 commit comments