Skip to content

Commit 77d1f0b

Browse files
author
Jakub Bukaj
committed
rollup merge of #19193: scialex/rc-counts
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. This sort of information is useful for creating dynamically cleared caches for use in OS development, for example holding pages of files in memory until the address space is needed for something else.
2 parents 1e5de8c + 69861df commit 77d1f0b

File tree

2 files changed

+100
-4
lines changed

2 files changed

+100
-4
lines changed

src/liballoc/arc.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ impl<T> Arc<T> {
119119
}
120120
}
121121

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 }
126+
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) }
131+
122132
#[unstable = "waiting on stability of Clone"]
123133
impl<T> Clone for Arc<T> {
124134
/// Duplicate an atomically reference counted wrapper.
@@ -321,7 +331,7 @@ mod tests {
321331
use std::sync::atomic;
322332
use std::task;
323333
use std::vec::Vec;
324-
use super::{Arc, Weak};
334+
use super::{Arc, Weak, weak_count, strong_count};
325335
use std::sync::Mutex;
326336

327337
struct Canary(*mut atomic::AtomicUint);
@@ -465,6 +475,49 @@ mod tests {
465475
drop(arc_weak);
466476
}
467477

478+
#[test]
479+
fn test_strong_count() {
480+
let a = Arc::new(0u32);
481+
assert!(strong_count(&a) == 1);
482+
let w = a.downgrade();
483+
assert!(strong_count(&a) == 1);
484+
let b = w.upgrade().expect("");
485+
assert!(strong_count(&b) == 2);
486+
assert!(strong_count(&a) == 2);
487+
drop(w);
488+
drop(a);
489+
assert!(strong_count(&b) == 1);
490+
let c = b.clone();
491+
assert!(strong_count(&b) == 2);
492+
assert!(strong_count(&c) == 2);
493+
}
494+
495+
#[test]
496+
fn test_weak_count() {
497+
let a = Arc::new(0u32);
498+
assert!(strong_count(&a) == 1);
499+
assert!(weak_count(&a) == 0);
500+
let w = a.downgrade();
501+
assert!(strong_count(&a) == 1);
502+
assert!(weak_count(&a) == 1);
503+
let x = w.clone();
504+
assert!(weak_count(&a) == 2);
505+
drop(w);
506+
drop(x);
507+
assert!(strong_count(&a) == 1);
508+
assert!(weak_count(&a) == 0);
509+
let c = a.clone();
510+
assert!(strong_count(&a) == 2);
511+
assert!(weak_count(&a) == 0);
512+
let d = c.downgrade();
513+
assert!(weak_count(&c) == 1);
514+
assert!(strong_count(&c) == 2);
515+
516+
drop(a);
517+
drop(c);
518+
drop(d);
519+
}
520+
468521
#[test]
469522
fn show_arc() {
470523
let a = Arc::new(5u32);

src/liballoc/rc.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,24 @@ impl<T> Rc<T> {
213213
}
214214
}
215215

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 }
220+
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() }
225+
216226
/// Returns true if the `Rc` currently has unique ownership.
217227
///
218228
/// Unique ownership means that there are no other `Rc` or `Weak` values
219229
/// that share the same contents.
220230
#[inline]
221231
#[experimental]
222232
pub fn is_unique<T>(rc: &Rc<T>) -> bool {
223-
// note that we hold both a strong and a weak reference
224-
rc.strong() == 1 && rc.weak() == 1
233+
weak_count(rc) == 0 && strong_count(rc) == 1
225234
}
226235

227236
/// Unwraps the contained value if the `Rc` has unique ownership.
@@ -489,7 +498,7 @@ impl<T> RcBoxPtr<T> for Weak<T> {
489498
#[cfg(test)]
490499
#[allow(experimental)]
491500
mod tests {
492-
use super::{Rc, Weak};
501+
use super::{Rc, Weak, weak_count, strong_count};
493502
use std::cell::RefCell;
494503
use std::option::{Option, Some, None};
495504
use std::result::{Err, Ok};
@@ -566,6 +575,40 @@ mod tests {
566575
assert!(super::is_unique(&x));
567576
}
568577

578+
#[test]
579+
fn test_strong_count() {
580+
let a = Rc::new(0u32);
581+
assert!(strong_count(&a) == 1);
582+
let w = a.downgrade();
583+
assert!(strong_count(&a) == 1);
584+
let b = w.upgrade().expect("upgrade of live rc failed");
585+
assert!(strong_count(&b) == 2);
586+
assert!(strong_count(&a) == 2);
587+
drop(w);
588+
drop(a);
589+
assert!(strong_count(&b) == 1);
590+
let c = b.clone();
591+
assert!(strong_count(&b) == 2);
592+
assert!(strong_count(&c) == 2);
593+
}
594+
595+
#[test]
596+
fn test_weak_count() {
597+
let a = Rc::new(0u32);
598+
assert!(strong_count(&a) == 1);
599+
assert!(weak_count(&a) == 0);
600+
let w = a.downgrade();
601+
assert!(strong_count(&a) == 1);
602+
assert!(weak_count(&a) == 1);
603+
drop(w);
604+
assert!(strong_count(&a) == 1);
605+
assert!(weak_count(&a) == 0);
606+
let c = a.clone();
607+
assert!(strong_count(&a) == 2);
608+
assert!(weak_count(&a) == 0);
609+
drop(c);
610+
}
611+
569612
#[test]
570613
fn try_unwrap() {
571614
let x = Rc::new(3u);

0 commit comments

Comments
 (0)