1 /**
2  * The utillib library.
3  * More information is available at http://www.jinchess.com/.
4  * Copyright (C) 2002 Alexander Maryanovsky.
5  * All rights reserved.
6  *
7  * The utillib library is free software; you can redistribute
8  * it and/or modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * The utillib library is distributed in the hope that it will
13  * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with utillib library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 
22 package free.util;
23 
24 import java.util.Enumeration;
25 import java.util.Vector;
26 
27 /**
28  * <P>A blocking queue, one that always "contains" elements.
29  * If it is in fact empty, the pop() and peek() method will block until an
30  * item is pushed.
31  * <P><B>NOTE:</B> This class is thread safe.
32  *
33  * @author Alexander Maryanovsky.
34  */
35 
36 public class BlockingQueue implements Cloneable{
37 
38 
39   /**
40    * The underlying Vector this BlockingQueue is using.
41    */
42 
43   private final Vector queue;
44 
45 
46   /**
47    * The lock we use to synchronize pushing.
48    */
49 
50   private final Object pushLock = new String("BlockingQueue pushLock");
51 
52 
53   /**
54    * The lock we use to synchronize popping.
55    */
56 
57   private final Object popLock = new String("BlockingQueue popLock");
58 
59 
60 
61 
62   /**
63    * Creates a new, empty BlockingQueue.
64    */
65 
BlockingQueue()66   public BlockingQueue(){
67     queue = new Vector();
68   }
69 
70 
71 
72 
73 
74   /**
75    * Pushes an element into the queue.
76    */
77 
push(Object object)78   public void push(Object object){
79     synchronized(pushLock){
80       queue.addElement(object);
81       synchronized(this){
82         notify();
83       }
84     }
85   }
86 
87 
88 
89   /**
90    * Pops an element from the queue. If the queue is empty, this method blocks
91    * until another thread pushes an element into the queue.
92    *
93    * @throws InterruptedException if the invoking thread was interrupted
94    * while waiting for an element to be pushed into the queue.
95    */
96 
pop()97   public Object pop() throws InterruptedException{
98     return pop(0);
99   }
100 
101 
102 
103   /**
104    * Pops an element from the queue. Unlike the pop() method, this method does not block
105    * for longer than the given amount of milliseconds. When the given amount of milliseconds
106    * have passed, this method will throw an InterruptedException.
107    */
108 
pop(long timeout)109   public Object pop(long timeout) throws InterruptedException{
110     synchronized(popLock){
111       synchronized(this){
112         if (queue.isEmpty()){
113           wait(timeout);
114           if (queue.isEmpty())
115             throw new InterruptedException("Timed out");
116         }
117       }
118       Object val = queue.firstElement();
119       queue.removeElementAt(0);
120       return val;
121     }
122   }
123 
124 
125 
126   /**
127    * Returns the element on top of the queue without popping it. If the queue
128    * is empty, this method blocks until another thread pushes an element into
129    * the queue.
130    *
131    * @throws InterruptedException if the invoking thread was interrupted while
132    * waiting for an element to be pushed into the queue.
133    */
134 
peek()135   public Object peek() throws InterruptedException{
136     return peek(0);
137   }
138 
139 
140 
141 
142   /**
143    * Returns the element on top of the queue without popping it.
144    * Unlike the peek() method, this method does not block
145    * for longer than the given amount of milliseconds. When the given amount of milliseconds
146    * have passed, this method will throw an InterruptedException.
147    */
148 
peek(long timeout)149   public Object peek(long timeout) throws InterruptedException{
150     synchronized(popLock){
151       synchronized(this){
152         if (queue.isEmpty()){
153           wait(timeout);
154           if (queue.isEmpty())
155             throw new InterruptedException("Timed out");
156         }
157       }
158       return queue.firstElement();
159     }
160   }
161 
162 
163 
164 
165 
166 
167   /**
168    * Returns true if the queue is empty (this returns the actual state of the
169    * queue, meaning it may return true even though ideologically, a BlockingQueue
170    * is never empty).
171    */
172 
isEmpty()173   public boolean isEmpty(){
174     return queue.isEmpty();
175   }
176 
177 
178 
179   /**
180    * Returns true if the given element is in the queue.
181    */
182 
contains(Object element)183   public boolean contains(Object element){
184     return queue.contains(element);
185   }
186 
187 
188 
189   /**
190    * Returns the size of the queue.
191    */
192 
size()193   public int size(){
194     return queue.size();
195   }
196 
197 
198 
199   /**
200    * Returns an Enumeration of the elements in this queue. The order of the
201    * elements is the same as if they were popped from the queue one by one (the
202    * first element is the first element that would have been popped). <br>
203    * <B>IMPORTANT:</B> Modifying the queue breaks the returned Enumeration.
204    */
205 
getElements()206   public Enumeration getElements(){
207     return queue.elements();
208   }
209 
210 
211 
212   /**
213    * Removes all elements from this queue.
214    */
215 
removeAllElements()216   public void removeAllElements(){
217     queue.removeAllElements();
218   }
219 
220 
221 
222   /**
223    * Removes all elements from this queue.
224    */
225 
clear()226   public void clear(){
227     queue.removeAllElements();
228   }
229 
230 
231 
232   /**
233    * Returns a shallow copy of this BlockingQueue.
234    */
235 
clone()236   public synchronized Object clone(){
237     BlockingQueue copy = new BlockingQueue();
238     Enumeration elems = getElements();
239     while (elems.hasMoreElements()){
240       Object item = elems.nextElement();
241       copy.push(item);
242     }
243     return copy;
244   }
245 
246 
247 
248 }
249