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