|
|
@ -496,31 +496,16 @@ public class WindowCache { |
|
|
|
private void gc() { |
|
|
|
private void gc() { |
|
|
|
Ref r; |
|
|
|
Ref r; |
|
|
|
while ((r = (Ref) queue.poll()) != null) { |
|
|
|
while ((r = (Ref) queue.poll()) != null) { |
|
|
|
// Sun's Java 5 and 6 implementation have a bug where a Reference
|
|
|
|
clear(r); |
|
|
|
// can be enqueued and dequeued twice on the same reference queue
|
|
|
|
|
|
|
|
// due to a race condition within ReferenceQueue.enqueue(Reference).
|
|
|
|
final int s = slot(r.pack, r.position); |
|
|
|
//
|
|
|
|
final Entry e1 = table.get(s); |
|
|
|
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6837858
|
|
|
|
for (Entry n = e1; n != null; n = n.next) { |
|
|
|
//
|
|
|
|
if (n.ref == r) { |
|
|
|
// We CANNOT permit a Reference to come through us twice, as it will
|
|
|
|
n.dead = true; |
|
|
|
// skew the resource counters we maintain. Our canClear() check here
|
|
|
|
|
|
|
|
// provides a way to skip the redundant dequeues, if any.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
if (r.canClear()) { |
|
|
|
|
|
|
|
clear(r); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boolean found = false; |
|
|
|
|
|
|
|
final int s = slot(r.pack, r.position); |
|
|
|
|
|
|
|
final Entry e1 = table.get(s); |
|
|
|
|
|
|
|
for (Entry n = e1; n != null; n = n.next) { |
|
|
|
|
|
|
|
if (n.ref == r) { |
|
|
|
|
|
|
|
n.dead = true; |
|
|
|
|
|
|
|
found = true; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (found) |
|
|
|
|
|
|
|
table.compareAndSet(s, e1, clean(e1)); |
|
|
|
table.compareAndSet(s, e1, clean(e1)); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -581,8 +566,6 @@ public class WindowCache { |
|
|
|
|
|
|
|
|
|
|
|
long lastAccess; |
|
|
|
long lastAccess; |
|
|
|
|
|
|
|
|
|
|
|
private boolean cleared; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected Ref(final PackFile pack, final long position, |
|
|
|
protected Ref(final PackFile pack, final long position, |
|
|
|
final ByteWindow v, final ReferenceQueue<ByteWindow> queue) { |
|
|
|
final ByteWindow v, final ReferenceQueue<ByteWindow> queue) { |
|
|
|
super(v, queue); |
|
|
|
super(v, queue); |
|
|
@ -590,13 +573,6 @@ public class WindowCache { |
|
|
|
this.position = position; |
|
|
|
this.position = position; |
|
|
|
this.size = v.size(); |
|
|
|
this.size = v.size(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
final synchronized boolean canClear() { |
|
|
|
|
|
|
|
if (cleared) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
cleared = true; |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static final class Lock { |
|
|
|
private static final class Lock { |
|
|
|