Skip to content

Commit cf4b684

Browse files
committed
Add Arc::(try_)clone_from_ref(_in)
1 parent 9f3d745 commit cf4b684

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

library/alloc/src/sync.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,104 @@ impl<T, A: Allocator> Arc<mem::MaybeUninit<T>, A> {
14421442
}
14431443
}
14441444

1445+
impl<T: ?Sized + CloneToUninit> Arc<T> {
1446+
/// Constructs a new `Arc<T>` with a clone of `value`.
1447+
///
1448+
/// # Examples
1449+
///
1450+
/// ```
1451+
/// #![feature(clone_from_ref)]
1452+
/// use std::sync::Arc;
1453+
///
1454+
/// let hello: Arc<str> = Arc::clone_from_ref("hello");
1455+
/// ```
1456+
#[cfg(not(no_global_oom_handling))]
1457+
#[unstable(feature = "clone_from_ref", issue = "149075")]
1458+
pub fn clone_from_ref(value: &T) -> Arc<T> {
1459+
Arc::clone_from_ref_in(value, Global)
1460+
}
1461+
1462+
/// Constructs a new `Arc<T>` with a clone of `value`, returning an error if allocation fails
1463+
///
1464+
/// # Examples
1465+
///
1466+
/// ```
1467+
/// #![feature(clone_from_ref)]
1468+
/// #![feature(allocator_api)]
1469+
/// use std::sync::Arc;
1470+
///
1471+
/// let hello: Arc<str> = Arc::try_clone_from_ref("hello")?;
1472+
/// # Ok::<(), std::alloc::AllocError>(())
1473+
/// ```
1474+
#[unstable(feature = "clone_from_ref", issue = "149075")]
1475+
//#[unstable(feature = "allocator_api", issue = "32838")]
1476+
pub fn try_clone_from_ref(value: &T) -> Result<Arc<T>, AllocError> {
1477+
Arc::try_clone_from_ref_in(value, Global)
1478+
}
1479+
}
1480+
1481+
impl<T: ?Sized + CloneToUninit, A: Allocator> Arc<T, A> {
1482+
/// Constructs a new `Arc<T>` with a clone of `value` in the provided allocator.
1483+
///
1484+
/// # Examples
1485+
///
1486+
/// ```
1487+
/// #![feature(clone_from_ref)]
1488+
/// #![feature(allocator_api)]
1489+
/// use std::sync::Arc;
1490+
/// use std::alloc::System;
1491+
///
1492+
/// let hello: Arc<str, System> = Arc::clone_from_ref_in("hello", System);
1493+
/// ```
1494+
#[cfg(not(no_global_oom_handling))]
1495+
#[unstable(feature = "clone_from_ref", issue = "149075")]
1496+
//#[unstable(feature = "allocator_api", issue = "32838")]
1497+
pub fn clone_from_ref_in(value: &T, alloc: A) -> Arc<T, A> {
1498+
// `in_progress` drops the allocation if we panic before finishing initializing it.
1499+
let mut in_progress: UniqueArcUninit<T, A> = UniqueArcUninit::new(value, alloc);
1500+
1501+
// Initialize with clone of value.
1502+
let initialized_clone = unsafe {
1503+
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
1504+
value.clone_to_uninit(in_progress.data_ptr().cast());
1505+
// Cast type of pointer, now that it is initialized.
1506+
in_progress.into_arc()
1507+
};
1508+
1509+
initialized_clone
1510+
}
1511+
1512+
/// Constructs a new `Arc<T>` with a clone of `value` in the provided allocator, returning an error if allocation fails
1513+
///
1514+
/// # Examples
1515+
///
1516+
/// ```
1517+
/// #![feature(clone_from_ref)]
1518+
/// #![feature(allocator_api)]
1519+
/// use std::sync::Arc;
1520+
/// use std::alloc::System;
1521+
///
1522+
/// let hello: Arc<str, System> = Arc::try_clone_from_ref_in("hello", System)?;
1523+
/// # Ok::<(), std::alloc::AllocError>(())
1524+
/// ```
1525+
#[unstable(feature = "clone_from_ref", issue = "149075")]
1526+
//#[unstable(feature = "allocator_api", issue = "32838")]
1527+
pub fn try_clone_from_ref_in(value: &T, alloc: A) -> Result<Arc<T, A>, AllocError> {
1528+
// `in_progress` drops the allocation if we panic before finishing initializing it.
1529+
let mut in_progress: UniqueArcUninit<T, A> = UniqueArcUninit::try_new(value, alloc)?;
1530+
1531+
// Initialize with clone of value.
1532+
let initialized_clone = unsafe {
1533+
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
1534+
value.clone_to_uninit(in_progress.data_ptr().cast());
1535+
// Cast type of pointer, now that it is initialized.
1536+
in_progress.into_arc()
1537+
};
1538+
1539+
Ok(initialized_clone)
1540+
}
1541+
}
1542+
14451543
impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> {
14461544
/// Converts to `Arc<[T]>`.
14471545
///
@@ -4159,6 +4257,20 @@ impl<T: ?Sized, A: Allocator> UniqueArcUninit<T, A> {
41594257
Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) }
41604258
}
41614259

4260+
/// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it,
4261+
/// returning an error if allocation fails.
4262+
fn try_new(for_value: &T, alloc: A) -> Result<UniqueArcUninit<T, A>, AllocError> {
4263+
let layout = Layout::for_value(for_value);
4264+
let ptr = unsafe {
4265+
Arc::try_allocate_for_layout(
4266+
layout,
4267+
|layout_for_arcinner| alloc.allocate(layout_for_arcinner),
4268+
|mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const ArcInner<T>),
4269+
)?
4270+
};
4271+
Ok(Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) })
4272+
}
4273+
41624274
/// Returns the pointer to be written into to initialize the [`Arc`].
41634275
fn data_ptr(&mut self) -> *mut T {
41644276
let offset = data_offset_align(self.layout_for_value.align());

0 commit comments

Comments
 (0)