< prev index next >

src/java.base/share/classes/java/lang/ref/Reference.java

Print this page
rev 50093 : [mq]: pp2_work

*** 41,115 **** * @since 1.2 */ public abstract class Reference<T> { ! /* A Reference instance is in one of four possible internal states: * * Active: Subject to special treatment by the garbage collector. Some ! * time after the collector detects that the reachability of the ! * referent has changed to the appropriate state, it changes the ! * instance's state to either Pending or Inactive, depending upon ! * whether or not the instance was registered with a queue when it was ! * created. In the former case it also adds the instance to the ! * pending-Reference list. Newly-created instances are Active. * * Pending: An element of the pending-Reference list, waiting to be ! * enqueued by the Reference-handler thread. Unregistered instances ! * are never in this state. ! * ! * Enqueued: An element of the queue with which the instance was ! * registered when it was created. When an instance is removed from ! * its ReferenceQueue, it is made Inactive. Unregistered instances are ! * never in this state. ! * ! * Inactive: Nothing more to do. Once an instance becomes Inactive its ! * state will never change again. ! * ! * The state is encoded in the queue and next fields as follows: ! * ! * 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. ! * ! * 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 */ volatile ReferenceQueue<? super T> queue; ! /* When active: NULL ! * pending: this ! * Enqueued: next reference in queue (or this if last) ! * Inactive: this */ @SuppressWarnings("rawtypes") volatile 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 */ ! private transient Reference<T> discovered; /* used by VM */ /* High-priority thread to enqueue pending References */ private static class ReferenceHandler extends Thread { --- 41,161 ---- * @since 1.2 */ public abstract class Reference<T> { ! /* The state of a Reference object is characterized by two attributes. It ! * may be either "active", "pending", or "inactive". It may also be ! * either "registered", "enqueued", "dequeued", or "unregistered". * * Active: Subject to special treatment by the garbage collector. Some ! * time after the collector detects that the reachability of the referent ! * has changed to the appropriate state, the collector "notifies" the ! * reference, changing the state to either "pending" or "inactive". ! * referent != null; discovered = null, or in GC discovered list. * * Pending: An element of the pending-Reference list, waiting to be ! * processed by the Reference-handler thread. The pending-Reference list ! * is linked through the discovered fields of references in the list. ! * referent = null; discovered = next element in pending-Reference list. ! * ! * Inactive: Neither Active nor Pending. ! * referent = null. ! * ! * Registered: Associated with a queue when created, and not yet added to ! * the queue. ! * queue = the associated queue. ! * ! * Enqueued: Added to the associated queue, and not yet removed. ! * queue = ReferenceQueue.ENQUEUE; next = next entry in list, or this to ! * indicate end of list. ! * ! * Dequeued: Added to the associated queue and then removed. ! * queue = ReferenceQueue.NULL; next = this. ! * ! * Unregistered: Not associated with a queue when created. ! * queue = ReferenceQueue.NULL. ! * ! * The collector only needs to examine the referent field and the ! * discovered field to determine whether a normal Reference object needs ! * special treatment. If the referent is non-null and not known to be ! * live, then it may need to be discovered for possible later ! * notification. But if the discovered field is non-null, then either (1) ! * it has already been discovered, or (2) it is in the pending list. ! * ! * FinalReference differs from other references, because a FinalReference ! * is not cleared when notified. The referent being null or not cannot be ! * used to distinguish between the active state and pending or inactive ! * states. However, FinalReferences do not support enqueue(). Instead, ! * the next field of a FinalReference object is set to the object when it ! * is added to the pending list, and the use of this as the value of next ! * in the enqueued and dequeued states maintains the non-active state. An ! * additional check that the next field is null is required to determine ! * that a FinalReference object is active. ! * ! * Initial states: ! * active/registered ! * active/unregistered [1] ! * ! * Transitions: ! * active/registered -> pending/registered - GC ! * -> inactive/registered - clear ! * -> inactive/enqueued - enqueue [2] ! * pending/registered -> pending/enqueued - enqueue [2] ! * -> inactive/enqueued - pending list processing ! * pending/enqueued -> inactive/enqueued - pending list processing ! * -> pending/dequeued - poll/remove ! * pending/dequeued -> inactive/dequeued - pending list processing ! * inactive/registered -> inactive/enqueued - enqueue [2] ! * inactive/enqueued -> inactive/dequeued - poll/remove ! * ! * active/unregistered -> pending/unregistered - GC ! * -> inactive/unregistered - GC, clear, enqueue ! * pending/unregistered -> inactive/unregistered - pending list processing ! * ! * Terminal states: ! * inactive/dequeued ! * inactive/unregistered ! * ! * Unreachable states (because enqueue also clears): ! * active/enqeued ! * active/dequeued ! * ! * [1] Unregistered is not permitted for FinalReferences. ! * ! * [2] These transitions are not possible for FinalReferences, making ! * pending/enqueued and pending/dequeued unreachable, and ! * inactive/registered terminal. */ private T referent; /* Treated specially by GC */ volatile ReferenceQueue<? super T> queue; ! /* The link in a ReferenceQueue's list of Reference objects. ! * ! * When registered: null ! * enqueued: next element in queue (or this if last) ! * dequeued: this (marking FinalReferences as inactive) ! * unregistered: null */ @SuppressWarnings("rawtypes") volatile Reference next; ! /* Used by the garbage collector to accumulate Reference objects that need ! * to be revisited in order to decide whether they should be notified. ! * Also used as the link in the pending-Reference list. The discovered ! * field and the next field are distinct to allow the enqueue() method to ! * be applied to a Reference object while it is either in the ! * pending-Reference list or in the garbage collector's discovered set. ! * ! * When active: null or next element in a discovered reference list ! * maintained by the GC (or this if last) ! * pending: next element in the pending-Reference list (null if last) ! * inactive: null */ ! private transient Reference<T> discovered; /* High-priority thread to enqueue pending References */ private static class ReferenceHandler extends Thread {
< prev index next >