< prev index next >

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

Print this page
rev 50093 : [mq]: pp2_work

@@ -41,75 +41,121 @@
  * @since    1.2
  */
 
 public abstract class Reference<T> {
 
-    /* A Reference instance is in one of four possible internal states:
+    /* 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, 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.
+     * 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
-     *     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.
+     * 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;
 
-    /* When active:   NULL
-     *     pending:   this
-     *    Enqueued:   next reference in queue (or this if last)
-     *    Inactive:   this
+    /* 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;
 
-    /* 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
+    /* 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;  /* used by VM */
+    private transient Reference<T> discovered;
 
 
     /* High-priority thread to enqueue pending References
      */
     private static class ReferenceHandler extends Thread {
< prev index next >