refactor send_map impl to be based on structs

This commit is contained in:
Niko Matsakis
2012-08-28 11:59:31 -07:00
parent 0031617f30
commit e9b7ce6f57

View File

@@ -13,19 +13,38 @@ Sendable hash maps. Very much a work in progress.
type HashFn<K> = pure fn~(K) -> uint; type HashFn<K> = pure fn~(K) -> uint;
type EqFn<K> = pure fn~(K, K) -> bool; type EqFn<K> = pure fn~(K, K) -> bool;
trait send_map<K, V: copy> {
// FIXME(#3148) ^^^^ once find_ref() works, we can drop V:copy
fn insert(&mut self, +k: K, +v: V) -> bool;
fn remove(&mut self, k: &K) -> bool;
fn clear(&mut self);
pure fn len(&const self) -> uint;
pure fn is_empty(&const self) -> bool;
fn contains_key(&const self, k: &K) -> bool;
fn each_ref(&self, blk: fn(k: &K, v: &V) -> bool);
fn each_key_ref(&self, blk: fn(k: &K) -> bool);
fn each_value_ref(&self, blk: fn(v: &V) -> bool);
fn find(&const self, k: &K) -> Option<V>;
fn get(&const self, k: &K) -> V;
}
/// Open addressing with linear probing. /// Open addressing with linear probing.
mod linear { mod linear {
export LinearMap, linear_map, linear_map_with_capacity, public_methods; export LinearMap, linear_map, linear_map_with_capacity, public_methods;
const initial_capacity: uint = 32u; // 2^5 const initial_capacity: uint = 32u; // 2^5
type Bucket<K,V> = {hash: uint, key: K, value: V}; struct Bucket<K,V> {
enum LinearMap<K,V> { hash: uint;
LinearMap_({ key: K;
hashfn: pure fn~(x: &K) -> uint, value: V;
eqfn: pure fn~(x: &K, y: &K) -> bool, }
resize_at: uint, struct LinearMap<K,V> {
size: uint, hashfn: pure fn~(x: &K) -> uint;
buckets: ~[Option<Bucket<K,V>>]}) eqfn: pure fn~(x: &K, y: &K) -> bool;
resize_at: uint;
size: uint;
buckets: ~[Option<Bucket<K,V>>];
} }
// FIXME(#3148) -- we could rewrite found_entry // FIXME(#3148) -- we could rewrite found_entry
@@ -51,12 +70,13 @@ mod linear {
+eqfn: pure fn~(x: &K, y: &K) -> bool, +eqfn: pure fn~(x: &K, y: &K) -> bool,
initial_capacity: uint) -> LinearMap<K,V> { initial_capacity: uint) -> LinearMap<K,V> {
LinearMap_({ LinearMap {
hashfn: hashfn, hashfn: hashfn,
eqfn: eqfn, eqfn: eqfn,
resize_at: resize_at(initial_capacity), resize_at: resize_at(initial_capacity),
size: 0, size: 0,
buckets: vec::from_fn(initial_capacity, |_i| None)}) buckets: vec::from_fn(initial_capacity, |_i| None)
}
} }
priv impl<K, V> LinearMap<K,V> { priv impl<K, V> LinearMap<K,V> {
@@ -136,15 +156,19 @@ mod linear {
for uint::range(0, old_capacity) |i| { for uint::range(0, old_capacity) |i| {
let mut bucket = None; let mut bucket = None;
bucket <-> old_buckets[i]; bucket <-> old_buckets[i];
if bucket.is_some() { self.insert_opt_bucket(bucket);
self.insert_bucket(bucket);
}
} }
} }
fn insert_bucket(&mut self, +bucket: Option<Bucket<K,V>>) { fn insert_opt_bucket(&mut self, +bucket: Option<Bucket<K,V>>) {
let {hash, key, value} <- option::unwrap(bucket); match move bucket {
let _ = self.insert_internal(hash, key, value); Some(Bucket {hash: move hash,
key: move key,
value: move value}) => {
self.insert_internal(hash, key, value);
}
None => {}
}
} }
/// Inserts the key value pair into the buckets. /// Inserts the key value pair into the buckets.
@@ -156,14 +180,18 @@ mod linear {
FoundHole(idx) => { FoundHole(idx) => {
debug!("insert fresh (%?->%?) at idx %?, hash %?", debug!("insert fresh (%?->%?) at idx %?, hash %?",
k, v, idx, hash); k, v, idx, hash);
self.buckets[idx] = Some({hash: hash, key: k, value: v}); self.buckets[idx] = Some(Bucket {hash: hash,
key: k,
value: v});
self.size += 1; self.size += 1;
return true; return true;
} }
FoundEntry(idx) => { FoundEntry(idx) => {
debug!("insert overwrite (%?->%?) at idx %?, hash %?", debug!("insert overwrite (%?->%?) at idx %?, hash %?",
k, v, idx, hash); k, v, idx, hash);
self.buckets[idx] = Some({hash: hash, key: k, value: v}); self.buckets[idx] = Some(Bucket {hash: hash,
key: k,
value: v});
return false; return false;
} }
} }
@@ -223,7 +251,7 @@ mod linear {
while self.buckets[idx].is_some() { while self.buckets[idx].is_some() {
let mut bucket = None; let mut bucket = None;
bucket <-> self.buckets[idx]; bucket <-> self.buckets[idx];
self.insert_bucket(bucket); self.insert_opt_bucket(bucket);
idx = self.next_bucket(idx, len_buckets); idx = self.next_bucket(idx, len_buckets);
} }
self.size -= 1; self.size -= 1;