@@ -22,9 +22,9 @@ use mem::{self, min_align_of, size_of};
2222use num:: { Int , UnsignedInt } ;
2323use ops:: { Deref , DerefMut , Drop } ;
2424use 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} ;
2626use result:: Result :: { self , Ok , Err } ;
27- use rt:: heap:: { allocate, deallocate} ;
27+ use rt:: heap:: { allocate, deallocate, reallocate_inplace } ;
2828use collections:: hash_state:: HashState ;
2929use core:: nonzero:: NonZero ;
3030
@@ -277,6 +277,14 @@ impl<K, V, M> Bucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
277277 Bucket :: at_index ( table, 0 ) . map ( |b| b. into_iter ( ) ) . unwrap_or_else ( |b| b. into_iter ( ) )
278278 }
279279
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+
280288 /// Reads a bucket at a given index, returning an enum indicating whether
281289 /// it's initialized or not. You need to match on this enum to get
282290 /// the appropriate types to call most of the other functions in
@@ -521,6 +529,47 @@ impl<K, V> RawTable<K, V> {
521529 }
522530 }
523531
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+
524573 /// The hashtable's capacity, similar to a vector's.
525574 pub fn capacity ( & self ) -> usize {
526575 self . capacity
0 commit comments