--- a/jdk/src/share/classes/java/lang/ref/Reference.java Mon Oct 31 16:23:43 2011 -0700
+++ b/jdk/src/share/classes/java/lang/ref/Reference.java Mon Oct 31 17:38:15 2011 -0700
@@ -27,7 +27,6 @@
import sun.misc.Cleaner;
-
/**
* Abstract base class for reference objects. This class defines the
* operations common to all reference objects. Because reference objects are
@@ -69,7 +68,7 @@
* null.
*
* Pending: queue = ReferenceQueue with which instance is registered;
- * next = Following instance in queue, or this if at end of list.
+ * next = this
*
* Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
* in queue, or this if at end of list.
@@ -81,17 +80,28 @@
* the next field is null then the instance is active; if it is non-null,
* then the collector should treat the instance normally.
*
- * To ensure that concurrent collector can discover active Reference
+ * To ensure that a concurrent collector can discover active Reference
* objects without interfering with application threads that may apply
* the enqueue() method to those objects, collectors should link
- * discovered objects through the discovered field.
+ * discovered objects through the discovered field. The discovered
+ * field is also used for linking Reference objects in the pending list.
*/
private T referent; /* Treated specially by GC */
ReferenceQueue<? super T> queue;
+ /* When active: NULL
+ * pending: this
+ * Enqueued: next reference in queue (or this if last)
+ * Inactive: this
+ */
Reference next;
+
+ /* When active: next element in a discovered reference list maintained by GC (or this if last)
+ * pending: next element in the pending list (or null if last)
+ * otherwise: NULL
+ */
transient private Reference<T> discovered; /* used by VM */
@@ -106,7 +116,8 @@
/* List of References waiting to be enqueued. The collector adds
* References to this list, while the Reference-handler thread removes
- * them. This list is protected by the above lock object.
+ * them. This list is protected by the above lock object. The
+ * list uses the discovered field to link its elements.
*/
private static Reference pending = null;
@@ -120,14 +131,12 @@
public void run() {
for (;;) {
-
Reference r;
synchronized (lock) {
if (pending != null) {
r = pending;
- Reference rn = r.next;
- pending = (rn == r) ? null : rn;
- r.next = r;
+ pending = r.discovered;
+ r.discovered = null;
} else {
try {
lock.wait();
@@ -201,10 +210,8 @@
* been enqueued
*/
public boolean isEnqueued() {
- /* In terms of the internal states, this predicate actually tests
- whether the instance is either Pending or Enqueued */
synchronized (this) {
- return (this.queue != ReferenceQueue.NULL) && (this.next != null);
+ return (this.next != null && this.queue == ReferenceQueue.ENQUEUED);
}
}