@@ -17,10 +17,10 @@ use clone::Clone;
17
17
use cmp;
18
18
use hash:: { Hash , Hasher } ;
19
19
use iter:: { Iterator , IteratorExt , count} ;
20
- use marker:: { Copy , Sized } ;
20
+ use marker:: { Copy , Sized , PhantomData , PhantomFn } ;
21
21
use mem:: { self , min_align_of, size_of} ;
22
22
use num:: { Int , UnsignedInt } ;
23
- use ops:: { Deref , DerefMut , Drop } ;
23
+ use ops:: Drop ;
24
24
use option:: Option :: { self , Some , None } ;
25
25
use ptr:: { self , Unique , PtrExt } ;
26
26
use result:: Result :: { self , Ok , Err } ;
@@ -77,20 +77,17 @@ struct RawBucket<K, V> {
77
77
kval : * mut ( K , V ) ,
78
78
}
79
79
80
- impl < K , V > Copy for RawBucket < K , V > { }
81
-
82
- #[ derive( Clone ) ]
83
- pub struct TableRef < M > ( pub M ) ;
84
-
85
- impl < M : Copy > Copy for TableRef < M > { }
86
-
87
80
pub struct Bucket < K , V , M , S = ( ) > {
88
81
raw : RawBucket < K , V > ,
89
82
idx : usize ,
90
83
capacity : usize ,
91
- table : TableRef < M > ,
84
+ table : M ,
85
+ marker : PhantomData < S > ,
86
+
92
87
}
93
88
89
+ impl < K , V > Copy for RawBucket < K , V > { }
90
+
94
91
impl < K , V , M : Copy , S > Copy for Bucket < K , V , M , S > where M : Borrow < RawTable < K , V > > { }
95
92
96
93
mod bucket {
@@ -151,20 +148,6 @@ fn can_alias_safehash_as_option() {
151
148
assert_eq ! ( size_of:: <SafeHash >( ) , size_of:: <Option <SafeHash >>( ) )
152
149
}
153
150
154
- impl < K , V , M > Deref for TableRef < M > where M : Borrow < RawTable < K , V > > {
155
- type Target = RawTable < K , V > ;
156
-
157
- fn deref ( & self ) -> & RawTable < K , V > {
158
- self . 0 . borrow ( )
159
- }
160
- }
161
-
162
- impl < K , V , M > DerefMut for TableRef < M > where M : Borrow < RawTable < K , V > > {
163
- fn deref_mut ( & mut self ) -> & mut RawTable < K , V > {
164
- self . 0 . borrow_mut ( )
165
- }
166
- }
167
-
168
151
impl < K , V > RawBucket < K , V > {
169
152
unsafe fn offset ( self , count : isize ) -> RawBucket < K , V > {
170
153
RawBucket {
@@ -180,19 +163,21 @@ impl<K, V, M, S> Borrow<RawTable<K, V>> for Bucket<K, V, M, S>
180
163
where M : Borrow < RawTable < K , V > >
181
164
{
182
165
fn borrow ( & self ) -> & RawTable < K , V > {
183
- self . table . 0 . borrow ( )
166
+ self . table . borrow ( ) . borrow ( )
184
167
}
185
168
}
186
169
187
170
impl < K , V , M , S > BorrowMut < RawTable < K , V > > for Bucket < K , V , M , S >
188
- where M : Borrow < RawTable < K , V > >
171
+ where M : BorrowMut < RawTable < K , V > >
189
172
{
190
173
fn borrow_mut ( & mut self ) -> & mut RawTable < K , V > {
191
- self . table . 0 . borrow_mut ( )
174
+ self . table . borrow_mut ( ) . borrow_mut ( )
192
175
}
193
176
}
194
177
195
- pub trait Put { }
178
+ /// `Put` is implemented for types which that provide access to a table and cannot be invalidated
179
+ /// by filling a bucket. A similar implementation for `Take` is possible.
180
+ pub trait Put : PhantomFn < Self > { }
196
181
impl < K , V > Put for RawTable < K , V > { }
197
182
impl < ' t , K , V > Put for & ' t mut RawTable < K , V > { }
198
183
impl < K , V , M : Put > Put for Bucket < K , V , M > { }
@@ -202,11 +187,11 @@ impl<K, V, M: Put> Put for FullBucket<K, V, M> {}
202
187
impl < K , V , M , S > Bucket < K , V , M , S > {
203
188
/// Borrow a reference to the table.
204
189
pub fn table ( & self ) -> & M {
205
- & self . table . 0
190
+ & self . table
206
191
}
207
192
/// Move out the reference to the table.
208
193
pub fn into_table ( self ) -> M {
209
- self . table . 0
194
+ self . table
210
195
}
211
196
/// Get the raw index.
212
197
pub fn index ( & self ) -> usize {
@@ -232,14 +217,14 @@ impl<K, V, M> Bucket<K, V, M> where M: Borrow<RawTable<K, V>> {
232
217
pub fn at_index ( table : M , ib_index : uint )
233
218
-> Result < Bucket < K , V , M > , Bucket < K , V , M , bucket:: TableIsEmpty > >
234
219
{
235
- let table = TableRef ( table) ;
236
- let capacity = table. capacity ( ) ;
220
+ let capacity = table. borrow ( ) . capacity ( ) ;
237
221
let idx = ib_index & ( capacity - 1 ) ;
238
222
let bucket: Bucket < K , V , M > = Bucket {
239
- raw : unsafe { table. first_bucket_raw ( ) . offset ( idx as isize ) } ,
223
+ raw : unsafe { table. borrow ( ) . first_bucket_raw ( ) . offset ( idx as isize ) } ,
240
224
idx : idx,
241
225
capacity : capacity,
242
226
table : table,
227
+ marker : PhantomData ,
243
228
} ;
244
229
if capacity == 0 {
245
230
Err ( bucket. unsafe_cast ( ) )
@@ -254,7 +239,7 @@ impl<K, V, M> Bucket<K, V, M> where M: Borrow<RawTable<K, V>> {
254
239
255
240
/// Narrows down the range of iteration, which must be a power of 2.
256
241
pub fn iter_to ( mut self , limit : usize ) -> Bucket < K , V , M > {
257
- assert ! ( limit <= self . table. capacity( ) ) ;
242
+ assert ! ( limit <= self . table. borrow ( ) . capacity( ) ) ;
258
243
assert ! ( limit. is_power_of_two( ) ) ;
259
244
self . capacity = limit;
260
245
self
@@ -295,6 +280,7 @@ impl<K, V, M, S> Bucket<K, V, M, S> where M: Borrow<RawTable<K, V>> {
295
280
idx : self . idx ,
296
281
capacity : self . capacity ,
297
282
table : self . table ,
283
+ marker : PhantomData ,
298
284
}
299
285
}
300
286
@@ -315,18 +301,20 @@ impl<K, V, M, S> Bucket<K, V, M, S> where M: Borrow<RawTable<K, V>> {
315
301
raw : self . raw ,
316
302
idx : self . idx ,
317
303
capacity : self . capacity ,
318
- table : TableRef ( self ) ,
304
+ table : self ,
305
+ marker : PhantomData ,
319
306
}
320
307
}
321
308
}
322
309
323
310
impl < K , V , M > EmptyBucket < K , V , M > where M : Borrow < RawTable < K , V > > {
324
311
pub fn gap_peek ( self ) -> Option < GapThenFull < K , V , M > > {
325
312
let gap = Bucket {
326
- table : TableRef ( ( ) ) ,
313
+ table : ( ) ,
327
314
idx : self . idx ,
328
315
capacity : self . capacity ,
329
316
raw : self . raw ,
317
+ marker : PhantomData ,
330
318
} ;
331
319
332
320
match self . into_next ( ) . peek ( ) {
@@ -341,7 +329,7 @@ impl<K, V, M> EmptyBucket<K, V, M> where M: Borrow<RawTable<K, V>> {
341
329
}
342
330
}
343
331
344
- impl < K , V , M > EmptyBucket < K , V , M > where M : Borrow < RawTable < K , V > > , M : Put {
332
+ impl < K , V , M > EmptyBucket < K , V , M > where M : BorrowMut < RawTable < K , V > > , M : Put {
345
333
/// Puts given key and value pair, along with the key's hash,
346
334
/// into this bucket in the hashtable. Note how `self` is 'moved' into
347
335
/// this function, because this slot will no longer be empty when
@@ -356,7 +344,7 @@ impl<K, V, M> EmptyBucket<K, V, M> where M: Borrow<RawTable<K, V>>, M: Put {
356
344
ptr:: write ( self . raw . kval , ( key, value) ) ;
357
345
}
358
346
359
- self . table . size += 1 ;
347
+ self . table . borrow_mut ( ) . size += 1 ;
360
348
361
349
self . unsafe_cast ( )
362
350
}
@@ -413,7 +401,7 @@ impl<'t, K, V, M: 't> FullBucket<K, V, M> where M: BorrowMut<RawTable<K, V>> {
413
401
/// This works similarly to `put`, building an `EmptyBucket` out of the
414
402
/// taken bucket.
415
403
pub fn take ( mut self ) -> ( EmptyBucket < K , V , M > , K , V ) {
416
- self . table . size -= 1 ;
404
+ self . table . borrow_mut ( ) . size -= 1 ;
417
405
418
406
unsafe {
419
407
* self . raw . hash = None ;
@@ -497,46 +485,47 @@ impl<K, V> RawTable<K, V> {
497
485
}
498
486
} else {
499
487
RawBucket {
500
- hash : self . middle . ptr as * mut Option < SafeHash > ,
501
- kval : self . middle . ptr . offset ( -( self . capacity as isize ) ) ,
488
+ hash : self . as_mut_ptr ( ) as * mut Option < SafeHash > ,
489
+ kval : self . as_mut_ptr ( ) . offset ( -( self . capacity as isize ) ) ,
502
490
}
503
491
}
504
492
}
505
493
494
+ /// Grows a non-empty table in-place.
506
495
pub fn grow_inplace ( & mut self , capacity : uint ) -> bool {
507
496
assert ! ( capacity. is_power_of_two( ) ) ;
508
497
assert ! ( capacity >= self . capacity) ;
509
498
510
- if self . middle . ptr . is_null ( ) {
499
+ if self . capacity == 0 {
511
500
return false ;
512
501
}
513
502
514
503
let new_size = checked_size_generic :: < K , V > ( capacity) ;
515
504
516
505
unsafe {
517
- let ptr = self . middle . ptr . offset ( -( self . capacity as isize ) ) as * mut u8 ;
506
+ let ptr = self . as_mut_ptr ( ) . offset ( -( self . capacity as isize ) ) as * mut u8 ;
518
507
let is_inplace = reallocate_inplace ( ptr,
519
508
size_generic :: < K , V > ( self . capacity ) ,
520
509
new_size,
521
510
align :: < K , V > ( ) ) >= new_size;
522
511
523
512
if is_inplace {
524
513
let cap_diff = ( capacity - self . capacity ) as isize ;
525
- let hashes = self . middle . ptr . offset ( cap_diff) as * mut Option < SafeHash > ;
514
+ let hashes = self . as_mut_ptr ( ) . offset ( cap_diff) as * mut Option < SafeHash > ;
526
515
// Copy the array of hashes. Maybe it's already in cache.
527
516
if size_of :: < ( K , V ) > ( ) >= size_of :: < Option < SafeHash > > ( ) {
528
517
// The regions of memory occupied by old and new hash arrays are disjoint.
529
518
// before: [KVKVKVKV|h h h h ]
530
519
// after: [KVKVKVKV|KVKVKVKV|h h h h h h h h ]
531
- ptr:: copy_nonoverlapping ( hashes, self . middle . ptr as * const _ , self . capacity ) ;
520
+ ptr:: copy_nonoverlapping ( hashes, self . as_mut_ptr ( ) as * const _ , self . capacity ) ;
532
521
} else {
533
522
// before: [KVKVKVKV|h h |h h ]
534
523
// after: [KVKVKVKV|KVKVKVKV|h h h h h h h h ]
535
- ptr:: copy ( hashes, self . middle . ptr as * const _ , self . capacity ) ;
524
+ ptr:: copy ( hashes, self . as_mut_ptr ( ) as * const _ , self . capacity ) ;
536
525
}
537
- zero_memory ( hashes. offset ( self . capacity as int ) , capacity - self . capacity ) ;
526
+ ptr :: write_bytes ( hashes. offset ( self . capacity as int ) , 0 , capacity - self . capacity ) ;
538
527
539
- self . middle = Unique :: new ( self . middle . ptr . offset ( cap_diff) ) ;
528
+ self . middle = Unique :: new ( self . as_mut_ptr ( ) . offset ( cap_diff) ) ;
540
529
self . capacity = capacity;
541
530
}
542
531
@@ -554,6 +543,11 @@ impl<K, V> RawTable<K, V> {
554
543
pub fn size ( & self ) -> usize {
555
544
self . size
556
545
}
546
+
547
+ /// Pointer to one-past-the-last key-value pair.
548
+ pub fn as_mut_ptr ( & self ) -> * mut ( K , V ) {
549
+ unsafe { self . middle . get ( ) as * const _ as * mut _ }
550
+ }
557
551
}
558
552
559
553
/// Rounds up to a multiple of a power of two. Returns the closest multiple
@@ -598,7 +592,7 @@ fn align<K, V>() -> usize {
598
592
}
599
593
600
594
/// A newtyped RawBucket. Not copyable.
601
- pub struct RawFullBucket < K , V , M > ( RawBucket < K , V > ) ;
595
+ pub struct RawFullBucket < K , V , M > ( RawBucket < K , V > , PhantomData < M > ) ;
602
596
603
597
impl < ' t , K , V , M : ' t > RawFullBucket < K , V , M > where M : Borrow < RawTable < K , V > > {
604
598
pub fn into_refs ( self ) -> ( & ' t K , & ' t V ) {
@@ -617,7 +611,7 @@ impl<'t, K, V, M: 't> RawFullBucket<K, V, M> where M: BorrowMut<RawTable<K, V>>
617
611
pub struct RawFullBuckets < K , V , M > {
618
612
raw : RawBucket < K , V > ,
619
613
hashes_end : * mut Option < SafeHash > ,
620
- table : TableRef < M > ,
614
+ table : M ,
621
615
}
622
616
623
617
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
@@ -641,7 +635,7 @@ impl<K, V, M> Iterator for RawFullBuckets<K, V, M> {
641
635
// it with the pointer to the next one.
642
636
let prev = ptr:: replace ( & mut self . raw , self . raw . offset ( 1 ) ) ;
643
637
if * prev. hash != None {
644
- return Some ( RawFullBucket ( prev) ) ;
638
+ return Some ( RawFullBucket ( prev, PhantomData ) ) ;
645
639
}
646
640
}
647
641
}
@@ -666,12 +660,13 @@ impl<K, V> Drop for RawTable<K, V> {
666
660
}
667
661
}
668
662
669
- let ptr = self . middle . ptr . offset ( -( self . capacity as isize ) ) as * mut u8 ;
663
+ let ptr = self . as_mut_ptr ( ) . offset ( -( self . capacity as isize ) ) as * mut u8 ;
670
664
deallocate ( ptr, size_generic :: < K , V > ( self . capacity ) , align :: < K , V > ( ) ) ;
671
665
}
672
666
}
673
667
}
674
668
669
+ /// A partial table provides safe and cheap draining and incremental construction.
675
670
pub struct PartialRawTable < K , V > {
676
671
table : RawTable < K , V > ,
677
672
front : RawBucket < K , V > ,
@@ -681,6 +676,7 @@ pub struct PartialRawTable<K, V> {
681
676
}
682
677
683
678
impl < K , V > PartialRawTable < K , V > {
679
+ /// Turn a table into a partial table. All buckets are already initialized.
684
680
pub fn new ( table : RawTable < K , V > ) -> PartialRawTable < K , V > {
685
681
unsafe {
686
682
PartialRawTable {
@@ -693,6 +689,7 @@ impl<K, V> PartialRawTable<K, V> {
693
689
}
694
690
}
695
691
692
+ /// Initialize a bucket. Has no effect if there are no uninitialized buckets at the back.
696
693
pub fn push_back ( & mut self , bucket : Option < ( SafeHash , K , V ) > ) {
697
694
unsafe {
698
695
if self . back_num != 0 {
@@ -709,6 +706,7 @@ impl<K, V> PartialRawTable<K, V> {
709
706
}
710
707
}
711
708
709
+ /// Takes out an initialized bucket. Returns None if all buckets are uninitialized.
712
710
pub fn take_front ( & mut self ) -> Option < ( SafeHash , K , V ) > {
713
711
unsafe {
714
712
while self . front . hash != self . back . hash {
@@ -725,10 +723,11 @@ impl<K, V> PartialRawTable<K, V> {
725
723
None
726
724
}
727
725
726
+ /// Unwrap the table by zeroing uninitialized ranges.
728
727
pub fn unwrap ( self ) -> RawTable < K , V > {
729
728
unsafe {
730
- ptr:: write_bytes ( self . table . first_bucket_raw ( ) . hash , self . front_num ) ;
731
- ptr:: write_bytes ( self . back . hash , self . back_num ) ;
729
+ ptr:: write_bytes ( self . table . first_bucket_raw ( ) . hash , 0 , self . front_num ) ;
730
+ ptr:: write_bytes ( self . back . hash , 0 , self . back_num ) ;
732
731
let table = ptr:: read ( & self . table ) ;
733
732
mem:: forget ( self ) ;
734
733
table
@@ -740,6 +739,7 @@ impl<K, V> PartialRawTable<K, V> {
740
739
}
741
740
}
742
741
742
+ /// Drops all initialized buckets in the partial table.
743
743
#[ unsafe_destructor]
744
744
impl < K , V > Drop for PartialRawTable < K , V > {
745
745
fn drop ( & mut self ) {
0 commit comments