Skip to content

Commit 49b6a37

Browse files
committed
Implement alloc::sync::{Arc,Weak,UniqueArc} with alloc::raw_rc types
1 parent 9c67c67 commit 49b6a37

File tree

10 files changed

+613
-1387
lines changed

10 files changed

+613
-1387
lines changed

library/alloc/src/raw_rc/raw_rc.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,16 @@ where
244244
self.weak.into_raw_parts()
245245
}
246246

247+
// `is_unique` only exists on `Arc`, so we need this `#[cfg(not(no_sync))]`. It can be removed
248+
// if `Rc::is_unique` is added.
249+
#[cfg(not(no_sync))]
250+
pub(crate) unsafe fn is_unique<R>(&self) -> bool
251+
where
252+
R: RefCounter,
253+
{
254+
unsafe { is_unique::<R>(self.value_ptr()) }
255+
}
256+
247257
#[cfg(not(no_global_oom_handling))]
248258
pub(crate) unsafe fn make_mut<R>(&mut self) -> &mut T
249259
where
@@ -742,6 +752,23 @@ impl<A> RawRc<dyn Any, A> {
742752
}
743753
}
744754

755+
#[cfg(not(no_sync))]
756+
impl<A> RawRc<dyn Any + Send + Sync, A> {
757+
pub(crate) fn downcast<T>(self) -> Result<RawRc<T, A>, Self>
758+
where
759+
T: Any,
760+
{
761+
if self.as_ref().is::<T>() { Ok(unsafe { self.downcast_unchecked() }) } else { Err(self) }
762+
}
763+
764+
pub(crate) unsafe fn downcast_unchecked<T>(self) -> RawRc<T, A>
765+
where
766+
T: Any,
767+
{
768+
unsafe { self.cast() }
769+
}
770+
}
771+
745772
impl<T, A> AsRef<T> for RawRc<T, A>
746773
where
747774
T: ?Sized,

library/alloc/src/raw_rc/raw_weak.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,19 @@ where
282282
!ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr())
283283
}
284284

285+
/// Returns the `RefCounts` object inside the reference-counted allocation if `self` is
286+
/// non-dangling.
287+
#[cfg(not(no_sync))]
288+
pub(crate) fn ref_counts(&self) -> Option<&RefCounts> {
289+
(!is_dangling(self.ptr.cast())).then(|| unsafe { self.ref_counts_unchecked() })
290+
}
291+
285292
/// Returns the `RefCounts` object inside the reference-counted allocation, assume `self` is
286293
/// non-dangling.
287294
///
288295
/// # Safety
289296
///
290297
/// `self` is non-dangling.
291-
#[cfg(not(no_global_oom_handling))]
292298
pub(super) unsafe fn ref_counts_unchecked(&self) -> &RefCounts {
293299
unsafe { self.value_ptr_unchecked().ref_counts_ptr().as_ref() }
294300
}

library/alloc/src/rc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ use crate::vec::Vec;
272272

273273
type RefCounter = Cell<usize>;
274274

275-
unsafe impl raw_rc::RefCounter for RefCounter {
275+
unsafe impl raw_rc::RefCounter for Cell<usize> {
276276
#[inline]
277277
fn increment(&self) {
278278
// NOTE: If you `mem::forget` `Rc`s (or `Weak`s), drop is skipped and the ref-count

0 commit comments

Comments
 (0)