Skip to content

Commit 69861df

Browse files
author
Alexander Light
committed
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`.
1 parent 4c36ad0 commit 69861df

File tree

2 files changed

+57
-92
lines changed

2 files changed

+57
-92
lines changed

src/liballoc/arc.rs

Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,17 @@ impl<T> Arc<T> {
117117
// these contents.
118118
unsafe { &*self._ptr }
119119
}
120+
}
120121

121-
/// Get the number of weak references to this value.
122-
#[inline]
123-
#[experimental]
124-
pub fn weak_count(&self) -> uint { self.inner().weak.load(atomic::SeqCst) - 1 }
122+
/// Get the number of weak references to this value.
123+
#[inline]
124+
#[experimental]
125+
pub fn weak_count<T>(this: &Arc<T>) -> uint { this.inner().weak.load(atomic::SeqCst) - 1 }
125126

126-
/// Get the number of strong references to this value.
127-
#[inline]
128-
#[experimental]
129-
pub fn strong_count(&self) -> uint { self.inner().strong.load(atomic::SeqCst) }
130-
}
127+
/// Get the number of strong references to this value.
128+
#[inline]
129+
#[experimental]
130+
pub fn strong_count<T>(this: &Arc<T>) -> uint { this.inner().strong.load(atomic::SeqCst) }
131131

132132
#[unstable = "waiting on stability of Clone"]
133133
impl<T> Clone for Arc<T> {
@@ -257,29 +257,6 @@ impl<T: Sync + Send> Weak<T> {
257257
// See comments above for why this is "safe"
258258
unsafe { &*self._ptr }
259259
}
260-
261-
// Why is there no `weak_count()`?
262-
//
263-
// It is not possible to determine the number of weak references with only a weak reference
264-
// accurately in a wait-free manner. This is because we have a data-race with the last strong
265-
// reference's `drop` method. If that operation pauses between decrementing the strong
266-
// reference count to 0 and removing the implicit weak reference that the strong references
267-
// share then we will incorrectly think there is one more weak reference then there really is.
268-
//
269-
// We cannot get around this without making parts of this object no longer wait-free, since we
270-
// would either need to use locks to get mutual exclusion with `drop` or make it so that the
271-
// weak and strong reference counts can be modified atomically together. The first option
272-
// destroys wait-freedom by adding a lock and the second (in addition to being annoying to
273-
// implement) would make many operations (at least `downgrade` and both `clone`s) go from being
274-
// wait-free to merely lock-free, as we would need to do a manual CAS loop to get around other
275-
// threads modifying the other value in each of these cases.
276-
277-
/// Get the number of strong references to this value.
278-
///
279-
/// If this function returns 0 then the value has been freed.
280-
#[inline]
281-
#[experimental]
282-
pub fn strong_count(&self) -> uint { self.inner().strong.load(atomic::SeqCst) }
283260
}
284261

285262
#[experimental = "Weak pointers may not belong in this module."]
@@ -354,7 +331,7 @@ mod tests {
354331
use std::sync::atomic;
355332
use std::task;
356333
use std::vec::Vec;
357-
use super::{Arc, Weak};
334+
use super::{Arc, Weak, weak_count, strong_count};
358335
use std::sync::Mutex;
359336

360337
struct Canary(*mut atomic::AtomicUint);
@@ -501,38 +478,40 @@ mod tests {
501478
#[test]
502479
fn test_strong_count() {
503480
let a = Arc::new(0u32);
504-
assert!(a.strong_count() == 1);
481+
assert!(strong_count(&a) == 1);
505482
let w = a.downgrade();
506-
assert!(a.strong_count() == 1);
483+
assert!(strong_count(&a) == 1);
507484
let b = w.upgrade().expect("");
508-
assert!(b.strong_count() == 2);
509-
assert!(a.strong_count() == 2);
485+
assert!(strong_count(&b) == 2);
486+
assert!(strong_count(&a) == 2);
510487
drop(w);
511488
drop(a);
512-
assert!(b.strong_count() == 1);
489+
assert!(strong_count(&b) == 1);
513490
let c = b.clone();
514-
assert!(b.strong_count() == 2);
515-
assert!(c.strong_count() == 2);
491+
assert!(strong_count(&b) == 2);
492+
assert!(strong_count(&c) == 2);
516493
}
517494

518495
#[test]
519496
fn test_weak_count() {
520497
let a = Arc::new(0u32);
521-
assert!(a.strong_count() == 1);
522-
assert!(a.weak_count() == 0);
498+
assert!(strong_count(&a) == 1);
499+
assert!(weak_count(&a) == 0);
523500
let w = a.downgrade();
524-
assert!(a.strong_count() == 1);
525-
assert!(w.strong_count() == 1);
526-
assert!(a.weak_count() == 1);
501+
assert!(strong_count(&a) == 1);
502+
assert!(weak_count(&a) == 1);
503+
let x = w.clone();
504+
assert!(weak_count(&a) == 2);
527505
drop(w);
528-
assert!(a.strong_count() == 1);
529-
assert!(a.weak_count() == 0);
506+
drop(x);
507+
assert!(strong_count(&a) == 1);
508+
assert!(weak_count(&a) == 0);
530509
let c = a.clone();
531-
assert!(a.strong_count() == 2);
532-
assert!(a.weak_count() == 0);
510+
assert!(strong_count(&a) == 2);
511+
assert!(weak_count(&a) == 0);
533512
let d = c.downgrade();
534-
assert!(c.weak_count() == 1);
535-
assert!(c.strong_count() == 2);
513+
assert!(weak_count(&c) == 1);
514+
assert!(strong_count(&c) == 2);
536515

537516
drop(a);
538517
drop(c);

src/liballoc/rc.rs

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -211,17 +211,17 @@ impl<T> Rc<T> {
211211
_noshare: marker::NoSync
212212
}
213213
}
214+
}
214215

215-
/// Get the number of weak references to this value.
216-
#[inline]
217-
#[experimental]
218-
pub fn weak_count(&self) -> uint { self.weak() - 1 }
216+
/// Get the number of weak references to this value.
217+
#[inline]
218+
#[experimental]
219+
pub fn weak_count<T>(this: &Rc<T>) -> uint { this.weak() - 1 }
219220

220-
/// Get the number of strong references to this value.
221-
#[inline]
222-
#[experimental]
223-
pub fn strong_count(&self) -> uint { self.strong() }
224-
}
221+
/// Get the number of strong references to this value.
222+
#[inline]
223+
#[experimental]
224+
pub fn strong_count<T>(this: &Rc<T>) -> uint { this.strong() }
225225

226226
/// Returns true if the `Rc` currently has unique ownership.
227227
///
@@ -230,7 +230,7 @@ impl<T> Rc<T> {
230230
#[inline]
231231
#[experimental]
232232
pub fn is_unique<T>(rc: &Rc<T>) -> bool {
233-
rc.weak_count() == 0 && rc.strong_count() == 1
233+
weak_count(rc) == 0 && strong_count(rc) == 1
234234
}
235235

236236
/// Unwraps the contained value if the `Rc` has unique ownership.
@@ -433,20 +433,6 @@ impl<T> Weak<T> {
433433
Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync })
434434
}
435435
}
436-
437-
/// Get the number of weak references to this value.
438-
#[inline]
439-
#[experimental]
440-
pub fn weak_count(&self) -> uint {
441-
if self.strong() != 0 { self.weak() - 1 } else { self.weak() }
442-
}
443-
444-
/// Get the number of strong references to this value.
445-
///
446-
/// If this function returns 0 then the value has been freed.
447-
#[inline]
448-
#[experimental]
449-
pub fn strong_count(&self) -> uint { self.strong() }
450436
}
451437

452438
#[unsafe_destructor]
@@ -512,7 +498,7 @@ impl<T> RcBoxPtr<T> for Weak<T> {
512498
#[cfg(test)]
513499
#[allow(experimental)]
514500
mod tests {
515-
use super::{Rc, Weak};
501+
use super::{Rc, Weak, weak_count, strong_count};
516502
use std::cell::RefCell;
517503
use std::option::{Option, Some, None};
518504
use std::result::{Err, Ok};
@@ -592,35 +578,35 @@ mod tests {
592578
#[test]
593579
fn test_strong_count() {
594580
let a = Rc::new(0u32);
595-
assert!(a.strong_count() == 1);
581+
assert!(strong_count(&a) == 1);
596582
let w = a.downgrade();
597-
assert!(a.strong_count() == 1);
583+
assert!(strong_count(&a) == 1);
598584
let b = w.upgrade().expect("upgrade of live rc failed");
599-
assert!(b.strong_count() == 2);
600-
assert!(a.strong_count() == 2);
585+
assert!(strong_count(&b) == 2);
586+
assert!(strong_count(&a) == 2);
601587
drop(w);
602588
drop(a);
603-
assert!(b.strong_count() == 1);
589+
assert!(strong_count(&b) == 1);
604590
let c = b.clone();
605-
assert!(b.strong_count() == 2);
606-
assert!(c.strong_count() == 2);
591+
assert!(strong_count(&b) == 2);
592+
assert!(strong_count(&c) == 2);
607593
}
608594

609595
#[test]
610596
fn test_weak_count() {
611597
let a = Rc::new(0u32);
612-
assert!(a.strong_count() == 1);
613-
assert!(a.weak_count() == 0);
598+
assert!(strong_count(&a) == 1);
599+
assert!(weak_count(&a) == 0);
614600
let w = a.downgrade();
615-
assert!(a.strong_count() == 1);
616-
assert!(w.weak_count() == 1);
601+
assert!(strong_count(&a) == 1);
602+
assert!(weak_count(&a) == 1);
617603
drop(w);
618-
assert!(a.strong_count() == 1);
619-
assert!(a.weak_count() == 0);
604+
assert!(strong_count(&a) == 1);
605+
assert!(weak_count(&a) == 0);
620606
let c = a.clone();
621-
assert!(a.strong_count() == 2);
622-
assert!(a.weak_count() == 0);
623-
assert!(c.downgrade().weak_count() == 1);
607+
assert!(strong_count(&a) == 2);
608+
assert!(weak_count(&a) == 0);
609+
drop(c);
624610
}
625611

626612
#[test]

0 commit comments

Comments
 (0)