about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2012-08-30 19:01:22 -0700
committerGraydon Hoare <graydon@mozilla.com>2012-08-30 19:05:54 -0700
commit536cb90a216a08870fbaac6aad93f77f0681537d (patch)
tree92020449953adee5178ec5c9f10901577691d779 /src/libcore
parent3462bb6a462253333758b12a8cb1ee72981329cb (diff)
Migrate core::send_map to random, keyed hashes w/ hash::Hash trait.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/hash.rs2
-rw-r--r--src/libcore/send_map.rs73
-rw-r--r--src/libcore/task.rs12
-rw-r--r--src/libcore/to_bytes.rs13
4 files changed, 48 insertions, 52 deletions
diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs
index 0e9c9110c8e..1b579e1d497 100644
--- a/src/libcore/hash.rs
+++ b/src/libcore/hash.rs
@@ -17,7 +17,7 @@ import io::Writer;
 import io::WriterUtil;
 import to_bytes::IterBytes;
 
-export Streaming, State;
+export Streaming, State, Hash, HashUtil;
 export default_state;
 export hash_bytes_keyed;
 export hash_str_keyed;
diff --git a/src/libcore/send_map.rs b/src/libcore/send_map.rs
index 2b85a0d5784..d5323abe05a 100644
--- a/src/libcore/send_map.rs
+++ b/src/libcore/send_map.rs
@@ -4,16 +4,11 @@ Sendable hash maps.  Very much a work in progress.
 
 */
 
+import cmp::Eq;
+import hash::Hash;
+import to_bytes::IterBytes;
 
-/**
- * A function that returns a hash of a value
- *
- * The hash should concentrate entropy in the lower bits.
- */
-type HashFn<K> = pure fn~(K) -> uint;
-type EqFn<K> = pure fn~(K, K) -> bool;
-
-trait SendMap<K, V: copy> {
+trait SendMap<K:Eq Hash, V: copy> {
     // FIXME(#3148)  ^^^^ once find_ref() works, we can drop V:copy
 
     fn insert(&mut self, +k: K, +v: V) -> bool;
@@ -34,14 +29,14 @@ mod linear {
     export LinearMap, linear_map, linear_map_with_capacity, public_methods;
 
     const initial_capacity: uint = 32u; // 2^5
-    struct Bucket<K,V> {
+    struct Bucket<K:Eq Hash,V> {
         hash: uint;
         key: K;
         value: V;
     }
-    struct LinearMap<K,V> {
-        hashfn: pure fn~(x: &K) -> uint;
-        eqfn: pure fn~(x: &K, y: &K) -> bool;
+    struct LinearMap<K:Eq Hash,V> {
+        k0: u64;
+        k1: u64;
         resize_at: uint;
         size: uint;
         buckets: ~[Option<Bucket<K,V>>];
@@ -58,28 +53,29 @@ mod linear {
         ((capacity as float) * 3. / 4.) as uint
     }
 
-    fn LinearMap<K,V>(
-        +hashfn: pure fn~(x: &K) -> uint,
-        +eqfn: pure fn~(x: &K, y: &K) -> bool) -> LinearMap<K,V> {
-
-        linear_map_with_capacity(hashfn, eqfn, 32)
+    fn LinearMap<K:Eq Hash,V>() -> LinearMap<K,V> {
+        linear_map_with_capacity(32)
     }
 
-    fn linear_map_with_capacity<K,V>(
-        +hashfn: pure fn~(x: &K) -> uint,
-        +eqfn: pure fn~(x: &K, y: &K) -> bool,
+    fn linear_map_with_capacity<K:Eq Hash,V>(
         initial_capacity: uint) -> LinearMap<K,V> {
+        let r = rand::Rng();
+        linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(),
+                                          initial_capacity)
+    }
 
+    fn linear_map_with_capacity_and_keys<K:Eq Hash,V> (
+        k0: u64, k1: u64,
+        initial_capacity: uint) -> LinearMap<K,V> {
         LinearMap {
-            hashfn: hashfn,
-            eqfn: eqfn,
+            k0: k0, k1: k1,
             resize_at: resize_at(initial_capacity),
             size: 0,
             buckets: vec::from_fn(initial_capacity, |_i| None)
         }
     }
 
-    priv impl<K, V> LinearMap<K,V> {
+    priv impl<K:Hash IterBytes Eq, V> LinearMap<K,V> {
         #[inline(always)]
         pure fn to_bucket(&const self,
                           h: uint) -> uint {
@@ -123,7 +119,7 @@ mod linear {
         pure fn bucket_for_key(&const self,
                                buckets: &[Option<Bucket<K,V>>],
                                k: &K) -> SearchResult {
-            let hash = self.hashfn(k);
+            let hash = k.hash_keyed(self.k0, self.k1) as uint;
             self.bucket_for_key_with_hash(buckets, hash, k)
         }
 
@@ -134,7 +130,7 @@ mod linear {
                                          k: &K) -> SearchResult {
             let _ = for self.bucket_sequence(hash) |i| {
                 match buckets[i] {
-                  Some(bkt) => if bkt.hash == hash && self.eqfn(k, &bkt.key) {
+                  Some(bkt) => if bkt.hash == hash && *k == bkt.key {
                     return FoundEntry(i);
                   },
                   None => return FoundHole(i)
@@ -204,7 +200,7 @@ mod linear {
         }
     }
 
-    impl<K,V> LinearMap<K,V> {
+    impl<K:Hash IterBytes Eq,V> LinearMap<K,V> {
         fn insert(&mut self, +k: K, +v: V) -> bool {
             if self.size >= self.resize_at {
                 // n.b.: We could also do this after searching, so
@@ -216,7 +212,7 @@ mod linear {
                 self.expand();
             }
 
-            let hash = self.hashfn(&k);
+            let hash = k.hash_keyed(self.k0, self.k1) as uint;
             self.insert_internal(hash, k, v)
         }
 
@@ -319,7 +315,7 @@ mod linear {
         }
     }
 
-    impl<K,V: copy> LinearMap<K,V> {
+    impl<K:Hash IterBytes Eq, V: copy> LinearMap<K,V> {
         fn find(&const self, k: &K) -> Option<V> {
             match self.bucket_for_key(self.buckets, k) {
               FoundEntry(idx) => {
@@ -346,17 +342,17 @@ mod linear {
 
     }
 
-    impl<K: copy, V: copy> LinearMap<K,V> {
+    impl<K: Hash IterBytes Eq copy, V: copy> LinearMap<K,V> {
         fn each(&self, blk: fn(+K,+V) -> bool) {
             self.each_ref(|k,v| blk(copy *k, copy *v));
         }
     }
-    impl<K: copy, V> LinearMap<K,V> {
+    impl<K: Hash IterBytes Eq copy, V> LinearMap<K,V> {
         fn each_key(&self, blk: fn(+K) -> bool) {
             self.each_key_ref(|k| blk(copy *k));
         }
     }
-    impl<K, V: copy> LinearMap<K,V> {
+    impl<K: Hash IterBytes Eq, V: copy> LinearMap<K,V> {
         fn each_value(&self, blk: fn(+V) -> bool) {
             self.each_value_ref(|v| blk(copy *v));
         }
@@ -368,11 +364,8 @@ mod test {
 
     import linear::LinearMap;
 
-    pure fn uint_hash(x: &uint) -> uint { *x }
-    pure fn uint_eq(x: &uint, y: &uint) -> bool { *x == *y }
-
     fn int_linear_map<V>() -> LinearMap<uint,V> {
-        return LinearMap(uint_hash, uint_eq);
+        return LinearMap();
     }
 
     #[test]
@@ -395,7 +388,7 @@ mod test {
 
     #[test]
     fn conflicts() {
-        let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
+        let mut m = ~linear::linear_map_with_capacity(4);
         assert m.insert(1, 2);
         assert m.insert(5, 3);
         assert m.insert(9, 4);
@@ -406,7 +399,7 @@ mod test {
 
     #[test]
     fn conflict_remove() {
-        let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
+        let mut m = ~linear::linear_map_with_capacity(4);
         assert m.insert(1, 2);
         assert m.insert(5, 3);
         assert m.insert(9, 4);
@@ -417,7 +410,7 @@ mod test {
 
     #[test]
     fn empty() {
-        let mut m = ~linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
+        let mut m = ~linear::linear_map_with_capacity(4);
         assert m.insert(1, 2);
         assert !m.is_empty();
         assert m.remove(&1);
@@ -426,7 +419,7 @@ mod test {
 
     #[test]
     fn iterate() {
-        let mut m = linear::linear_map_with_capacity(uint_hash, uint_eq, 4);
+        let mut m = linear::linear_map_with_capacity(4);
         for uint::range(0, 32) |i| {
             assert (&mut m).insert(i, i*2);
         }
diff --git a/src/libcore/task.rs b/src/libcore/task.rs
index 8cb3c10c40b..f1c461d5c1c 100644
--- a/src/libcore/task.rs
+++ b/src/libcore/task.rs
@@ -731,17 +731,7 @@ type rust_closure = libc::c_void;
 type TaskSet = send_map::linear::LinearMap<*rust_task,()>;
 
 fn new_taskset() -> TaskSet {
-    pure fn task_hash(t: &*rust_task) -> uint {
-        let task: *rust_task = *t;
-        hash::hash_uint(task as uint) as uint
-    }
-    pure fn task_eq(t1: &*rust_task, t2: &*rust_task) -> bool {
-        let task1: *rust_task = *t1;
-        let task2: *rust_task = *t2;
-        task1 == task2
-    }
-
-    send_map::linear::LinearMap(task_hash, task_eq)
+    send_map::linear::LinearMap()
 }
 fn taskset_insert(tasks: &mut TaskSet, task: *rust_task) {
     let didnt_overwrite = tasks.insert(task, ());
diff --git a/src/libcore/to_bytes.rs b/src/libcore/to_bytes.rs
index f4305a74917..e379b3dbc68 100644
--- a/src/libcore/to_bytes.rs
+++ b/src/libcore/to_bytes.rs
@@ -290,6 +290,19 @@ impl<A: IterBytes> ~A: IterBytes {
     }
 }
 
+// NB: raw-pointer IterBytes does _not_ dereference
+// to the target; it just gives you the pointer-bytes.
+impl<A> *A: IterBytes {
+    #[inline(always)]
+    fn iter_le_bytes(f: Cb) {
+        (self as uint).iter_le_bytes(f);
+    }
+    #[inline(always)]
+    fn iter_be_bytes(f: Cb) {
+        (self as uint).iter_be_bytes(f);
+    }
+}
+
 
 trait ToBytes {
     fn to_le_bytes() -> ~[u8];