@@ -22,9 +22,9 @@ use mem::{self, min_align_of, size_of};
22
22
use num:: { Int , UnsignedInt } ;
23
23
use ops:: { Deref , DerefMut , Drop } ;
24
24
use option:: Option :: { self , Some , None } ;
25
- use ptr:: { self , Unique , PtrExt , copy_nonoverlapping_memory, zero_memory} ;
25
+ use ptr:: { self , Unique , PtrExt , copy_memory , copy_nonoverlapping_memory, zero_memory} ;
26
26
use result:: Result :: { self , Ok , Err } ;
27
- use rt:: heap:: { allocate, deallocate} ;
27
+ use rt:: heap:: { allocate, deallocate, reallocate_inplace } ;
28
28
use collections:: hash_state:: HashState ;
29
29
use core:: nonzero:: NonZero ;
30
30
@@ -277,6 +277,14 @@ impl<K, V, M> Bucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
277
277
Bucket :: at_index ( table, 0 ) . map ( |b| b. into_iter ( ) ) . unwrap_or_else ( |b| b. into_iter ( ) )
278
278
}
279
279
280
+ /// Narrows down the range of iteration, which must be a power of 2.
281
+ pub fn iter_to ( mut self , limit : usize ) -> Bucket < K , V , M > {
282
+ assert ! ( limit <= self . 0 . table. capacity( ) ) ;
283
+ assert ! ( limit. is_power_of_two( ) ) ;
284
+ self . 0 . capacity = limit;
285
+ self
286
+ }
287
+
280
288
/// Reads a bucket at a given index, returning an enum indicating whether
281
289
/// it's initialized or not. You need to match on this enum to get
282
290
/// the appropriate types to call most of the other functions in
@@ -521,6 +529,47 @@ impl<K, V> RawTable<K, V> {
521
529
}
522
530
}
523
531
532
+ pub fn grow_inplace ( & mut self , capacity : uint ) -> bool {
533
+ assert ! ( capacity. is_power_of_two( ) ) ;
534
+ assert ! ( capacity >= self . capacity) ;
535
+
536
+ if self . middle . ptr . is_null ( ) {
537
+ return false ;
538
+ }
539
+
540
+ let new_size = checked_size_generic :: < K , V > ( capacity) ;
541
+
542
+ unsafe {
543
+ let ptr = self . middle . ptr . offset ( -( self . capacity as isize ) ) as * mut u8 ;
544
+ let is_inplace = reallocate_inplace ( ptr,
545
+ size_generic :: < K , V > ( self . capacity ) ,
546
+ new_size,
547
+ align :: < K , V > ( ) ) >= new_size;
548
+
549
+ if is_inplace {
550
+ let cap_diff = ( capacity - self . capacity ) as isize ;
551
+ let hashes = self . middle . ptr . offset ( cap_diff) as * mut Option < SafeHash > ;
552
+ // Copy the array of hashes. Maybe it's already in cache.
553
+ if size_of :: < ( K , V ) > ( ) >= size_of :: < Option < SafeHash > > ( ) {
554
+ // The regions of memory occupied by old and new hash arrays are disjoint.
555
+ // before: [KVKVKVKV|h h h h ]
556
+ // after: [KVKVKVKV|KVKVKVKV|h h h h h h h h ]
557
+ copy_nonoverlapping_memory ( hashes, self . middle . ptr as * const _ , self . capacity ) ;
558
+ } else {
559
+ // before: [KVKVKVKV|h h |h h ]
560
+ // after: [KVKVKVKV|KVKVKVKV|h h h h h h h h ]
561
+ copy_memory ( hashes, self . middle . ptr as * const _ , self . capacity ) ;
562
+ }
563
+ zero_memory ( hashes. offset ( self . capacity as int ) , capacity - self . capacity ) ;
564
+
565
+ self . middle = Unique ( self . middle . ptr . offset ( cap_diff) ) ;
566
+ self . capacity = capacity;
567
+ }
568
+
569
+ return is_inplace;
570
+ }
571
+ }
572
+
524
573
/// The hashtable's capacity, similar to a vector's.
525
574
pub fn capacity ( & self ) -> usize {
526
575
self . capacity
0 commit comments