diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 2a087fa678c..4f744b0b2de 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -117,18 +117,18 @@ impl Arc { // these contents. unsafe { &*self._ptr } } - - /// Get the number of weak references to this value. - #[inline] - #[experimental] - pub fn weak_count(&self) -> uint { self.inner().weak.load(atomic::SeqCst) - 1 } - - /// Get the number of strong references to this value. - #[inline] - #[experimental] - pub fn strong_count(&self) -> uint { self.inner().strong.load(atomic::SeqCst) } } +/// Get the number of weak references to this value. +#[inline] +#[experimental] +pub fn weak_count(this: &Arc) -> uint { this.inner().weak.load(atomic::SeqCst) - 1 } + +/// Get the number of strong references to this value. +#[inline] +#[experimental] +pub fn strong_count(this: &Arc) -> uint { this.inner().strong.load(atomic::SeqCst) } + #[unstable = "waiting on stability of Clone"] impl Clone for Arc { /// Duplicate an atomically reference counted wrapper. @@ -257,29 +257,6 @@ impl Weak { // See comments above for why this is "safe" unsafe { &*self._ptr } } - - // Why is there no `weak_count()`? - // - // It is not possible to determine the number of weak references with only a weak reference - // accurately in a wait-free manner. This is because we have a data-race with the last strong - // reference's `drop` method. If that operation pauses between decrementing the strong - // reference count to 0 and removing the implicit weak reference that the strong references - // share then we will incorrectly think there is one more weak reference then there really is. - // - // We cannot get around this without making parts of this object no longer wait-free, since we - // would either need to use locks to get mutual exclusion with `drop` or make it so that the - // weak and strong reference counts can be modified atomically together. The first option - // destroys wait-freedom by adding a lock and the second (in addition to being annoying to - // implement) would make many operations (at least `downgrade` and both `clone`s) go from being - // wait-free to merely lock-free, as we would need to do a manual CAS loop to get around other - // threads modifying the other value in each of these cases. - - /// Get the number of strong references to this value. - /// - /// If this function returns 0 then the value has been freed. - #[inline] - #[experimental] - pub fn strong_count(&self) -> uint { self.inner().strong.load(atomic::SeqCst) } } #[experimental = "Weak pointers may not belong in this module."] @@ -354,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); @@ -501,38 +478,40 @@ mod tests { #[test] fn test_strong_count() { let a = Arc::new(0u32); - assert!(a.strong_count() == 1); + assert!(strong_count(&a) == 1); let w = a.downgrade(); - assert!(a.strong_count() == 1); + assert!(strong_count(&a) == 1); let b = w.upgrade().expect(""); - assert!(b.strong_count() == 2); - assert!(a.strong_count() == 2); + assert!(strong_count(&b) == 2); + assert!(strong_count(&a) == 2); drop(w); drop(a); - assert!(b.strong_count() == 1); + assert!(strong_count(&b) == 1); let c = b.clone(); - assert!(b.strong_count() == 2); - assert!(c.strong_count() == 2); + assert!(strong_count(&b) == 2); + assert!(strong_count(&c) == 2); } #[test] fn test_weak_count() { let a = Arc::new(0u32); - assert!(a.strong_count() == 1); - assert!(a.weak_count() == 0); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 0); let w = a.downgrade(); - assert!(a.strong_count() == 1); - assert!(w.strong_count() == 1); - assert!(a.weak_count() == 1); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 1); + let x = w.clone(); + assert!(weak_count(&a) == 2); drop(w); - assert!(a.strong_count() == 1); - assert!(a.weak_count() == 0); + drop(x); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 0); let c = a.clone(); - assert!(a.strong_count() == 2); - assert!(a.weak_count() == 0); + assert!(strong_count(&a) == 2); + assert!(weak_count(&a) == 0); let d = c.downgrade(); - assert!(c.weak_count() == 1); - assert!(c.strong_count() == 2); + assert!(weak_count(&c) == 1); + assert!(strong_count(&c) == 2); drop(a); drop(c); diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index ba6f5cde2f4..df84ac9aec9 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -211,18 +211,18 @@ impl Rc { _noshare: marker::NoSync } } - - /// Get the number of weak references to this value. - #[inline] - #[experimental] - pub fn weak_count(&self) -> uint { self.weak() - 1 } - - /// Get the number of strong references to this value. - #[inline] - #[experimental] - pub fn strong_count(&self) -> uint { self.strong() } } +/// Get the number of weak references to this value. +#[inline] +#[experimental] +pub fn weak_count(this: &Rc) -> uint { this.weak() - 1 } + +/// Get the number of strong references to this value. +#[inline] +#[experimental] +pub fn strong_count(this: &Rc) -> uint { this.strong() } + /// Returns true if the `Rc` currently has unique ownership. /// /// Unique ownership means that there are no other `Rc` or `Weak` values @@ -230,7 +230,7 @@ impl Rc { #[inline] #[experimental] pub fn is_unique(rc: &Rc) -> bool { - rc.weak_count() == 0 && rc.strong_count() == 1 + weak_count(rc) == 0 && strong_count(rc) == 1 } /// Unwraps the contained value if the `Rc` has unique ownership. @@ -433,20 +433,6 @@ impl Weak { Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }) } } - - /// Get the number of weak references to this value. - #[inline] - #[experimental] - pub fn weak_count(&self) -> uint { - if self.strong() != 0 { self.weak() - 1 } else { self.weak() } - } - - /// Get the number of strong references to this value. - /// - /// If this function returns 0 then the value has been freed. - #[inline] - #[experimental] - pub fn strong_count(&self) -> uint { self.strong() } } #[unsafe_destructor] @@ -512,7 +498,7 @@ impl RcBoxPtr for Weak { #[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}; @@ -592,35 +578,35 @@ mod tests { #[test] fn test_strong_count() { let a = Rc::new(0u32); - assert!(a.strong_count() == 1); + assert!(strong_count(&a) == 1); let w = a.downgrade(); - assert!(a.strong_count() == 1); + assert!(strong_count(&a) == 1); let b = w.upgrade().expect("upgrade of live rc failed"); - assert!(b.strong_count() == 2); - assert!(a.strong_count() == 2); + assert!(strong_count(&b) == 2); + assert!(strong_count(&a) == 2); drop(w); drop(a); - assert!(b.strong_count() == 1); + assert!(strong_count(&b) == 1); let c = b.clone(); - assert!(b.strong_count() == 2); - assert!(c.strong_count() == 2); + assert!(strong_count(&b) == 2); + assert!(strong_count(&c) == 2); } #[test] fn test_weak_count() { let a = Rc::new(0u32); - assert!(a.strong_count() == 1); - assert!(a.weak_count() == 0); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 0); let w = a.downgrade(); - assert!(a.strong_count() == 1); - assert!(w.weak_count() == 1); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 1); drop(w); - assert!(a.strong_count() == 1); - assert!(a.weak_count() == 0); + assert!(strong_count(&a) == 1); + assert!(weak_count(&a) == 0); let c = a.clone(); - assert!(a.strong_count() == 2); - assert!(a.weak_count() == 0); - assert!(c.downgrade().weak_count() == 1); + assert!(strong_count(&a) == 2); + assert!(weak_count(&a) == 0); + drop(c); } #[test]