!7
static int n = 1000000;
sbool done;
// iterate safely (& quickly) in the face of concurrent modifications
// is now called concurrentlyIterateKeys in the library
static IterableIterator iterateKeysQuickly(final NavigableMap map) {
ret iteratorFromFunction(new F0() {
Iterator it = keys(map).iterator();
A key;
A get() {
synchronized(map) {
try {
if (!it.hasNext()) null;
ret key = it.next();
} catch (ConcurrentModificationException e) {
print("Re-iterating");
it = map.tailMap(key, false).keySet().iterator();
if (!it.hasNext()) null;
ret key = it.next(); // Can't throw another exception
}
}
}
});
}
p {
final NavigableMap map = synchroNavigableMap(litcimap());
final new L ids;
repeat n {
map.put(addAndReturn(ids, randomID()), Bool.TRUE);
}
long sum = 0;
repeat 5 {
int i = 0;
sum = 0;
time "Iterating" {
for (S key : keys(map)) {
if (!key.startsWith("_")) {
++i;
sum += key.hashCode();
}
}
}
assertEquals(i, n);
}
thread "Interfere" {
repeat with ms sleep 10 {
if (done) ret;
synchronized(map) {
map.put("_" + randomID(), Bool.TRUE);
}
}
}
repeat 5 {
int i = 0;
long sum2 = 0;
time "Iterating quickly" {
for (S key : iterateKeysQuickly(map)) {
if (!key.startsWith("_")) {
++i;
sum2 += key.hashCode();
}
}
}
assertEquals(i, n);
assertEquals(sum, sum2);
}
done = true;
}