Keep track of a static collection of all PackWriter instances
Stored in a weak concurrent hash map, which we clean up while iterating. Usually the weak reference behavior should not be necessary because PackWriters should be released with release(), but we still want to avoid leaks when dealing with broken client code. Change-Id: I337abb952ac6524f7f920fedf04065edf84d01d2
This commit is contained in:
parent
f26b79d044
commit
2b584b9216
|
@ -49,6 +49,7 @@
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.security.MessageDigest;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
|
@ -62,7 +63,9 @@
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -141,6 +144,50 @@
|
|||
public class PackWriter {
|
||||
private static final int PACK_VERSION_GENERATED = 2;
|
||||
|
||||
private static final Map<WeakReference<PackWriter>, Boolean> instances =
|
||||
new ConcurrentHashMap<WeakReference<PackWriter>, Boolean>();
|
||||
|
||||
private static final Iterable<PackWriter> instancesIterable = new Iterable<PackWriter>() {
|
||||
public Iterator<PackWriter> iterator() {
|
||||
return new Iterator<PackWriter>() {
|
||||
private final Iterator<WeakReference<PackWriter>> it =
|
||||
instances.keySet().iterator();
|
||||
private PackWriter next;
|
||||
|
||||
public boolean hasNext() {
|
||||
if (next != null)
|
||||
return true;
|
||||
while (it.hasNext()) {
|
||||
WeakReference<PackWriter> ref = it.next();
|
||||
next = ref.get();
|
||||
if (next != null)
|
||||
return true;
|
||||
it.remove();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public PackWriter next() {
|
||||
if (hasNext()) {
|
||||
PackWriter result = next;
|
||||
next = null;
|
||||
return result;
|
||||
}
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/** @return all allocated, non-released PackWriters instances. */
|
||||
public static Iterable<PackWriter> getInstances() {
|
||||
return instancesIterable;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final BlockList<ObjectToPack> objectsLists[] = new BlockList[Constants.OBJ_TAG + 1];
|
||||
{
|
||||
|
@ -176,6 +223,8 @@ public class PackWriter {
|
|||
|
||||
private final MutableState state;
|
||||
|
||||
private final WeakReference<PackWriter> selfRef;
|
||||
|
||||
private Statistics.ObjectType typeStats;
|
||||
|
||||
private List<ObjectToPack> sortedByName;
|
||||
|
@ -269,6 +318,8 @@ public PackWriter(final PackConfig config, final ObjectReader reader) {
|
|||
reuseValidate = true; // be paranoid by default
|
||||
stats = new Statistics();
|
||||
state = new MutableState();
|
||||
selfRef = new WeakReference<PackWriter>(this);
|
||||
instances.put(selfRef, Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -901,6 +952,7 @@ public void release() {
|
|||
myDeflater.end();
|
||||
myDeflater = null;
|
||||
}
|
||||
instances.remove(selfRef);
|
||||
}
|
||||
|
||||
private void searchForReuse(ProgressMonitor monitor) throws IOException {
|
||||
|
|
Loading…
Reference in New Issue