diff options
| author | Alexander Light <scialexlight@gmail.com> | 2014-11-20 16:38:36 -0500 |
|---|---|---|
| committer | Alexander Light <scialexlight@gmail.com> | 2014-11-21 15:42:01 -0500 |
| commit | 4c36ad01e709448e8090b79ac96d0a6bb0607b23 (patch) | |
| tree | cd77f0dbc10914aa365355a656916d455e121eee /src/liballoc/rc.rs | |
| parent | 96c8f2b0c1846756e617f1f1fc1372c506e24248 (diff) | |
| download | rust-4c36ad01e709448e8090b79ac96d0a6bb0607b23.tar.gz rust-4c36ad01e709448e8090b79ac96d0a6bb0607b23.zip | |
Add `weak_count` and `strong_count` to Rc and Arc
These functions allow you to see how many weak and strong references there are to an `Arc`, `Rc`, or an `rc::Weak`. Due to the design of `Arc` it is not possible to get the number of weak references of an arbitrary `arc::Weak`. Look in `arc.rs` for a more in-depth explanation. On `arc::Arc` and `arc::Weak` these operations are wait-free and atomic.
Diffstat (limited to 'src/liballoc/rc.rs')
| -rw-r--r-- | src/liballoc/rc.rs | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 501f915461a..ba6f5cde2f4 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -211,6 +211,16 @@ 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 strong references to this value. + #[inline] + #[experimental] + pub fn strong_count(&self) -> uint { self.strong() } } /// Returns true if the `Rc` currently has unique ownership. @@ -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 + rc.weak_count() == 0 && rc.strong_count() == 1 } /// Unwraps the contained value if the `Rc` has unique ownership. @@ -424,6 +433,20 @@ 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] @@ -567,6 +590,40 @@ mod tests { } #[test] + fn test_strong_count() { + let a = Rc::new(0u32); + assert!(a.strong_count() == 1); + let w = a.downgrade(); + assert!(a.strong_count() == 1); + let b = w.upgrade().expect("upgrade of live rc failed"); + assert!(b.strong_count() == 2); + assert!(a.strong_count() == 2); + drop(w); + drop(a); + assert!(b.strong_count() == 1); + let c = b.clone(); + assert!(b.strong_count() == 2); + assert!(c.strong_count() == 2); + } + + #[test] + fn test_weak_count() { + let a = Rc::new(0u32); + assert!(a.strong_count() == 1); + assert!(a.weak_count() == 0); + let w = a.downgrade(); + assert!(a.strong_count() == 1); + assert!(w.weak_count() == 1); + drop(w); + assert!(a.strong_count() == 1); + assert!(a.weak_count() == 0); + let c = a.clone(); + assert!(a.strong_count() == 2); + assert!(a.weak_count() == 0); + assert!(c.downgrade().weak_count() == 1); + } + + #[test] fn try_unwrap() { let x = Rc::new(3u); assert_eq!(super::try_unwrap(x), Ok(3u)); |
