001/*
002 * %W% %E%
003 *
004 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
005 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
006 */
007
008package sun.misc;
009
010import java.util.Enumeration;
011import java.util.NoSuchElementException;
012
013/**
014 * Queue: implements a simple queue mechanism.  Allows for enumeration of the 
015 * elements.
016 *
017 * @version %I%, %G%
018 * @author Herb Jellinek
019 */
020
021public class Queue {
022
023    int length = 0;
024
025    QueueElement head = null;
026    QueueElement tail = null;
027
028    public Queue() {
029    }
030
031    /**
032     * Enqueue an object.
033     */
034    public synchronized void enqueue(Object obj) {
035        
036        QueueElement newElt = new QueueElement(obj);
037
038        if (head == null) {
039            head = newElt;
040            tail = newElt;
041            length = 1;
042        } else {
043            newElt.next = head;
044            head.prev = newElt;
045            head = newElt;
046            length++;
047        }
048        notify();
049    }
050
051    /**
052     * Dequeue the oldest object on the queue.  Will wait indefinitely.
053     *
054     * @return    the oldest object on the queue.
055     * @exception java.lang.InterruptedException if any thread has
056     *              interrupted this thread.
057     */
058    public Object dequeue() throws InterruptedException {
059        return dequeue(0L);
060    }
061
062    /**
063     * Dequeue the oldest object on the queue.
064     * @param timeOut the number of milliseconds to wait for something 
065     * to arrive.
066     *
067     * @return    the oldest object on the queue.
068     * @exception java.lang.InterruptedException if any thread has
069     *              interrupted this thread.
070     */
071    public synchronized Object dequeue(long timeOut)
072        throws InterruptedException {
073        
074        while (tail == null) {
075            wait(timeOut);
076        }
077        QueueElement elt = tail;
078        tail = elt.prev;
079        if (tail == null) {
080            head = null;
081        } else {
082            tail.next = null;
083        }
084        length--;
085        return elt.obj;
086    }
087
088    /**
089     * Is the queue empty?
090     * @return true if the queue is empty.
091     */
092    public synchronized boolean isEmpty() {
093        return (tail == null);
094    }
095
096    /**
097     * Returns an enumeration of the elements in Last-In, First-Out
098     * order. Use the Enumeration methods on the returned object to
099     * fetch the elements sequentially.
100     */
101    public final synchronized Enumeration elements() {
102        return new LIFOQueueEnumerator(this);
103    }
104
105    /**
106     * Returns an enumeration of the elements in First-In, First-Out
107     * order. Use the Enumeration methods on the returned object to
108     * fetch the elements sequentially.
109     */
110    public final synchronized Enumeration reverseElements() {
111        return new FIFOQueueEnumerator(this);
112    }
113
114    public synchronized void dump(String msg) {
115        System.err.println(">> "+msg);
116        System.err.println("["+length+" elt(s); head = "+
117                           (head == null ? "null" : (head.obj)+"")+
118                           " tail = "+(tail == null ? "null" : (tail.obj)+""));
119        QueueElement cursor = head;
120        QueueElement last = null;
121        while (cursor != null) {
122            System.err.println("  "+cursor);
123            last = cursor;
124            cursor = cursor.next;
125        }
126        if (last != tail) {
127            System.err.println("  tail != last: "+tail+", "+last);
128        }
129        System.err.println("]");
130    }
131}
132
133final class FIFOQueueEnumerator implements Enumeration {
134    Queue queue;
135    QueueElement cursor;
136
137    FIFOQueueEnumerator(Queue q) {
138        queue = q;
139        cursor = q.tail;
140    }
141
142    public boolean hasMoreElements() {
143        return (cursor != null);
144    }
145
146    public Object nextElement() {
147        synchronized (queue) {
148            if (cursor != null) {
149                QueueElement result = cursor;
150                cursor = cursor.prev;
151                return result.obj;
152            }
153        }
154        throw new NoSuchElementException("FIFOQueueEnumerator");
155    }
156}
157
158final class LIFOQueueEnumerator implements Enumeration {
159    Queue queue;
160    QueueElement cursor;
161
162    LIFOQueueEnumerator(Queue q) {
163        queue = q;
164        cursor = q.head;
165    }
166
167    public boolean hasMoreElements() {
168        return (cursor != null);
169    }
170
171    public Object nextElement() {
172        synchronized (queue) {
173            if (cursor != null) {
174                QueueElement result = cursor;
175                cursor = cursor.next;
176                return result.obj;
177            }
178        }
179        throw new NoSuchElementException("LIFOQueueEnumerator");
180    }
181}
182
183class QueueElement {
184    QueueElement next = null;
185    QueueElement prev = null;
186
187    Object obj = null;
188
189    QueueElement(Object obj) {
190        this.obj = obj;
191    }
192
193    public String toString() {
194        return "QueueElement[obj="+obj+(prev == null ? " null" : " prev")+
195            (next == null ? " null" : " next")+"]";
196    }
197}
198