rt/emul/compact/src/main/java/java/lang/ref/Reference.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 26 Feb 2013 16:54:16 +0100
changeset 772 d382dacfd73f
parent 604 emul/compact/src/main/java/java/lang/ref/Reference.java@3fcc279c921b
permissions -rw-r--r--
Moving modules around so the runtime is under one master pom and can be built without building other modules that are in the repository
jaroslav@601
     1
/*
jaroslav@601
     2
 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
jaroslav@601
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jaroslav@601
     4
 *
jaroslav@601
     5
 * This code is free software; you can redistribute it and/or modify it
jaroslav@601
     6
 * under the terms of the GNU General Public License version 2 only, as
jaroslav@601
     7
 * published by the Free Software Foundation.  Oracle designates this
jaroslav@601
     8
 * particular file as subject to the "Classpath" exception as provided
jaroslav@601
     9
 * by Oracle in the LICENSE file that accompanied this code.
jaroslav@601
    10
 *
jaroslav@601
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
jaroslav@601
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jaroslav@601
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jaroslav@601
    14
 * version 2 for more details (a copy is included in the LICENSE file that
jaroslav@601
    15
 * accompanied this code).
jaroslav@601
    16
 *
jaroslav@601
    17
 * You should have received a copy of the GNU General Public License version
jaroslav@601
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
jaroslav@601
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jaroslav@601
    20
 *
jaroslav@601
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jaroslav@601
    22
 * or visit www.oracle.com if you need additional information or have any
jaroslav@601
    23
 * questions.
jaroslav@601
    24
 */
jaroslav@601
    25
jaroslav@601
    26
package java.lang.ref;
jaroslav@601
    27
jaroslav@601
    28
jaroslav@601
    29
/**
jaroslav@601
    30
 * Abstract base class for reference objects.  This class defines the
jaroslav@601
    31
 * operations common to all reference objects.  Because reference objects are
jaroslav@601
    32
 * implemented in close cooperation with the garbage collector, this class may
jaroslav@601
    33
 * not be subclassed directly.
jaroslav@601
    34
 *
jaroslav@601
    35
 * @author   Mark Reinhold
jaroslav@601
    36
 * @since    1.2
jaroslav@601
    37
 */
jaroslav@601
    38
jaroslav@601
    39
public abstract class Reference<T> {
jaroslav@601
    40
jaroslav@601
    41
    /* A Reference instance is in one of four possible internal states:
jaroslav@601
    42
     *
jaroslav@601
    43
     *     Active: Subject to special treatment by the garbage collector.  Some
jaroslav@601
    44
     *     time after the collector detects that the reachability of the
jaroslav@601
    45
     *     referent has changed to the appropriate state, it changes the
jaroslav@601
    46
     *     instance's state to either Pending or Inactive, depending upon
jaroslav@601
    47
     *     whether or not the instance was registered with a queue when it was
jaroslav@601
    48
     *     created.  In the former case it also adds the instance to the
jaroslav@601
    49
     *     pending-Reference list.  Newly-created instances are Active.
jaroslav@601
    50
     *
jaroslav@601
    51
     *     Pending: An element of the pending-Reference list, waiting to be
jaroslav@601
    52
     *     enqueued by the Reference-handler thread.  Unregistered instances
jaroslav@601
    53
     *     are never in this state.
jaroslav@601
    54
     *
jaroslav@601
    55
     *     Enqueued: An element of the queue with which the instance was
jaroslav@601
    56
     *     registered when it was created.  When an instance is removed from
jaroslav@601
    57
     *     its ReferenceQueue, it is made Inactive.  Unregistered instances are
jaroslav@601
    58
     *     never in this state.
jaroslav@601
    59
     *
jaroslav@601
    60
     *     Inactive: Nothing more to do.  Once an instance becomes Inactive its
jaroslav@601
    61
     *     state will never change again.
jaroslav@601
    62
     *
jaroslav@601
    63
     * The state is encoded in the queue and next fields as follows:
jaroslav@601
    64
     *
jaroslav@601
    65
     *     Active: queue = ReferenceQueue with which instance is registered, or
jaroslav@601
    66
     *     ReferenceQueue.NULL if it was not registered with a queue; next =
jaroslav@601
    67
     *     null.
jaroslav@601
    68
     *
jaroslav@601
    69
     *     Pending: queue = ReferenceQueue with which instance is registered;
jaroslav@601
    70
     *     next = Following instance in queue, or this if at end of list.
jaroslav@601
    71
     *
jaroslav@601
    72
     *     Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
jaroslav@601
    73
     *     in queue, or this if at end of list.
jaroslav@601
    74
     *
jaroslav@601
    75
     *     Inactive: queue = ReferenceQueue.NULL; next = this.
jaroslav@601
    76
     *
jaroslav@601
    77
     * With this scheme the collector need only examine the next field in order
jaroslav@601
    78
     * to determine whether a Reference instance requires special treatment: If
jaroslav@601
    79
     * the next field is null then the instance is active; if it is non-null,
jaroslav@601
    80
     * then the collector should treat the instance normally.
jaroslav@601
    81
     *
jaroslav@601
    82
     * To ensure that concurrent collector can discover active Reference
jaroslav@601
    83
     * objects without interfering with application threads that may apply
jaroslav@601
    84
     * the enqueue() method to those objects, collectors should link
jaroslav@601
    85
     * discovered objects through the discovered field.
jaroslav@601
    86
     */
jaroslav@601
    87
jaroslav@601
    88
    private T referent;         /* Treated specially by GC */
jaroslav@601
    89
jaroslav@601
    90
    ReferenceQueue<? super T> queue;
jaroslav@601
    91
jaroslav@601
    92
    Reference next;
jaroslav@601
    93
    transient private Reference<T> discovered;  /* used by VM */
jaroslav@601
    94
jaroslav@601
    95
jaroslav@601
    96
    /* Object used to synchronize with the garbage collector.  The collector
jaroslav@601
    97
     * must acquire this lock at the beginning of each collection cycle.  It is
jaroslav@601
    98
     * therefore critical that any code holding this lock complete as quickly
jaroslav@601
    99
     * as possible, allocate no new objects, and avoid calling user code.
jaroslav@601
   100
     */
jaroslav@601
   101
    static private class Lock { };
jaroslav@601
   102
    private static Lock lock = new Lock();
jaroslav@601
   103
jaroslav@601
   104
jaroslav@601
   105
    /* List of References waiting to be enqueued.  The collector adds
jaroslav@601
   106
     * References to this list, while the Reference-handler thread removes
jaroslav@601
   107
     * them.  This list is protected by the above lock object.
jaroslav@601
   108
     */
jaroslav@601
   109
    private static Reference pending = null;
jaroslav@601
   110
jaroslav@601
   111
jaroslav@601
   112
jaroslav@601
   113
    /* -- Referent accessor and setters -- */
jaroslav@601
   114
jaroslav@601
   115
    /**
jaroslav@601
   116
     * Returns this reference object's referent.  If this reference object has
jaroslav@601
   117
     * been cleared, either by the program or by the garbage collector, then
jaroslav@601
   118
     * this method returns <code>null</code>.
jaroslav@601
   119
     *
jaroslav@601
   120
     * @return   The object to which this reference refers, or
jaroslav@601
   121
     *           <code>null</code> if this reference object has been cleared
jaroslav@601
   122
     */
jaroslav@601
   123
    public T get() {
jaroslav@601
   124
        return this.referent;
jaroslav@601
   125
    }
jaroslav@601
   126
jaroslav@601
   127
    /**
jaroslav@601
   128
     * Clears this reference object.  Invoking this method will not cause this
jaroslav@601
   129
     * object to be enqueued.
jaroslav@601
   130
     *
jaroslav@601
   131
     * <p> This method is invoked only by Java code; when the garbage collector
jaroslav@601
   132
     * clears references it does so directly, without invoking this method.
jaroslav@601
   133
     */
jaroslav@601
   134
    public void clear() {
jaroslav@601
   135
        this.referent = null;
jaroslav@601
   136
    }
jaroslav@601
   137
jaroslav@601
   138
jaroslav@601
   139
    /* -- Queue operations -- */
jaroslav@601
   140
jaroslav@601
   141
    /**
jaroslav@601
   142
     * Tells whether or not this reference object has been enqueued, either by
jaroslav@601
   143
     * the program or by the garbage collector.  If this reference object was
jaroslav@601
   144
     * not registered with a queue when it was created, then this method will
jaroslav@601
   145
     * always return <code>false</code>.
jaroslav@601
   146
     *
jaroslav@601
   147
     * @return   <code>true</code> if and only if this reference object has
jaroslav@601
   148
     *           been enqueued
jaroslav@601
   149
     */
jaroslav@601
   150
    public boolean isEnqueued() {
jaroslav@601
   151
        /* In terms of the internal states, this predicate actually tests
jaroslav@601
   152
           whether the instance is either Pending or Enqueued */
jaroslav@601
   153
        synchronized (this) {
jaroslav@601
   154
            return (this.queue != ReferenceQueue.NULL) && (this.next != null);
jaroslav@601
   155
        }
jaroslav@601
   156
    }
jaroslav@601
   157
jaroslav@601
   158
    /**
jaroslav@601
   159
     * Adds this reference object to the queue with which it is registered,
jaroslav@601
   160
     * if any.
jaroslav@601
   161
     *
jaroslav@601
   162
     * <p> This method is invoked only by Java code; when the garbage collector
jaroslav@601
   163
     * enqueues references it does so directly, without invoking this method.
jaroslav@601
   164
     *
jaroslav@601
   165
     * @return   <code>true</code> if this reference object was successfully
jaroslav@601
   166
     *           enqueued; <code>false</code> if it was already enqueued or if
jaroslav@601
   167
     *           it was not registered with a queue when it was created
jaroslav@601
   168
     */
jaroslav@601
   169
    public boolean enqueue() {
jaroslav@601
   170
        return this.queue.enqueue(this);
jaroslav@601
   171
    }
jaroslav@601
   172
jaroslav@601
   173
jaroslav@601
   174
    /* -- Constructors -- */
jaroslav@601
   175
jaroslav@601
   176
    Reference(T referent) {
jaroslav@601
   177
        this(referent, null);
jaroslav@601
   178
    }
jaroslav@601
   179
jaroslav@601
   180
    Reference(T referent, ReferenceQueue<? super T> queue) {
jaroslav@601
   181
        this.referent = referent;
jaroslav@601
   182
        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
jaroslav@601
   183
    }
jaroslav@601
   184
jaroslav@601
   185
}