001: /*
002: * @(#)ReferenceQueue.java 1.23 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.lang.ref;
029:
030: /**
031: * Reference queues, to which registered reference objects are appended by the
032: * garbage collector after the appropriate reachability changes are detected.
033: *
034: * @version 1.17 10/31/00
035: * @author Mark Reinhold
036: * @since 1.2
037: */
038:
039: public class ReferenceQueue {
040:
041: /**
042: * Constructs a new reference-object queue.
043: */
044: public ReferenceQueue() {
045: }
046:
047: private static class Null extends ReferenceQueue {
048: boolean enqueue(Reference r) {
049: return false;
050: }
051: }
052:
053: static ReferenceQueue NULL = new Null();
054: static ReferenceQueue ENQUEUED = new Null();
055:
056: static private class Lock {
057: };
058:
059: private Lock lock = new Lock();
060: private Reference head = null;
061: private long queueLength = 0;
062:
063: boolean enqueue(Reference r) { /* Called only by Reference class */
064: synchronized (r) {
065: if (r.queue == ENQUEUED)
066: return false;
067: synchronized (lock) {
068: r.queue = ENQUEUED;
069: r.next = (head == null) ? r : head;
070: head = r;
071: queueLength++;
072: lock.notifyAll();
073: return true;
074: }
075: }
076: }
077:
078: private Reference reallyPoll() { /* Must hold lock */
079: if (head != null) {
080: Reference r = head;
081: head = (r.next == r) ? null : r.next;
082: r.queue = NULL;
083: r.next = r;
084: queueLength--;
085: return r;
086: }
087: return null;
088: }
089:
090: /**
091: * Polls this queue to see if a reference object is available. If one is
092: * available without further delay then it is removed from the queue and
093: * returned. Otherwise this method immediately returns <tt>null</tt>.
094: *
095: * @return A reference object, if one was immediately available,
096: * otherwise <code>null</code>
097: */
098: public Reference poll() {
099: synchronized (lock) {
100: return reallyPoll();
101: }
102: }
103:
104: /**
105: * Removes the next reference object in this queue, blocking until either
106: * one becomes available or the given timeout period expires.
107: *
108: * <p> This method does not offer real-time guarantees: It schedules the
109: * timeout as if by invoking the {@link Object#wait(long)} method.
110: *
111: * @param timeout If positive, block for up <code>timeout</code>
112: * milliseconds while waiting for a reference to be
113: * added to this queue. If zero, block indefinitely.
114: *
115: * @return A reference object, if one was available within the specified
116: * timeout period, otherwise <code>null</code>
117: *
118: * @throws IllegalArgumentException
119: * If the value of the timeout argument is negative
120: *
121: * @throws InterruptedException
122: * If the timeout wait is interrupted
123: */
124: public Reference remove(long timeout)
125: throws IllegalArgumentException, InterruptedException {
126: if (timeout < 0) {
127: throw new IllegalArgumentException("Negative timeout value");
128: }
129: synchronized (lock) {
130: Reference r = reallyPoll();
131: if (r != null)
132: return r;
133: for (;;) {
134: lock.wait(timeout);
135: r = reallyPoll();
136: if (r != null)
137: return r;
138: if (timeout != 0)
139: return null;
140: }
141: }
142: }
143:
144: /**
145: * Removes the next reference object in this queue, blocking until one
146: * becomes available.
147: *
148: * @return A reference object, blocking until one becomes available
149: * @throws InterruptedException If the wait is interrupted
150: */
151: public Reference remove() throws InterruptedException {
152: return remove(0);
153: }
154:
155: }
|