@@ -328,6 +328,79 @@ impl<T> Arc<T> {
328328 Self :: from_inner ( Box :: leak ( x) . into ( ) )
329329 }
330330
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_with)]
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_with(|me| Foo {
348+ /// me: me.clone(),
349+ /// });
350+ /// ```
351+ #[ inline]
352+ #[ unstable( feature = "arc_new_with" , issue = "none" ) ]
353+ pub fn new_with ( 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+
331404 /// Constructs a new `Arc` with uninitialized contents.
332405 ///
333406 /// # Examples
@@ -1608,7 +1681,8 @@ impl<T: ?Sized> Weak<T> {
16081681 #[ stable( feature = "arc_weak" , since = "1.4.0" ) ]
16091682 pub fn upgrade ( & self ) -> Option < Arc < T > > {
16101683 // We use a CAS loop to increment the strong count instead of a
1611- // fetch_add because once the count hits 0 it must never be above 0.
1684+ // fetch_add as this function should never take the reference count
1685+ // from zero to one.
16121686 let inner = self . inner ( ) ?;
16131687
16141688 // Relaxed load because any write of 0 that we can observe
@@ -1631,8 +1705,11 @@ impl<T: ?Sized> Weak<T> {
16311705 }
16321706 }
16331707
1634- // Relaxed is valid for the same reason it is on Arc's Clone impl
1635- match inner. strong . compare_exchange_weak ( n, n + 1 , Relaxed , Relaxed ) {
1708+ // Relaxed is fine for the failure case because we don't have any expectations about the new state.
1709+ // Acquire is necessary for the success case to synchronise with `Arc::new_with`, when the inner
1710+ // value can be initialized after `Weak` references have already been created. In that case, we
1711+ // expect to observe the fully initialized value.
1712+ match inner. strong . compare_exchange_weak ( n, n + 1 , Acquire , Relaxed ) {
16361713 Ok ( _) => return Some ( Arc :: from_inner ( self . ptr ) ) , // null checked above
16371714 Err ( old) => n = old,
16381715 }
0 commit comments