Skip to content

Commit 052a140

Browse files
committed
Add {Arc,Weak}::into_raw_with_allocator
1 parent a2002ec commit 052a140

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

library/alloc/src/sync.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,34 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
14971497
ptr
14981498
}
14991499

1500+
/// Consumes the `Arc`, returning the wrapped pointer and allocator.
1501+
///
1502+
/// To avoid a memory leak the pointer must be converted back to an `Arc` using
1503+
/// [`Arc::from_raw_in`].
1504+
///
1505+
/// # Examples
1506+
///
1507+
/// ```
1508+
/// #![feature(allocator_api)]
1509+
/// use std::sync::Arc;
1510+
/// use std::alloc::System;
1511+
///
1512+
/// let x = Arc::new_in("hello".to_owned(), System);
1513+
/// let (ptr, alloc) = Arc::into_raw_with_allocator(x);
1514+
/// assert_eq!(unsafe { &*ptr }, "hello");
1515+
/// let x = unsafe { Arc::from_raw_in(ptr, alloc) };
1516+
/// assert_eq!(&*x, "hello");
1517+
/// ```
1518+
#[must_use = "losing the pointer will leak memory"]
1519+
#[unstable(feature = "allocator_api", issue = "32838")]
1520+
pub fn into_raw_with_allocator(this: Self) -> (*const T, A) {
1521+
let this = mem::ManuallyDrop::new(this);
1522+
let ptr = Self::as_ptr(&this);
1523+
// Safety: `this` is ManuallyDrop so the allocator will not be double-dropped
1524+
let alloc = unsafe { ptr::read(Self::allocator(&this)) };
1525+
(ptr, alloc)
1526+
}
1527+
15001528
/// Provides a raw pointer to the data.
15011529
///
15021530
/// The counts are not affected in any way and the `Arc` is not consumed. The pointer is valid for
@@ -2739,6 +2767,45 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
27392767
result
27402768
}
27412769

2770+
/// Consumes the `Weak<T>`, returning the wrapped pointer and allocator.
2771+
///
2772+
/// This converts the weak pointer into a raw pointer, while still preserving the ownership of
2773+
/// one weak reference (the weak count is not modified by this operation). It can be turned
2774+
/// back into the `Weak<T>` with [`from_raw_in`].
2775+
///
2776+
/// The same restrictions of accessing the target of the pointer as with
2777+
/// [`as_ptr`] apply.
2778+
///
2779+
/// # Examples
2780+
///
2781+
/// ```
2782+
/// #![feature(allocator_api)]
2783+
/// use std::sync::{Arc, Weak};
2784+
/// use std::alloc::System;
2785+
///
2786+
/// let strong = Arc::new_in("hello".to_owned(), System);
2787+
/// let weak = Arc::downgrade(&strong);
2788+
/// let (raw, alloc) = weak.into_raw_with_allocator();
2789+
///
2790+
/// assert_eq!(1, Arc::weak_count(&strong));
2791+
/// assert_eq!("hello", unsafe { &*raw });
2792+
///
2793+
/// drop(unsafe { Weak::from_raw_in(raw, alloc) });
2794+
/// assert_eq!(0, Arc::weak_count(&strong));
2795+
/// ```
2796+
///
2797+
/// [`from_raw_in`]: Weak::from_raw_in
2798+
/// [`as_ptr`]: Weak::as_ptr
2799+
#[must_use = "losing the pointer will leak memory"]
2800+
#[unstable(feature = "allocator_api", issue = "32838")]
2801+
pub fn into_raw_with_allocator(self) -> (*const T, A) {
2802+
let this = mem::ManuallyDrop::new(self);
2803+
let result = this.as_ptr();
2804+
// Safety: `this` is ManuallyDrop so the allocator will not be double-dropped
2805+
let alloc = unsafe { ptr::read(Self::allocator(&this)) };
2806+
(result, alloc)
2807+
}
2808+
27422809
/// Converts a raw pointer previously created by [`into_raw`] back into `Weak<T>` in the provided
27432810
/// allocator.
27442811
///

0 commit comments

Comments
 (0)