28
28
#[ cfg( feature = "std" ) ]
29
29
extern crate std;
30
30
31
+ #[ cfg( feature = "rand" ) ]
32
+ extern crate rand;
33
+
31
34
use core:: convert:: TryInto ;
32
35
use core:: default:: Default ;
33
36
#[ cfg( feature = "std" ) ]
@@ -46,6 +49,14 @@ pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
46
49
#[ cfg( feature = "std" ) ]
47
50
pub type FxHashSet < V > = HashSet < V , BuildHasherDefault < FxHasher > > ;
48
51
52
+ /// Type alias for a hashmap using the `fx` hash algorithm with [`FxRandomState`].
53
+ #[ cfg( feature = "rand" ) ]
54
+ pub type FxHashMapRnd < K , V > = HashMap < K , V , FxRandomState > ;
55
+
56
+ /// Type alias for a hashmap using the `fx` hash algorithm with [`FxRandomState`].
57
+ #[ cfg( feature = "rand" ) ]
58
+ pub type FxHashSetRnd < V > = HashSet < V , FxRandomState > ;
59
+
49
60
/// A speedy hash algorithm for use within rustc. The hashmap in liballoc
50
61
/// by default uses SipHash which isn't quite as speedy as we want. In the
51
62
/// compiler we're not really worried about DOS attempts, so we use a fast
@@ -61,6 +72,16 @@ pub struct FxHasher {
61
72
hash : usize ,
62
73
}
63
74
75
+ /// `FxRandomState` is an alternative state for `HashMap` types.
76
+ ///
77
+ /// A particular instance `FxRandomState` will create the same instances of
78
+ /// [`Hasher`], but the hashers created by two different `FxRandomState`
79
+ /// instances are unlikely to produce the same result for the same values.
80
+ #[ cfg( feature = "rand" ) ]
81
+ pub struct FxRandomState {
82
+ seed : usize ,
83
+ }
84
+
64
85
#[ cfg( target_pointer_width = "32" ) ]
65
86
const K : usize = 0x9e3779b9 ;
66
87
#[ cfg( target_pointer_width = "64" ) ]
@@ -153,3 +174,38 @@ impl Hasher for FxHasher {
153
174
self . hash as u64
154
175
}
155
176
}
177
+
178
+ #[ cfg( feature = "rand" ) ]
179
+ impl FxRandomState {
180
+ // Constructs a new `FxRandomState` that is initialized with random seed.
181
+ pub fn new ( ) -> FxRandomState {
182
+ use rand:: Rng ;
183
+ use std:: { cell:: Cell , thread_local} ;
184
+
185
+ // This mirrors what `std::collections::hash_map::RandomState` does.
186
+ //
187
+ // Basically
188
+ // 1. Cache result of the rng in a thread local, so repeatedly
189
+ // creating maps is cheaper
190
+ // 2. Change the cached result on every creation, so maps created
191
+ // on the same thread don't have the same iteration order
192
+ thread_local ! ( static SEED : Cell <usize > = {
193
+ Cell :: new( rand:: thread_rng( ) . gen ( ) )
194
+ } ) ;
195
+
196
+ SEED . with ( |seed| {
197
+ let s = seed. get ( ) ;
198
+ seed. set ( s. wrapping_add ( 1 ) ) ;
199
+ FxRandomState { seed : s }
200
+ } )
201
+ }
202
+ }
203
+
204
+ #[ cfg( feature = "rand" ) ]
205
+ impl core:: hash:: BuildHasher for FxRandomState {
206
+ type Hasher = FxHasher ;
207
+
208
+ fn build_hasher ( & self ) -> Self :: Hasher {
209
+ FxHasher { hash : self . seed }
210
+ }
211
+ }
0 commit comments