Skip to content

Commit 536cb90

Browse files
committed
Migrate core::send_map to random, keyed hashes w/ hash::Hash trait.
1 parent 3462bb6 commit 536cb90

File tree

6 files changed

+56
-55
lines changed

6 files changed

+56
-55
lines changed

src/libcore/hash.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import io::Writer;
1717
import io::WriterUtil;
1818
import to_bytes::IterBytes;
1919

20-
export Streaming, State;
20+
export Streaming, State, Hash, HashUtil;
2121
export default_state;
2222
export hash_bytes_keyed;
2323
export hash_str_keyed;

src/libcore/send_map.rs

Lines changed: 33 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,11 @@ Sendable hash maps. Very much a work in progress.
44
55
*/
66

7+
import cmp::Eq;
8+
import hash::Hash;
9+
import to_bytes::IterBytes;
710

8-
/**
9-
* A function that returns a hash of a value
10-
*
11-
* The hash should concentrate entropy in the lower bits.
12-
*/
13-
type HashFn<K> = pure fn~(K) -> uint;
14-
type EqFn<K> = pure fn~(K, K) -> bool;
15-
16-
trait SendMap<K, V: copy> {
11+
trait SendMap<K:Eq Hash, V: copy> {
1712
// FIXME(#3148) ^^^^ once find_ref() works, we can drop V:copy
1813

1914
fn insert(&mut self, +k: K, +v: V) -> bool;
@@ -34,14 +29,14 @@ mod linear {
3429
export LinearMap, linear_map, linear_map_with_capacity, public_methods;
3530

3631
const initial_capacity: uint = 32u; // 2^5
37-
struct Bucket<K,V> {
32+
struct Bucket<K:Eq Hash,V> {
3833
hash: uint;
3934
key: K;
4035
value: V;
4136
}
42-
struct LinearMap<K,V> {
43-
hashfn: pure fn~(x: &K) -> uint;
44-
eqfn: pure fn~(x: &K, y: &K) -> bool;
37+
struct LinearMap<K:Eq Hash,V> {
38+
k0: u64;
39+
k1: u64;
4540
resize_at: uint;
4641
size: uint;
4742
buckets: ~[Option<Bucket<K,V>>];
@@ -58,28 +53,29 @@ mod linear {
5853
((capacity as float) * 3. / 4.) as uint
5954
}
6055

61-
fn LinearMap<K,V>(
62-
+hashfn: pure fn~(x: &K) -> uint,
63-
+eqfn: pure fn~(x: &K, y: &K) -> bool) -> LinearMap<K,V> {
64-
65-
linear_map_with_capacity(hashfn, eqfn, 32)
56+
fn LinearMap<K:Eq Hash,V>() -> LinearMap<K,V> {
57+
linear_map_with_capacity(32)
6658
}
6759

68-
fn linear_map_with_capacity<K,V>(
69-
+hashfn: pure fn~(x: &K) -> uint,
70-
+eqfn: pure fn~(x: &K, y: &K) -> bool,
60+
fn linear_map_with_capacity<K:Eq Hash,V>(
7161
initial_capacity: uint) -> LinearMap<K,V> {
62+
let r = rand::Rng();
63+
linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(),
64+
initial_capacity)
65+
}
7266

67+
fn linear_map_with_capacity_and_keys<K:Eq Hash,V> (
68+
k0: u64, k1: u64,
69+
initial_capacity: uint) -> LinearMap<K,V> {
7370
LinearMap {
74-
hashfn: hashfn,
75-
eqfn: eqfn,
71+
k0: k0, k1: k1,
7672
resize_at: resize_at(initial_capacity),
7773
size: 0,
7874
buckets: vec::from_fn(initial_capacity, |_i| None)
7975
}
8076
}
8177

82-
priv impl<K, V> LinearMap<K,V> {
78+
priv impl<K:Hash IterBytes Eq, V> LinearMap<K,V> {
8379
#[inline(always)]
8480
pure fn to_bucket(&const self,
8581
h: uint) -> uint {
@@ -123,7 +119,7 @@ mod linear {
123119
pure fn bucket_for_key(&const self,
124120
buckets: &[Option<Bucket<K,V>>],
125121
k: &K) -> SearchResult {
126-
let hash = self.hashfn(k);
122+
let hash = k.hash_keyed(self.k0, self.k1) as uint;
127123
self.bucket_for_key_with_hash(buckets, hash, k)
128124
}
129125

@@ -134,7 +130,7 @@ mod linear {
134130
k: &K) -> SearchResult {
135131
let _ = for self.bucket_sequence(hash) |i| {
136132
match buckets[i] {
137-
Some(bkt) => if bkt.hash == hash && self.eqfn(k, &bkt.key) {
133+
Some(bkt) => if bkt.hash == hash && *k == bkt.key {
138134
return FoundEntry(i);
139135
},
140136
None => return FoundHole(i)
@@ -204,7 +200,7 @@ mod linear {
204200
}
205201
}
206202

207-
impl<K,V> LinearMap<K,V> {
203+
impl<K:Hash IterBytes Eq,V> LinearMap<K,V> {
208204
fn insert(&mut self, +k: K, +v: V) -> bool {
209205
if self.size >= self.resize_at {
210206
// n.b.: We could also do this after searching, so
@@ -216,7 +212,7 @@ mod linear {
216212
self.expand();
217213
}
218214

219-
let hash = self.hashfn(&k);
215+
let hash = k.hash_keyed(self.k0, self.k1) as uint;
220216
self.insert_internal(hash, k, v)
221217
}
222218

@@ -319,7 +315,7 @@ mod linear {
319315
}
320316
}
321317

322-
impl<K,V: copy> LinearMap<K,V> {
318+
impl<K:Hash IterBytes Eq, V: copy> LinearMap<K,V> {
323319
fn find(&const self, k: &K) -> Option<V> {
324320
match self.bucket_for_key(self.buckets, k) {
325321
FoundEntry(idx) => {
@@ -346,17 +342,17 @@ mod linear {
346342

347343
}
348344

349-
impl<K: copy, V: copy> LinearMap<K,V> {
345+
impl<K: Hash IterBytes Eq copy, V: copy> LinearMap<K,V> {
350346
fn each(&self, blk: fn(+K,+V) -> bool) {
351347
self.each_ref(|k,v| blk(copy *k, copy *v));
352348
}
353349
}
354-
impl<K: copy, V> LinearMap<K,V> {
350+
impl<K: Hash IterBytes Eq copy, V> LinearMap<K,V> {
355351
fn each_key(&self, blk: fn(+K) -> bool) {
356352
self.each_key_ref(|k| blk(copy *k));
357353
}
358354
}
359-
impl<K, V: copy> LinearMap<K,V> {
355+
impl<K: Hash IterBytes Eq, V: copy> LinearMap<K,V> {
360356
fn each_value(&self, blk: fn(+V) -> bool) {
361357
self.each_value_ref(|v| blk(copy *v));
362358
}
@@ -368,11 +364,8 @@ mod test {
368364

369365
import linear::LinearMap;
370366

371-
pure fn uint_hash(x: &uint) -> uint { *x }
372-
pure fn uint_eq(x: &uint, y: &uint) -> bool { *x == *y }
373-
374367
fn int_linear_map<V>() -> LinearMap<uint,V> {
375-
return LinearMap(uint_hash, uint_eq);
368+
return LinearMap();
376369
}
377370

378371
#[test]
@@ -395,7 +388,7 @@ mod test {
395388

396389
#[test]
397390
fn conflicts() {
398-
let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
391+
let mut m = ~linear::linear_map_with_capacity(4);
399392
assert m.insert(1, 2);
400393
assert m.insert(5, 3);
401394
assert m.insert(9, 4);
@@ -406,7 +399,7 @@ mod test {
406399

407400
#[test]
408401
fn conflict_remove() {
409-
let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
402+
let mut m = ~linear::linear_map_with_capacity(4);
410403
assert m.insert(1, 2);
411404
assert m.insert(5, 3);
412405
assert m.insert(9, 4);
@@ -417,7 +410,7 @@ mod test {
417410

418411
#[test]
419412
fn empty() {
420-
let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
413+
let mut m = ~linear::linear_map_with_capacity(4);
421414
assert m.insert(1, 2);
422415
assert !m.is_empty();
423416
assert m.remove(&1);
@@ -426,7 +419,7 @@ mod test {
426419

427420
#[test]
428421
fn iterate() {
429-
let mut m = linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
422+
let mut m = linear::linear_map_with_capacity(4);
430423
for uint::range(0, 32) |i| {
431424
assert (&mut m).insert(i, i*2);
432425
}

src/libcore/task.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -731,17 +731,7 @@ type rust_closure = libc::c_void;
731731
type TaskSet = send_map::linear::LinearMap<*rust_task,()>;
732732

733733
fn new_taskset() -> TaskSet {
734-
pure fn task_hash(t: &*rust_task) -> uint {
735-
let task: *rust_task = *t;
736-
hash::hash_uint(task as uint) as uint
737-
}
738-
pure fn task_eq(t1: &*rust_task, t2: &*rust_task) -> bool {
739-
let task1: *rust_task = *t1;
740-
let task2: *rust_task = *t2;
741-
task1 == task2
742-
}
743-
744-
send_map::linear::LinearMap(task_hash, task_eq)
734+
send_map::linear::LinearMap()
745735
}
746736
fn taskset_insert(tasks: &mut TaskSet, task: *rust_task) {
747737
let didnt_overwrite = tasks.insert(task, ());

src/libcore/to_bytes.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,19 @@ impl<A: IterBytes> ~A: IterBytes {
290290
}
291291
}
292292

293+
// NB: raw-pointer IterBytes does _not_ dereference
294+
// to the target; it just gives you the pointer-bytes.
295+
impl<A> *A: IterBytes {
296+
#[inline(always)]
297+
fn iter_le_bytes(f: Cb) {
298+
(self as uint).iter_le_bytes(f);
299+
}
300+
#[inline(always)]
301+
fn iter_be_bytes(f: Cb) {
302+
(self as uint).iter_be_bytes(f);
303+
}
304+
}
305+
293306

294307
trait ToBytes {
295308
fn to_le_bytes() -> ~[u8];

src/libstd/map.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import to_str::ToStr;
77
import managed::Managed;
88
import send_map::linear::LinearMap;
99

10+
import core::cmp::Eq;
11+
import hash::Hash;
12+
import to_bytes::IterBytes;
13+
1014
export hashmap, hashfn, eqfn, set, map, chained, hashmap, str_hash;
1115
export box_str_hash;
1216
export bytes_hash, int_hash, uint_hash, set_add;
@@ -478,7 +482,8 @@ fn hash_from_uints<V: copy>(items: &[(uint, V)]) -> hashmap<uint, V> {
478482
}
479483

480484
// XXX Transitionary
481-
impl<K: copy, V: copy> Managed<LinearMap<K, V>>: map<K, V> {
485+
impl<K: Eq IterBytes Hash copy, V: copy> Managed<LinearMap<K, V>>:
486+
map<K, V> {
482487
pure fn size() -> uint {
483488
unchecked {
484489
do self.borrow_const |p| {

src/test/bench/core-map.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,10 @@ fn main(args: ~[~str]) {
168168
let rng = rand::seeded_rng(copy seed);
169169
let mut results = empty_results();
170170
int_benchmarks::<Managed<LinearMap<uint, uint>>>(
171-
|| Managed(LinearMap(uint::hash, uint::eq)),
171+
|| Managed(LinearMap()),
172172
rng, num_keys, &mut results);
173173
str_benchmarks::<Managed<LinearMap<~str, uint>>>(
174-
|| Managed(LinearMap(str::hash, str::eq)),
174+
|| Managed(LinearMap()),
175175
rng, num_keys, &mut results);
176176
write_results("libstd::map::hashmap", &results);
177177
}

0 commit comments

Comments
 (0)