// TODO: it isn't actually multithreaded at all
sclass CalculateEachElementOnce {
Map calculating = syncMap();
Map> calculated = syncMap();
synchronized B get(A a, IF1 f) {
Flag flag = calculating.get(a);
if (flag != null) {
flag.waitUntilUp();
ret unpackOKOrError(calculated.get(a));
} else {
flag = new Flag;
calculating.put(a, flag);
OKOrError b = okOrError(() -> f.get(a));
calculated.put(a, b);
calculating.remove(a);
flag.raise();
ret b!;
}
}
}