View Javadoc
1   /*
2    * Queue.java
3    *
4    * Created on den 16 september 2002, 11:31
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         // either I timoutted or there was an event, anyhow check if I should continue waiting
150         if ( size() == 0 )
151             return true;
152         
153         // There are still items in the queue, and if timeout was 0 (wait indefintely)
154         if ( timeout == 0 )
155             return waitForEmptyQueue( 0 );
156         
157         // Check if the timeout has expired
158         if (  stopTime > ( timeout + startTime ) )
159             return true;
160 
161         // Just wait some more time
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 }