sclass WeakValueMap is AutoCloseable {
// A value that has been stored with this key has been garbage
// collected.
event valueForKeyReleased(A key);
// internal
Map> map = syncMap();
RunnablesReferenceQueue queue;
class MyRef extends WeakRef is Runnable {
A key;
*(A *key, B value) { super(value, queue()!); }
run {
syncMapRemoveKeyAndValuePair(map, key, this);
valueForKeyReleased(key);
}
}
// public methods follow
B get(A key) {
ret getWeakRef(map.get(key));
}
B put(A key, B value) {
synchronized(mutex()) {
if (value == null) {
B old = getWeakRef(map.get(key));
map.remove(key);
ret old;
} else
ret getWeakRef(map.put(key, new MyRef(key, value)));
}
}
O mutex() { ret collectionMutex(map); }
RunnablesReferenceQueue queue() {
synchronized(mutex()) {
if (queue == null) queue = new RunnablesReferenceQueue;
ret queue;
}
}
close {
synchronized(mutex()) {
dispose queue;
}
}
}