emul/compact/src/main/java/java/lang/ref/ReferenceQueue.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 28 Jan 2013 18:12:47 +0100
branchjdk7-b147
changeset 601 5198affdb915
child 604 3fcc279c921b
permissions -rw-r--r--
Adding ObjectInputStream and ObjectOutputStream (but without implementation). Adding PropertyChange related classes.
     1 /*
     2  * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.lang.ref;
    27 
    28 /**
    29  * Reference queues, to which registered reference objects are appended by the
    30  * garbage collector after the appropriate reachability changes are detected.
    31  *
    32  * @author   Mark Reinhold
    33  * @since    1.2
    34  */
    35 
    36 public class ReferenceQueue<T> {
    37 
    38     /**
    39      * Constructs a new reference-object queue.
    40      */
    41     public ReferenceQueue() { }
    42 
    43     private static class Null extends ReferenceQueue {
    44         boolean enqueue(Reference r) {
    45             return false;
    46         }
    47     }
    48 
    49     static ReferenceQueue NULL = new Null();
    50     static ReferenceQueue ENQUEUED = new Null();
    51 
    52     static private class Lock { };
    53     private Lock lock = new Lock();
    54     private volatile Reference<? extends T> head = null;
    55     private long queueLength = 0;
    56 
    57     boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
    58         synchronized (r) {
    59             if (r.queue == ENQUEUED) return false;
    60             synchronized (lock) {
    61                 r.queue = ENQUEUED;
    62                 r.next = (head == null) ? r : head;
    63                 head = r;
    64                 queueLength++;
    65                 if (r instanceof FinalReference) {
    66                     sun.misc.VM.addFinalRefCount(1);
    67                 }
    68                 lock.notifyAll();
    69                 return true;
    70             }
    71         }
    72     }
    73 
    74     private Reference<? extends T> reallyPoll() {       /* Must hold lock */
    75         if (head != null) {
    76             Reference<? extends T> r = head;
    77             head = (r.next == r) ? null : r.next;
    78             r.queue = NULL;
    79             r.next = r;
    80             queueLength--;
    81             if (r instanceof FinalReference) {
    82                 sun.misc.VM.addFinalRefCount(-1);
    83             }
    84             return r;
    85         }
    86         return null;
    87     }
    88 
    89     /**
    90      * Polls this queue to see if a reference object is available.  If one is
    91      * available without further delay then it is removed from the queue and
    92      * returned.  Otherwise this method immediately returns <tt>null</tt>.
    93      *
    94      * @return  A reference object, if one was immediately available,
    95      *          otherwise <code>null</code>
    96      */
    97     public Reference<? extends T> poll() {
    98         if (head == null)
    99             return null;
   100         synchronized (lock) {
   101             return reallyPoll();
   102         }
   103     }
   104 
   105     /**
   106      * Removes the next reference object in this queue, blocking until either
   107      * one becomes available or the given timeout period expires.
   108      *
   109      * <p> This method does not offer real-time guarantees: It schedules the
   110      * timeout as if by invoking the {@link Object#wait(long)} method.
   111      *
   112      * @param  timeout  If positive, block for up to <code>timeout</code>
   113      *                  milliseconds while waiting for a reference to be
   114      *                  added to this queue.  If zero, block indefinitely.
   115      *
   116      * @return  A reference object, if one was available within the specified
   117      *          timeout period, otherwise <code>null</code>
   118      *
   119      * @throws  IllegalArgumentException
   120      *          If the value of the timeout argument is negative
   121      *
   122      * @throws  InterruptedException
   123      *          If the timeout wait is interrupted
   124      */
   125     public Reference<? extends T> remove(long timeout)
   126         throws IllegalArgumentException, InterruptedException
   127     {
   128         if (timeout < 0) {
   129             throw new IllegalArgumentException("Negative timeout value");
   130         }
   131         synchronized (lock) {
   132             Reference<? extends T> r = reallyPoll();
   133             if (r != null) return r;
   134             for (;;) {
   135                 lock.wait(timeout);
   136                 r = reallyPoll();
   137                 if (r != null) return r;
   138                 if (timeout != 0) return null;
   139             }
   140         }
   141     }
   142 
   143     /**
   144      * Removes the next reference object in this queue, blocking until one
   145      * becomes available.
   146      *
   147      * @return A reference object, blocking until one becomes available
   148      * @throws  InterruptedException  If the wait is interrupted
   149      */
   150     public Reference<? extends T> remove() throws InterruptedException {
   151         return remove(0);
   152     }
   153 
   154 }