diff options
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/arc.rs | 55 | ||||
| -rw-r--r-- | src/liballoc/boxed.rs | 10 | ||||
| -rw-r--r-- | src/liballoc/rc.rs | 49 |
3 files changed, 103 insertions, 11 deletions
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index c4f53d74467..4f744b0b2de 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -119,6 +119,16 @@ impl<T> Arc<T> { } } +/// Get the number of weak references to this value. +#[inline] +#[experimental] +pub fn weak_count<T>(this: &Arc<T>) -> uint { this.inner().weak.load(atomic::SeqCst) - 1 } + +/// Get the number of strong references to this value. +#[inline] +#[experimental] +pub fn strong_count<T>(this: &Arc<T>) -> uint { this.inner().strong.load(atomic::SeqCst) } + #[unstable = "waiting on stability of Clone"] impl<T> Clone for Arc<T> { /// Duplicate an atomically reference counted wrapper. @@ -321,7 +331,7 @@ mod tests { use std::sync::atomic; use std::task; use std::vec::Vec; - use super::{Arc, Weak}; + use super::{Arc, Weak, weak_count, strong_count}; use std::sync::Mutex; struct Canary(*mut atomic::AtomicUint); @@ -466,6 +476,49 @@ mod tests { } #[test] + fn test_strong_count() { + let a = Arc::new(0u32); + assert!(strong_count(&a) == 1); + let w = a.downgrade(); + assert!(strong_count(&a) == 1); + let b = w.upgrade().expect(""); + assert!(strong_count(&b) == 2); + assert!(strong_count(&a) == 2); + drop(w); + drop(a); + assert!(strong_count(&b) == 1); + let c = b.clone(); + assert!(strong_count(&b) == 2); + assert!(strong_count(&c) == 2); + } + + #[test] + fn test_weak_count() { + let a = Arc::new(0u32); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 0); + let w = a.downgrade(); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 1); + let x = w.clone(); + assert!(weak_count(&a) == 2); + drop(w); + drop(x); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 0); + let c = a.clone(); + assert!(strong_count(&a) == 2); + assert!(weak_count(&a) == 0); + let d = c.downgrade(); + assert!(weak_count(&c) == 1); + assert!(strong_count(&c) == 2); + + drop(a); + drop(c); + drop(d); + } + + #[test] fn show_arc() { let a = Arc::new(5u32); assert!(format!("{}", a).as_slice() == "5") diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 26f8522e1c1..000dda59e3d 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -15,7 +15,6 @@ use core::clone::Clone; use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; use core::default::Default; use core::fmt; -use core::intrinsics; use core::kinds::Sized; use core::mem; use core::option::Option; @@ -104,17 +103,14 @@ pub trait BoxAny { } #[stable] -impl BoxAny for Box<Any+'static> { +impl BoxAny for Box<Any> { #[inline] - fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any+'static>> { + fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> { if self.is::<T>() { unsafe { // Get the raw representation of the trait object let to: TraitObject = - *mem::transmute::<&Box<Any>, &TraitObject>(&self); - - // Prevent destructor on self being run - intrinsics::forget(self); + mem::transmute::<Box<Any>, TraitObject>(self); // Extract the data pointer Ok(mem::transmute(to.data)) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 501f915461a..df84ac9aec9 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -213,6 +213,16 @@ impl<T> Rc<T> { } } +/// Get the number of weak references to this value. +#[inline] +#[experimental] +pub fn weak_count<T>(this: &Rc<T>) -> uint { this.weak() - 1 } + +/// Get the number of strong references to this value. +#[inline] +#[experimental] +pub fn strong_count<T>(this: &Rc<T>) -> uint { this.strong() } + /// Returns true if the `Rc` currently has unique ownership. /// /// Unique ownership means that there are no other `Rc` or `Weak` values @@ -220,8 +230,7 @@ impl<T> Rc<T> { #[inline] #[experimental] pub fn is_unique<T>(rc: &Rc<T>) -> bool { - // note that we hold both a strong and a weak reference - rc.strong() == 1 && rc.weak() == 1 + weak_count(rc) == 0 && strong_count(rc) == 1 } /// Unwraps the contained value if the `Rc` has unique ownership. @@ -489,7 +498,7 @@ impl<T> RcBoxPtr<T> for Weak<T> { #[cfg(test)] #[allow(experimental)] mod tests { - use super::{Rc, Weak}; + use super::{Rc, Weak, weak_count, strong_count}; use std::cell::RefCell; use std::option::{Option, Some, None}; use std::result::{Err, Ok}; @@ -567,6 +576,40 @@ mod tests { } #[test] + fn test_strong_count() { + let a = Rc::new(0u32); + assert!(strong_count(&a) == 1); + let w = a.downgrade(); + assert!(strong_count(&a) == 1); + let b = w.upgrade().expect("upgrade of live rc failed"); + assert!(strong_count(&b) == 2); + assert!(strong_count(&a) == 2); + drop(w); + drop(a); + assert!(strong_count(&b) == 1); + let c = b.clone(); + assert!(strong_count(&b) == 2); + assert!(strong_count(&c) == 2); + } + + #[test] + fn test_weak_count() { + let a = Rc::new(0u32); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 0); + let w = a.downgrade(); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 1); + drop(w); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 0); + let c = a.clone(); + assert!(strong_count(&a) == 2); + assert!(weak_count(&a) == 0); + drop(c); + } + + #[test] fn try_unwrap() { let x = Rc::new(3u); assert_eq!(super::try_unwrap(x), Ok(3u)); |
