private void gc() {
Ref r;
while ((r = (Ref) queue.poll()) != null) {
- // Sun's Java 5 and 6 implementation have a bug where a Reference
- // can be enqueued and dequeued twice on the same reference queue
- // due to a race condition within ReferenceQueue.enqueue(Reference).
- //
- // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6837858
- //
- // We CANNOT permit a Reference to come through us twice, as it will
- // 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)
+ clear(r);
+
+ 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;
table.compareAndSet(s, e1, clean(e1));
+ break;
+ }
}
}
}
long lastAccess;
- private boolean cleared;
-
protected Ref(final PackFile pack, final long position,
final ByteWindow v, final ReferenceQueue<ByteWindow> queue) {
super(v, queue);
this.position = position;
this.size = v.size();
}
-
- final synchronized boolean canClear() {
- if (cleared)
- return false;
- cleared = true;
- return true;
- }
}
private static final class Lock {