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

`///

`