1
2
3
4
5
6
7 package net.sourceforge.jsh3modtool.gui.imagetable.cache;
8
9 import java.util.*;
10
11 /***
12 * Active queue that threads can listen on item addition and/or removal of items.
13 * @author erma
14 */
15 public class Queue
16 {
17 private Object additionEvent = new Object();
18
19 private Object removalEvent = new Object();
20
21 protected Vector listeners = new Vector();
22
23 protected int numberOfAvailablePlaces;
24 protected Vector queueItems;
25
26 /*** Creates a new instance of Queue */
27 public Queue( )
28 {
29 this( -1 );
30 }
31
32 /*** Creates a new instance of Queue
33 * @param numberOfPlaces Maximum capacity
34 */
35 public Queue( int numberOfPlaces )
36 {
37 super( );
38 numberOfAvailablePlaces = numberOfPlaces;
39 if ( numberOfAvailablePlaces == -1 )
40 queueItems = new Vector();
41 else
42 queueItems = new Vector( numberOfAvailablePlaces );
43 }
44
45 /***
46 * Waits until there is an object in the queue
47 * @return false if this wait() (thread) was interrupted; true otherwise
48 */
49 public boolean waitForFirstObject()
50 {
51 return waitForFirstObject(0);
52 }
53
54 /***
55 * Waits until there is an object in the queue for the specified timeout time
56 * @param timeout the maximum time to wait in milliseconds.
57 * @return false if this wait() (thread) was interrupted; true otherwise
58 */
59 public boolean waitForFirstObject( long timeout )
60 {
61 if ( size() > 0 )
62 return true;
63
64 synchronized( additionEvent )
65 {
66 try
67 {
68 additionEvent.wait( timeout );
69 return true;
70 } catch ( InterruptedException ie )
71 {
72 return false;
73 }
74 }
75 }
76
77 /***
78 * Waits until there is an available place in the queue.
79 * This method behaves exactly as if it simply performs the call waitForEmptySpace(0)
80 * @return false if this wait() (thread) was interrupted; true otherwise
81 */
82 public boolean waitForEmptySpace()
83 {
84 return waitForEmptySpace(0);
85 }
86
87 /***
88 * Waits until there is an available place in the queue for the specified timeout time
89 * @param timeout the maximum time to wait in milliseconds.
90 * @return false if this wait() (thread) was interrupted; true otherwise
91 */
92 public boolean waitForEmptySpace(long timeout)
93 {
94 if ( numberOfAvailablePlaces == -1 )
95 return true;
96
97 if ( size() < numberOfAvailablePlaces )
98 return true;
99
100 synchronized( removalEvent )
101 {
102 try
103 {
104 removalEvent.wait(timeout);
105 return true;
106 } catch ( InterruptedException ie )
107 {
108 return false;
109 }
110 }
111 }
112
113
114 /***
115 * Waits until the queue is empty for the specified timeout time
116 * This method behaves exactly as if it simply performs the call waitForEmptyQueue(0)
117 * @return false if this wait() (thread) was interrupted; true otherwise
118 */
119 public boolean waitForEmptyQueue()
120 {
121 return waitForEmptyQueue(0);
122 }
123
124 /***
125 * Waits until the queue is empty for the specified timeout time
126 * @param timeout the maximum time to wait in milliseconds.
127 * @return false if this wait() (thread) was interrupted; true otherwise
128 */
129 public boolean waitForEmptyQueue( long timeout )
130 {
131 if ( ( size() == 0 ) || ( timeout < 0 ) )
132 return true;
133
134 long startTime = System.currentTimeMillis();
135
136 synchronized( removalEvent )
137 {
138 try
139 {
140 removalEvent.wait(timeout);
141 } catch ( InterruptedException ie )
142 {
143 return false;
144 }
145 }
146
147 long stopTime = System.currentTimeMillis();
148
149
150 if ( size() == 0 )
151 return true;
152
153
154 if ( timeout == 0 )
155 return waitForEmptyQueue( 0 );
156
157
158 if ( stopTime > ( timeout + startTime ) )
159 return true;
160
161
162 return waitForEmptyQueue( timeout - ( stopTime - startTime ) );
163 }
164
165 /***
166 * Fire event that there is a new item in the queue
167 */
168 protected void fireAdditionEvent()
169 {
170 synchronized( additionEvent )
171 {
172 additionEvent.notify();
173 }
174 }
175
176 /***
177 * Fire event that there is one less item in the queue
178 */
179 protected void fireRemovalEvent()
180 {
181 synchronized( removalEvent )
182 {
183 removalEvent.notify();
184 }
185 }
186
187 /***
188 * Adds the specified item to the queue.
189 * @param item the item to add
190 * @return true if it was sucessfully added; false if there was no place.
191 */
192 public boolean add( QueueItem item )
193 {
194 return addLast( item );
195 }
196
197 /***
198 * Adds the specified item to the end of the queue.
199 * @param item the item to add
200 * @return true if it was sucessfully added; false if there was no place.
201 */
202 public boolean addLast( QueueItem item )
203 {
204 return add( item, queueItems.size() );
205 }
206
207 /***
208 * Adds the specified item to the end of the queue.
209 * @param item the item to add
210 * @return true if it was sucessfully added; false if there was no place.
211 */
212 public boolean addFirst( QueueItem item )
213 {
214 return add( item, 0 );
215 }
216
217 protected boolean add( QueueItem item, int index )
218 {
219 if ( item == null )
220 return false;
221
222 if ( ( numberOfAvailablePlaces != -1 ) && ( size() >= numberOfAvailablePlaces ) )
223 {
224 return false;
225 }
226 else
227 {
228 queueItems.add( index, item );
229 fireItemAdded( item );
230 fireAdditionEvent();
231 return true;
232 }
233 }
234
235 /***
236 * Removes all items in the queue
237 */
238 public void removeAll()
239 {
240 Enumeration items = queueItems.elements();
241 while ( items.hasMoreElements() )
242 {
243 fireItemRemoved( (QueueItem) items.nextElement() );
244 }
245 queueItems.removeAllElements();
246 fireRemovalEvent();
247 }
248
249 /***
250 * Remove the item at the specified index and return it.
251 * @param index the item index to remove
252 * @return the removed item
253 */
254 protected QueueItem remove( int index )
255 {
256 if ( ( index < queueItems.size() ) && ( index >= 0 ) )
257 {
258 QueueItem item = (QueueItem) queueItems.remove( index );
259 fireItemRemoved( item );
260 fireRemovalEvent();
261 return item;
262 }
263 else
264 {
265 return null;
266 }
267 }
268
269 /***
270 * Removes the queueitem from the queue
271 * @param item the item to remove from the queue
272 * @return the removed item; null if there wasnt such item in the queue
273 */
274 public QueueItem remove( QueueItem item )
275 {
276 if ( queueItems.size() > 0 )
277 {
278 int pos = queueItems.indexOf( item );
279
280 if ( pos != -1 )
281 {
282 return remove( pos );
283 }
284 else
285 {
286 return null;
287 }
288 }
289 else
290 {
291 return null;
292 }
293 }
294
295 /***
296 * Removes the first item and returns it.
297 * @return the removed item; null if there was no items in the queue
298 */
299 public QueueItem removeFirst()
300 {
301 return remove( 0 );
302 }
303
304 /***
305 * Removes the last item and returns it.
306 * @return the removed item; null if there was no items in the queue
307 */
308 public QueueItem removeLast()
309 {
310 return remove( size() - 1 );
311 }
312
313 /***
314 * Returns the first item in the queue
315 * @return the first item; null if the queue was empty
316 */
317 public QueueItem getFirst()
318 {
319 if ( queueItems.size() == 0 )
320 return null;
321 else
322 return (QueueItem) queueItems.firstElement();
323 }
324
325 /***
326 * Returns the last item in the queue
327 * @return the last item; null if the queue was empty
328 */
329 public QueueItem getLast()
330 {
331 if ( queueItems.size() == 0 )
332 return null;
333 else
334 return (QueueItem) queueItems.lastElement();
335 }
336
337 /*** Returns the size of the queue
338 * @return the size of the queue
339 */
340 public int size()
341 {
342 return queueItems.size();
343 }
344
345 /*** Returns if the queue is empty.
346 * @return if the queue is empty.
347 */
348 public boolean isEmpty()
349 {
350 return ( size() == 0 ? true : false );
351 }
352
353 /***
354 * Add a QueueListener to this object
355 * @param listener the listener
356 */
357 public void addListener( QueueListener listener )
358 {
359 listeners.add( listener );
360 }
361
362 /***
363 * Remove a QueueListener from this object
364 * @param listener the listener
365 */
366 public void removeListener( QueueListener listener )
367 {
368 listeners.remove( listener );
369 }
370
371 /***
372 * Notify all listeners that an item has been added
373 * @param item the item
374 */
375 protected void fireItemAdded( QueueItem item )
376 {
377 Enumeration elements = listeners.elements();
378 while ( elements.hasMoreElements() )
379 {
380 ( ( QueueListener ) elements.nextElement() ).queueItemAdded( this, item );
381 }
382 }
383
384 /***
385 * Notify all listeners that an item has been removed
386 * @param item the item
387 */
388 protected void fireItemRemoved( QueueItem item )
389 {
390 Enumeration elements = listeners.elements();
391 while ( elements.hasMoreElements() )
392 {
393 ( ( QueueListener ) elements.nextElement() ).queueItemRemoved( this, item );
394 }
395 }
396 }