Skip to content

Commit 8cb474e

Browse files
committed
Add {Arc,Weak}::into_raw_with_allocator
1 parent b17fae9 commit 8cb474e

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

library/alloc/src/sync.rs

+67
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,34 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
14891489
ptr
14901490
}
14911491

1492+
/// Consumes the `Arc`, returning the wrapped pointer and allocator.
1493+
///
1494+
/// To avoid a memory leak the pointer must be converted back to an `Arc` using
1495+
/// [`Arc::from_raw_in`].
1496+
///
1497+
/// # Examples
1498+
///
1499+
/// ```
1500+
/// #![feature(allocator_api)]
1501+
/// use std::sync::Arc;
1502+
/// use std::alloc::System;
1503+
///
1504+
/// let x = Arc::new_in("hello".to_owned(), System);
1505+
/// let (ptr, alloc) = Arc::into_raw_with_allocator(x);
1506+
/// assert_eq!(unsafe { &*ptr }, "hello");
1507+
/// let x = unsafe { Arc::from_raw_in(ptr, alloc) };
1508+
/// assert_eq!(&*x, "hello");
1509+
/// ```
1510+
#[must_use = "losing the pointer will leak memory"]
1511+
#[unstable(feature = "allocator_api", issue = "32838")]
1512+
pub fn into_raw_with_allocator(this: Self) -> (*const T, A) {
1513+
let this = mem::ManuallyDrop::new(this);
1514+
let ptr = Self::as_ptr(&this);
1515+
// Safety: `this` is ManuallyDrop so the allocator will not be double-dropped
1516+
let alloc = unsafe { ptr::read(Self::allocator(&this)) };
1517+
(ptr, alloc)
1518+
}
1519+
14921520
/// Provides a raw pointer to the data.
14931521
///
14941522
/// The counts are not affected in any way and the `Arc` is not consumed. The pointer is valid for
@@ -2724,6 +2752,45 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
27242752
result
27252753
}
27262754

2755+
/// Consumes the `Weak<T>`, returning the wrapped pointer and allocator.
2756+
///
2757+
/// This converts the weak pointer into a raw pointer, while still preserving the ownership of
2758+
/// one weak reference (the weak count is not modified by this operation). It can be turned
2759+
/// back into the `Weak<T>` with [`from_raw_in`].
2760+
///
2761+
/// The same restrictions of accessing the target of the pointer as with
2762+
/// [`as_ptr`] apply.
2763+
///
2764+
/// # Examples
2765+
///
2766+
/// ```
2767+
/// #![feature(allocator_api)]
2768+
/// use std::sync::{Arc, Weak};
2769+
/// use std::alloc::System;
2770+
///
2771+
/// let strong = Arc::new_in("hello".to_owned(), System);
2772+
/// let weak = Arc::downgrade(&strong);
2773+
/// let (raw, alloc) = weak.into_raw_with_allocator();
2774+
///
2775+
/// assert_eq!(1, Arc::weak_count(&strong));
2776+
/// assert_eq!("hello", unsafe { &*raw });
2777+
///
2778+
/// drop(unsafe { Weak::from_raw_in(raw, alloc) });
2779+
/// assert_eq!(0, Arc::weak_count(&strong));
2780+
/// ```
2781+
///
2782+
/// [`from_raw_in`]: Weak::from_raw_in
2783+
/// [`as_ptr`]: Weak::as_ptr
2784+
#[must_use = "losing the pointer will leak memory"]
2785+
#[unstable(feature = "allocator_api", issue = "32838")]
2786+
pub fn into_raw_with_allocator(self) -> (*const T, A) {
2787+
let this = mem::ManuallyDrop::new(self);
2788+
let result = this.as_ptr();
2789+
// Safety: `this` is ManuallyDrop so the allocator will not be double-dropped
2790+
let alloc = unsafe { ptr::read(Self::allocator(&this)) };
2791+
(result, alloc)
2792+
}
2793+
27272794
/// Converts a raw pointer previously created by [`into_raw`] back into `Weak<T>` in the provided
27282795
/// allocator.
27292796
///

0 commit comments

Comments
 (0)