summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorAlexander Light <allight@cs.brown.edu>2014-11-21 17:56:33 -0500
committerAlexander Light <allight@cs.brown.edu>2014-11-21 17:56:33 -0500
commit69861df831a2d0c551b46a291c2530aeeab6c704 (patch)
treefe9457503bc7622c5d5fab66a6819153033b7b7e /src/liballoc
parent4c36ad01e709448e8090b79ac96d0a6bb0607b23 (diff)
downloadrust-69861df831a2d0c551b46a291c2530aeeab6c704.tar.gz
rust-69861df831a2d0c551b46a291c2530aeeab6c704.zip
Shuffle locations for Deref
Remove both `strong_count` and `weak_count` from `Weak`s and make the
methods bare functions so as not to cause trouble with `deref`.
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/arc.rs81
-rw-r--r--src/liballoc/rc.rs68
2 files changed, 57 insertions, 92 deletions
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,17 +117,17 @@ impl<T> Arc<T> {
         // 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 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(&self) -> uint { self.inner().strong.load(atomic::SeqCst) }
-}
+/// 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> {
@@ -257,29 +257,6 @@ impl<T: Sync + Send> Weak<T> {
         // 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,17 +211,17 @@ impl<T> Rc<T> {
             _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 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(&self) -> uint { self.strong() }
-}
+/// 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.
 ///
@@ -230,7 +230,7 @@ impl<T> Rc<T> {
 #[inline]
 #[experimental]
 pub fn is_unique<T>(rc: &Rc<T>) -> 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<T> Weak<T> {
             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<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};
@@ -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]