mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 03:33:59 +00:00
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`.
This commit is contained in:
parent
4c36ad01e7
commit
69861df831
@ -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 }
|
||||
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) }
|
||||
}
|
||||
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);
|
||||
|
@ -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 }
|
||||
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() }
|
||||
}
|
||||
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]
|
||||
|
Loading…
Reference in New Issue
Block a user