11
11
//! Ordered containers with integer keys, implemented as radix tries (`TrieSet` and `TrieMap` types)
12
12
13
13
use prelude:: * ;
14
+ use mem;
14
15
use uint;
15
16
use util:: replace;
17
+ use unstable:: intrinsics:: init;
16
18
use vec;
17
19
18
20
// FIXME: #5244: need to manually update the TrieNode constructor
19
21
static SHIFT : uint = 4 ;
20
22
static SIZE : uint = 1 << SHIFT ;
21
23
static MASK : uint = SIZE - 1 ;
24
+ static NUM_CHUNKS : uint = uint:: bits / SHIFT ;
22
25
23
26
enum Child < T > {
24
27
Internal ( ~TrieNode < T > ) ,
@@ -111,35 +114,27 @@ impl<T> TrieMap<T> {
111
114
self . root . each_reverse ( f)
112
115
}
113
116
114
- /// Visit all keys in reverse order
115
- #[ inline]
116
- pub fn each_key_reverse ( & self , f: |& uint| -> bool) -> bool {
117
- self . each_reverse ( |k, _| f ( k) )
118
- }
119
-
120
- /// Visit all values in reverse order
121
- #[ inline]
122
- pub fn each_value_reverse ( & self , f: |& T | -> bool) -> bool {
123
- self . each_reverse ( |_, v| f ( v) )
124
- }
125
-
126
117
/// Get an iterator over the key-value pairs in the map
127
118
pub fn iter < ' a > ( & ' a self ) -> TrieMapIterator < ' a , T > {
128
- TrieMapIterator {
129
- stack : ~[ self . root . children . iter ( ) ] ,
130
- remaining_min : self . length ,
131
- remaining_max : self . length
132
- }
119
+ let mut iter = unsafe { TrieMapIterator :: new ( ) } ;
120
+ iter. stack [ 0 ] = self . root . children . iter ( ) ;
121
+ iter. length = 1 ;
122
+ iter. remaining_min = self . length ;
123
+ iter. remaining_max = self . length ;
124
+
125
+ iter
133
126
}
134
127
135
128
/// Get an iterator over the key-value pairs in the map, with the
136
129
/// ability to mutate the values.
137
130
pub fn mut_iter < ' a > ( & ' a mut self ) -> TrieMapMutIterator < ' a , T > {
138
- TrieMapMutIterator {
139
- stack : ~[ self . root . children . mut_iter ( ) ] ,
140
- remaining_min : self . length ,
141
- remaining_max : self . length
142
- }
131
+ let mut iter = unsafe { TrieMapMutIterator :: new ( ) } ;
132
+ iter. stack [ 0 ] = self . root . children . mut_iter ( ) ;
133
+ iter. length = 1 ;
134
+ iter. remaining_min = self . length ;
135
+ iter. remaining_max = self . length ;
136
+
137
+ iter
143
138
}
144
139
}
145
140
@@ -188,16 +183,16 @@ macro_rules! bound {
188
183
189
184
let key = $key;
190
185
191
- let mut idx = 0 ;
192
- let mut it = $iterator_name {
193
- stack: ~[ ] ,
194
- remaining_min: 0 ,
195
- remaining_max: this. length
196
- } ;
186
+ let mut it = unsafe { $iterator_name:: new( ) } ;
187
+ // everything else is zero'd, as we want.
188
+ it. remaining_max = this. length;
189
+
197
190
// this addr is necessary for the `Internal` pattern.
198
191
addr!( loop {
199
192
let children = unsafe { addr!( & $( $mut_) * ( * node) . children) } ;
200
- let child_id = chunk( key, idx) ;
193
+ // it.length is the current depth in the iterator and the
194
+ // current depth through the `uint` key we've traversed.
195
+ let child_id = chunk( key, it. length) ;
201
196
let ( slice_idx, ret) = match children[ child_id] {
202
197
Internal ( ref $( $mut_) * n) => {
203
198
node = addr!( & $( $mut_) * * * n as * $( $mut_) * TrieNode <T >) ;
@@ -214,9 +209,10 @@ macro_rules! bound {
214
209
( child_id + 1 , true )
215
210
}
216
211
} ;
217
- it. stack. push( children. $slice_from( slice_idx) . $iter( ) ) ;
212
+ // push to the stack.
213
+ it. stack[ it. length] = children. $slice_from( slice_idx) . $iter( ) ;
214
+ it. length += 1 ;
218
215
if ret { return it }
219
- idx += 1 ;
220
216
} )
221
217
}
222
218
}
@@ -328,7 +324,7 @@ impl TrieSet {
328
324
/// Visit all values in reverse order
329
325
#[ inline]
330
326
pub fn each_reverse ( & self , f: |& uint| -> bool) -> bool {
331
- self . map . each_key_reverse ( f )
327
+ self . map . each_reverse ( |k , _| f ( k ) )
332
328
}
333
329
334
330
/// Get an iterator over the values in the set
@@ -479,15 +475,17 @@ fn remove<T>(count: &mut uint, child: &mut Child<T>, key: uint,
479
475
480
476
/// Forward iterator over a map
481
477
pub struct TrieMapIterator < ' a , T > {
482
- priv stack : ~[ vec:: VecIterator < ' a , Child < T > > ] ,
478
+ priv stack : [ vec:: VecIterator < ' a , Child < T > > , .. NUM_CHUNKS ] ,
479
+ priv length : uint ,
483
480
priv remaining_min : uint ,
484
481
priv remaining_max : uint
485
482
}
486
483
487
484
/// Forward iterator over the key-value pairs of a map, with the
488
485
/// values being mutable.
489
486
pub struct TrieMapMutIterator < ' a , T > {
490
- priv stack : ~[ vec:: VecMutIterator < ' a , Child < T > > ] ,
487
+ priv stack : [ vec:: VecMutIterator < ' a , Child < T > > , .. NUM_CHUNKS ] ,
488
+ priv length : uint ,
491
489
priv remaining_min : uint ,
492
490
priv remaining_max : uint
493
491
}
@@ -499,27 +497,96 @@ macro_rules! iterator_impl {
499
497
( $name: ident,
500
498
iter = $iter: ident,
501
499
mutability = $( $mut_: tt) * ) => {
500
+ impl <' a, T > $name<' a, T > {
501
+ // Create new zero'd iterator. We have a thin gilding of safety by
502
+ // using init rather than uninit, so that the worst that can happen
503
+ // from failing to initialise correctly after calling these is a
504
+ // segfault.
505
+ #[ cfg( target_word_size="32" ) ]
506
+ unsafe fn new( ) -> $name<' a, T > {
507
+ $name {
508
+ remaining_min: 0 ,
509
+ remaining_max: 0 ,
510
+ length: 0 ,
511
+ // ick :( ... at least the compiler will tell us if we screwed up.
512
+ stack: [ init( ) , init( ) , init( ) , init( ) , init( ) , init( ) , init( ) , init( ) ]
513
+ }
514
+ }
515
+
516
+ #[ cfg( target_word_size="64" ) ]
517
+ unsafe fn new( ) -> $name<' a, T > {
518
+ $name {
519
+ remaining_min: 0 ,
520
+ remaining_max: 0 ,
521
+ length: 0 ,
522
+ stack: [ init( ) , init( ) , init( ) , init( ) , init( ) , init( ) , init( ) , init( ) ,
523
+ init( ) , init( ) , init( ) , init( ) , init( ) , init( ) , init( ) , init( ) ]
524
+ }
525
+ }
526
+ }
527
+
502
528
item!( impl <' a, T > Iterator <( uint, & ' a $( $mut_) * T ) > for $name<' a, T > {
529
+ // you might wonder why we're not even trying to act within the
530
+ // rules, and are just manipulating raw pointers like there's no
531
+ // such thing as invalid pointers and memory unsafety. The
532
+ // reason is performance, without doing this we can get the
533
+ // bench_iter_large microbenchmark down to about 30000 ns/iter
534
+ // (using .unsafe_ref to index self.stack directly, 38000
535
+ // ns/iter with [] checked indexing), but this smashes that down
536
+ // to 13500 ns/iter.
537
+ //
538
+ // Fortunately, it's still safe...
539
+ //
540
+ // We have an invariant that every Internal node
541
+ // corresponds to one push to self.stack, and one pop,
542
+ // nested appropriately. self.stack has enough storage
543
+ // to store the maximum depth of Internal nodes in the
544
+ // trie (8 on 32-bit platforms, 16 on 64-bit).
503
545
fn next( & mut self ) -> Option <( uint, & ' a $( $mut_) * T ) > {
504
- while !self . stack. is_empty( ) {
505
- match self . stack[ self . stack. len( ) - 1 ] . next( ) {
506
- None => {
507
- self . stack. pop( ) ;
508
- }
509
- Some ( child) => {
510
- addr!( match * child {
511
- Internal ( ref $( $mut_) * node) => {
512
- self . stack. push( node. children. $iter( ) ) ;
513
- }
514
- External ( key, ref $( $mut_) * value) => {
515
- self . remaining_max -= 1 ;
516
- if self . remaining_min > 0 {
517
- self . remaining_min -= 1 ;
546
+ let start_ptr = self . stack. as_mut_ptr( ) ;
547
+
548
+ unsafe {
549
+ // write_ptr is the next place to write to the stack.
550
+ // invariant: start_ptr <= write_ptr < end of the
551
+ // vector.
552
+ let mut write_ptr = start_ptr. offset( self . length as int) ;
553
+ while write_ptr != start_ptr {
554
+ // indexing back one is safe, since write_ptr >
555
+ // start_ptr now.
556
+ match ( * write_ptr. offset( -1 ) ) . next( ) {
557
+ // exhausted this iterator (i.e. finished this
558
+ // Internal node), so pop from the stack.
559
+ //
560
+ // don't bother clearing the memory, because the
561
+ // next time we use it we'll've written to it
562
+ // first.
563
+ None => write_ptr = write_ptr. offset( -1 ) ,
564
+ Some ( child) => {
565
+ addr!( match * child {
566
+ Internal ( ref $( $mut_) * node) => {
567
+ // going down a level, so push
568
+ // to the stack (this is the
569
+ // write referenced above)
570
+ * write_ptr = node. children. $iter( ) ;
571
+ write_ptr = write_ptr. offset( 1 ) ;
572
+ }
573
+ External ( key, ref $( $mut_) * value) => {
574
+ self . remaining_max -= 1 ;
575
+ if self . remaining_min > 0 {
576
+ self . remaining_min -= 1 ;
577
+ }
578
+ // store the new length of the
579
+ // stack, based on our current
580
+ // position.
581
+ self . length = ( write_ptr as uint
582
+ - start_ptr as uint) /
583
+ mem:: size_of_val( & * write_ptr) ;
584
+
585
+ return Some ( ( key, value) ) ;
518
586
}
519
- return Some ( ( key, value) ) ;
520
- }
521
- Nothing => { }
522
- } )
587
+ Nothing => { }
588
+ } )
589
+ }
523
590
}
524
591
}
525
592
}
0 commit comments