aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/weakref.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/weakref.rs')
-rw-r--r--components/script/dom/bindings/weakref.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/components/script/dom/bindings/weakref.rs b/components/script/dom/bindings/weakref.rs
index 248944d9962..e311d4a40bb 100644
--- a/components/script/dom/bindings/weakref.rs
+++ b/components/script/dom/bindings/weakref.rs
@@ -19,7 +19,9 @@ use js::jsapi::{JSTracer, JS_GetReservedSlot, JS_SetReservedSlot};
use js::jsval::PrivateValue;
use libc::c_void;
use std::cell::{Cell, UnsafeCell};
+use std::iter::Iterator;
use std::mem;
+use std::ops::{Deref, DerefMut, Drop};
use util::mem::HeapSizeOf;
/// The index of the slot wherein a pointer to the weak holder cell is
@@ -113,6 +115,25 @@ impl<T: WeakReferenceable> HeapSizeOf for WeakRef<T> {
}
}
+impl<T: WeakReferenceable> PartialEq for WeakRef<T> {
+ fn eq(&self, other: &Self) -> bool {
+ unsafe {
+ (**self.ptr).value.get() == (**other.ptr).value.get()
+ }
+ }
+}
+
+impl<T: WeakReferenceable> PartialEq<T> for WeakRef<T> {
+ fn eq(&self, other: &T) -> bool {
+ unsafe {
+ match (**self.ptr).value.get() {
+ Some(ptr) => *ptr == other,
+ None => false,
+ }
+ }
+ }
+}
+
no_jsmanaged_fields!(WeakRef<T: WeakReferenceable>);
impl<T: WeakReferenceable> Drop for WeakRef<T> {
@@ -182,3 +203,81 @@ impl<T: WeakReferenceable> JSTraceable for MutableWeakRef<T> {
}
}
}
+
+/// A vector of weak references. On tracing, the vector retains
+/// only references which still point to live objects.
+#[allow_unrooted_interior]
+#[derive(HeapSizeOf)]
+pub struct WeakRefVec<T: WeakReferenceable> {
+ vec: Vec<WeakRef<T>>,
+}
+
+impl<T: WeakReferenceable> WeakRefVec<T> {
+ /// Create a new vector of weak references.
+ pub fn new() -> Self {
+ WeakRefVec { vec: vec![] }
+ }
+
+ /// Calls a function on each reference which still points to a
+ /// live object. The order of the references isn't preserved.
+ pub fn update<F: FnMut(WeakRefEntry<T>)>(&mut self, mut f: F) {
+ let mut i = 0;
+ while i < self.vec.len() {
+ if self.vec[i].is_alive() {
+ f(WeakRefEntry { vec: self, index: &mut i });
+ } else {
+ self.vec.swap_remove(i);
+ }
+ }
+ }
+
+ /// Clears the vector of its dead references.
+ pub fn retain_alive(&mut self) {
+ self.update(|_| ());
+ }
+}
+
+impl<T: WeakReferenceable> Deref for WeakRefVec<T> {
+ type Target = Vec<WeakRef<T>>;
+
+ fn deref(&self) -> &Vec<WeakRef<T>> {
+ &self.vec
+ }
+}
+
+impl<T: WeakReferenceable> DerefMut for WeakRefVec<T> {
+ fn deref_mut(&mut self) -> &mut Vec<WeakRef<T>> {
+ &mut self.vec
+ }
+}
+
+/// An entry of a vector of weak references. Passed to the closure
+/// given to `WeakRefVec::update`.
+#[allow_unrooted_interior]
+pub struct WeakRefEntry<'a, T: WeakReferenceable + 'a> {
+ vec: &'a mut WeakRefVec<T>,
+ index: &'a mut usize,
+}
+
+impl<'a, T: WeakReferenceable + 'a> WeakRefEntry<'a, T> {
+ /// Remove the entry from the underlying vector of weak references.
+ pub fn remove(self) -> WeakRef<T> {
+ let ref_ = self.vec.swap_remove(*self.index);
+ mem::forget(self);
+ ref_
+ }
+}
+
+impl<'a, T: WeakReferenceable + 'a> Deref for WeakRefEntry<'a, T> {
+ type Target = WeakRef<T>;
+
+ fn deref(&self) -> &WeakRef<T> {
+ &self.vec[*self.index]
+ }
+}
+
+impl<'a, T: WeakReferenceable + 'a> Drop for WeakRefEntry<'a, T> {
+ fn drop(&mut self) {
+ *self.index += 1;
+ }
+}