src/share/classes/java/lang/ref/Reference.java
Print this page
*** 25,35 ****
package java.lang.ref;
import sun.misc.Cleaner;
-
/**
* Abstract base class for reference objects. This class defines the
* operations common to all reference objects. Because reference objects are
* implemented in close cooperation with the garbage collector, this class may
* not be subclassed directly.
--- 25,34 ----
*** 67,77 ****
* Active: queue = ReferenceQueue with which instance is registered, or
* ReferenceQueue.NULL if it was not registered with a queue; next =
* null.
*
* Pending: queue = ReferenceQueue with which instance is registered;
! * next = Following instance in queue, or this if at end of list.
*
* Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
* in queue, or this if at end of list.
*
* Inactive: queue = ReferenceQueue.NULL; next = this.
--- 66,76 ----
* Active: queue = ReferenceQueue with which instance is registered, or
* ReferenceQueue.NULL if it was not registered with a queue; next =
* null.
*
* Pending: queue = ReferenceQueue with which instance is registered;
! * next = this
*
* Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
* in queue, or this if at end of list.
*
* Inactive: queue = ReferenceQueue.NULL; next = this.
*** 79,99 ****
* With this scheme the collector need only examine the next field in order
* to determine whether a Reference instance requires special treatment: If
* 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
* objects without interfering with application threads that may apply
* the enqueue() method to those objects, collectors should link
! * discovered objects through the discovered field.
*/
private T referent; /* Treated specially by GC */
ReferenceQueue<? super T> queue;
Reference next;
transient private Reference<T> discovered; /* used by VM */
/* Object used to synchronize with the garbage collector. The collector
* must acquire this lock at the beginning of each collection cycle. It is
--- 78,109 ----
* With this scheme the collector need only examine the next field in order
* to determine whether a Reference instance requires special treatment: If
* 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 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. 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
+ * pending: next element in the pending list (or null if last)
+ * otherwise: NULL
+ */
transient private Reference<T> discovered; /* used by VM */
/* Object used to synchronize with the garbage collector. The collector
* must acquire this lock at the beginning of each collection cycle. It is
*** 104,114 ****
private static Lock lock = new Lock();
/* 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.
*/
private static Reference pending = null;
/* High-priority thread to enqueue pending References
*/
--- 114,125 ----
private static Lock lock = new Lock();
/* 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. The
! * list uses the discovered field to link its elements.
*/
private static Reference pending = null;
/* High-priority thread to enqueue pending References
*/
*** 118,135 ****
super(g, name);
}
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;
} else {
try {
lock.wait();
} catch (InterruptedException x) { }
continue;
--- 129,144 ----
super(g, name);
}
public void run() {
for (;;) {
Reference r;
synchronized (lock) {
if (pending != null) {
r = pending;
! pending = r.discovered;
! r.discovered = null;
} else {
try {
lock.wait();
} catch (InterruptedException x) { }
continue;
*** 199,212 ****
*
* @return <code>true</code> if and only if this reference object has
* 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);
}
}
/**
* Adds this reference object to the queue with which it is registered,
--- 208,219 ----
*
* @return <code>true</code> if and only if this reference object has
* been enqueued
*/
public boolean isEnqueued() {
synchronized (this) {
! return (this.next != null && this.queue == ReferenceQueue.ENQUEUED);
}
}
/**
* Adds this reference object to the queue with which it is registered,