Skip to content

Commit 6277b46

Browse files
committed
More stdlib hashmap work. Add a simple test and XFAIL it due to a valgrind-spotted UMR.
1 parent 5b2451c commit 6277b46

File tree

3 files changed

+47
-21
lines changed

3 files changed

+47
-21
lines changed

src/Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ TEST_XFAILS_X86 := $(TASK_XFAILS) \
395395
test/run-pass/generic-recursive-tag.rs \
396396
test/run-pass/iter-ret.rs \
397397
test/run-pass/lib-deque.rs \
398+
test/run-pass/lib-map.rs \
398399
test/run-pass/mlist-cycle.rs \
399400
test/run-pass/obj-as.rs \
400401
test/run-pass/task-comm.rs \
@@ -468,6 +469,7 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
468469
lazy-init.rs \
469470
lazychan.rs \
470471
lib-deque.rs \
472+
lib-map.rs \
471473
lib-rand.rs \
472474
linear-for-loop.rs \
473475
list.rs \

src/lib/map.rs

+29-21
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import std._vec;
1010

1111

1212
type hashfn[K] = fn(&K) -> uint;
13-
type eqfn[K] = fn(&K) -> bool;
13+
type eqfn[K] = fn(&K, &K) -> bool;
1414

1515
type hashmap[K, V] = obj {
1616
fn insert(&K key, &V val);
@@ -46,49 +46,55 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
4646
// is always a power of 2), so that all buckets are probed for a
4747
// fixed key.
4848

49-
fn hashl[K](hashfn[K] hasher, uint nbkts, &K key) -> uint {
49+
fn hashl[K](&hashfn[K] hasher, uint nbkts, &K key) -> uint {
5050
ret (hasher(key) >>> (sys.rustrt.size_of[uint]() * 8u / 2u))
5151
% nbkts;
5252
}
5353

54-
fn hashr[K](hashfn[K] hasher, uint nbkts, &K key) -> uint {
54+
fn hashr[K](&hashfn[K] hasher, uint nbkts, &K key) -> uint {
5555
ret ((((~ 0u) >>> (sys.rustrt.size_of[uint]() * 8u / 2u))
5656
& hasher(key)) * 2u + 1u)
5757
% nbkts;
5858
}
5959

60-
fn hash[K](hashfn[K] hasher, uint nbkts, &K key, uint i) -> uint {
60+
fn hash[K](&hashfn[K] hasher, uint nbkts, &K key, uint i) -> uint {
6161
ret hashl[K](hasher, nbkts, key) + i * hashr[K](hasher, nbkts, key);
6262
}
6363

6464
/**
6565
* We attempt to never call this with a full table. If we do, it
6666
* will fail.
6767
*/
68-
fn insert_common[K, V](hashfn[K] hasher,
68+
fn insert_common[K, V](&hashfn[K] hasher,
69+
&eqfn[K] eqer,
6970
vec[mutable bucket[K, V]] bkts,
7071
uint nbkts,
7172
&K key,
7273
&V val)
74+
-> bool
7375
{
7476
let uint i = 0u;
7577
while (i < nbkts) {
7678
// FIXME (issue #94): as in find_common()
7779
let int j = (hash[K](hasher, nbkts, key, i)) as int;
7880
alt (bkts.(j)) {
79-
case (some[K, V](_, _)) {
81+
case (some[K, V](k, _)) {
82+
if (eqer(key, k)) {
83+
ret false;
84+
}
8085
i += 1u;
8186
}
8287
case (_) {
8388
bkts.(j) = some[K, V](key, val);
84-
ret;
89+
ret true;
8590
}
8691
}
8792
}
8893
fail; // full table
8994
}
9095

91-
fn find_common[K, V](hashfn[K] hasher,
96+
fn find_common[K, V](&hashfn[K] hasher,
97+
&eqfn[K] eqer,
9298
vec[mutable bucket[K, V]] bkts,
9399
uint nbkts,
94100
&K key)
@@ -99,29 +105,31 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
99105
// FIXME (issue #94): Pending bugfix, remove uint coercion.
100106
let int j = (hash[K](hasher, nbkts, key, i)) as int;
101107
alt (bkts.(j)) {
102-
case (some[K, V](_, val)) {
103-
ret util.some[V](val);
108+
case (some[K, V](k, v)) {
109+
if (eqer(key, k)) {
110+
ret util.some[V](v);
111+
}
104112
}
105113
case (nil[K, V]()) {
106114
ret util.none[V]();
107115
}
108-
case (deleted[K, V]()) {
109-
i += 1u;
110-
}
116+
case (deleted[K, V]()) { }
111117
}
118+
i += 1u;
112119
}
113120
ret util.none[V]();
114121
}
115122

116123

117-
fn rehash[K, V](hashfn[K] hasher,
124+
fn rehash[K, V](&hashfn[K] hasher,
125+
&eqfn[K] eqer,
118126
vec[mutable bucket[K, V]] oldbkts, uint noldbkts,
119127
vec[mutable bucket[K, V]] newbkts, uint nnewbkts)
120128
{
121129
for (bucket[K, V] b in oldbkts) {
122130
alt (b) {
123131
case (some[K, V](k, v)) {
124-
insert_common[K, V](hasher, newbkts, nnewbkts, k, v);
132+
insert_common[K, V](hasher, eqer, newbkts, nnewbkts, k, v);
125133
}
126134
case (_) { }
127135
}
@@ -144,28 +152,28 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
144152
check ((nnewbkts as int) > 0);
145153

146154
let vec[mutable bucket[K, V]] newbkts = make_buckets[K, V](nnewbkts);
147-
rehash[K, V](hasher, bkts, nbkts, newbkts, nnewbkts);
155+
rehash[K, V](hasher, eqer, bkts, nbkts, newbkts, nnewbkts);
148156
}
149-
insert_common[K, V](hasher, bkts, nbkts, key, val);
157+
insert_common[K, V](hasher, eqer, bkts, nbkts, key, val);
150158
nelts += 1u;
151159
}
152160

153161
fn contains_key(&K key) -> bool {
154-
alt (find_common[K, V](hasher, bkts, nbkts, key)) {
162+
alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) {
155163
case (util.some[V](_)) { ret true; }
156164
case (_) { ret false; }
157165
}
158166
}
159167

160168
fn get(&K key) -> V {
161-
alt (find_common[K, V](hasher, bkts, nbkts, key)) {
169+
alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) {
162170
case (util.some[V](val)) { ret val; }
163171
case (_) { fail; }
164172
}
165173
}
166174

167175
fn find(&K key) -> util.option[V] {
168-
be find_common[K, V](hasher, bkts, nbkts, key);
176+
be find_common[K, V](hasher, eqer, bkts, nbkts, key);
169177
}
170178

171179
fn remove(&K key) -> util.option[V] {
@@ -191,7 +199,7 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
191199

192200
fn rehash() {
193201
let vec[mutable bucket[K, V]] newbkts = make_buckets[K, V](nbkts);
194-
rehash[K, V](hasher, bkts, nbkts, newbkts, nbkts);
202+
rehash[K, V](hasher, eqer, bkts, nbkts, newbkts, nbkts);
195203
bkts = newbkts;
196204
}
197205
}

src/test/run-pass/lib-map.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// -*- rust -*-
2+
3+
use std;
4+
import std.map;
5+
6+
fn test_simple() {
7+
fn eq(&uint x, &uint y) -> bool { ret x == y; }
8+
9+
let map.hashfn[uint] hasher = std.util.id[uint];
10+
let map.eqfn[uint] eqer = eq;
11+
let map.hashmap[uint, uint] hm = map.mk_hashmap[uint, uint](hasher, eqer);
12+
}
13+
14+
fn main() {
15+
test_simple();
16+
}

0 commit comments

Comments
 (0)