diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index f0a4902bb9235..8fa535b6ea4b4 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -937,6 +937,7 @@ impl + DoubleEndedIterator>> // making these arbitrary sub-range iterators. However the logic to construct these paths // efficiently is fairly involved, so this is a FIXME. The sub-range iterators also wouldn't be // able to accurately predict size, so those iterators can't implement ExactSizeIterator. + #[inline] fn next(&mut self) -> Option<(K, V)> { loop { // We want the smallest element, so try to get the top of the left stack @@ -1030,6 +1031,7 @@ impl + DoubleEndedIterator>> } impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> { + #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() } fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } } @@ -1040,20 +1042,24 @@ impl<'a, K, V> ExactSizeIterator<(&'a K, &'a V)> for Entries<'a, K, V> {} impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> { + #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() } fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } } impl<'a, K, V> DoubleEndedIterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> { + #[inline] fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next_back() } } impl<'a, K, V> ExactSizeIterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {} impl Iterator<(K, V)> for MoveEntries { + #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() } fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } } impl DoubleEndedIterator<(K, V)> for MoveEntries { + #[inline] fn next_back(&mut self) -> Option<(K, V)> { self.inner.next_back() } } impl ExactSizeIterator<(K, V)> for MoveEntries {} @@ -1130,6 +1136,25 @@ impl BTreeMap { } } + /// An intrusive version of `.iter()`. The closure will be called once with + /// every key/value pair in the tree. + /// + /// This is faster than calling `.iter()`, but is far less composable. + #[inline] + #[experimental = "relies on unboxed closures"] + pub fn intrusive_iter(&self, mut f: F) { + fn intrusive_iter_impl(node: &Node, f: &mut F) { + for ti in node.iter() { + match ti { + Elem(k, v) => (*f)(k, v), + Edge(e) => intrusive_iter_impl(e, f), + } + } + } + + intrusive_iter_impl(&self.root, &mut f); + } + /// Gets a mutable iterator over the entries of the map. #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn iter_mut<'a>(&'a mut self) -> MutEntries<'a, K, V> { @@ -1144,6 +1169,25 @@ impl BTreeMap { } } + /// An intrusive version of `.iter_mut()`. The closure will be called once + /// with every key/value pair in the tree. + /// + /// This is faster than calling `.iter_mut()`, but is far less composable. + #[inline] + #[experimental = "relies on unboxed closures"] + pub fn intrusive_iter_mut(&mut self, mut f: F) { + fn intrusive_iter_mut_impl(node: &mut Node, f: &mut F) { + for ti in node.iter_mut() { + match ti { + Elem(k, v) => (*f)(k, v), + Edge(e) => intrusive_iter_mut_impl(e, f), + } + } + } + + intrusive_iter_mut_impl(&mut self.root, &mut f); + } + /// Gets an owning iterator over the entries of the map. #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn into_iter(self) -> MoveEntries { @@ -1158,6 +1202,25 @@ impl BTreeMap { } } + /// An intrusive version of `.into_iter()`. The closure will be called once + /// with every key/value pair in the tree. + /// + /// This is faster than calling `.into_iter()`, but is far less composable. + #[inline] + #[experimental = "relies on unboxed closures"] + pub fn intrusive_into_iter(self, mut f: F) { + fn intrusive_into_iter_impl(node: Node, f: &mut F) { + for ti in node.into_iter() { + match ti { + Elem(k, v) => (*f)(k, v), + Edge(e) => intrusive_into_iter_impl(e, f), + } + } + } + + intrusive_into_iter_impl(self.root, &mut f); + } + /// Gets an iterator over the keys of the map. /// /// # Examples @@ -1580,4 +1643,34 @@ mod bench { pub fn iter_100000(b: &mut Bencher) { bench_iter(b, 100000); } + + fn bench_intrusive_iter(b: &mut Bencher, size: uint) { + let mut map = BTreeMap::::new(); + let mut rng = weak_rng(); + + for _ in range(0, size) { + map.insert(rng.gen(), rng.gen()); + } + + b.iter(|| { + map.intrusive_iter(|&mut: k, v| { + black_box(k); black_box(v); + }); + }); + } + + #[bench] + pub fn intrusive_iter_20(b: &mut Bencher) { + bench_intrusive_iter(b, 20); + } + + #[bench] + pub fn intrusive_iter_1000(b: &mut Bencher) { + bench_intrusive_iter(b, 1000); + } + + #[bench] + pub fn intrusive_iter_100000(b: &mut Bencher) { + bench_intrusive_iter(b, 100000); + } } diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index ae23f38c92913..28c87388d53c1 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -1334,10 +1334,14 @@ struct ElemsAndEdges(Elems, Edges); impl, Edges: DoubleEndedIterator> TraversalImpl for ElemsAndEdges { + #[inline] fn next_kv(&mut self) -> Option<(K, V)> { self.0.next() } + #[inline] fn next_kv_back(&mut self) -> Option<(K, V)> { self.0.next_back() } + #[inline] fn next_edge(&mut self) -> Option { self.1.next() } + #[inline] fn next_edge_back(&mut self) -> Option { self.1.next_back() } } @@ -1354,6 +1358,7 @@ struct MoveTraversalImpl { } impl TraversalImpl> for MoveTraversalImpl { + #[inline] fn next_kv(&mut self) -> Option<(K, V)> { match (self.keys.next(), self.vals.next()) { (Some(k), Some(v)) => Some((k, v)), @@ -1361,6 +1366,7 @@ impl TraversalImpl> for MoveTraversalImpl { } } + #[inline] fn next_kv_back(&mut self) -> Option<(K, V)> { match (self.keys.next_back(), self.vals.next_back()) { (Some(k), Some(v)) => Some((k, v)), @@ -1368,12 +1374,14 @@ impl TraversalImpl> for MoveTraversalImpl { } } + #[inline] fn next_edge(&mut self) -> Option> { // Necessary for correctness, but in a private module debug_assert!(!self.is_leaf); self.edges.next() } + #[inline] fn next_edge_back(&mut self) -> Option> { // Necessary for correctness, but in a private module debug_assert!(!self.is_leaf); @@ -1427,6 +1435,7 @@ pub type MoveTraversal = AbsTraversal>; impl> Iterator> for AbsTraversal { + #[inline] fn next(&mut self) -> Option> { let head_is_edge = self.head_is_edge; self.head_is_edge = !head_is_edge; @@ -1442,6 +1451,7 @@ impl> impl> DoubleEndedIterator> for AbsTraversal { + #[inline] fn next_back(&mut self) -> Option> { let tail_is_edge = self.tail_is_edge; self.tail_is_edge = !tail_is_edge; diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 039bbcd2b7020..274fa13d07449 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -24,7 +24,7 @@ #![allow(unknown_features)] #![feature(macro_rules, default_type_params, phase, globs)] #![feature(unsafe_destructor, import_shadowing, slicing_syntax)] -#![feature(tuple_indexing, unboxed_closures)] +#![feature(unboxed_closures)] #![no_std] #[phase(plugin, link)] extern crate core;