1   package org.mortbay.util;
2   
3   import java.util.AbstractList;
4   import java.util.Collection;
5   import java.util.Iterator;
6   import java.util.List;
7   import java.util.NoSuchElementException;
8   import java.util.Queue;
9   
10  /* ------------------------------------------------------------ */
11  /** Queue backed by circular array.
12   * 
13   * This partial Queue implementation (also with {@link #pop()} for stack operation)
14   * is backed by a growable circular array.
15   * 
16   * @author gregw
17   *
18   * @param <E>
19   */
20  public class ArrayQueue<E> extends AbstractList<E> implements Queue<E>
21  {
22      private Object[] _elements;
23      private int _nextE;
24      private int _nextSlot;
25      private int _size;
26      private int _growCapacity;
27      
28      public ArrayQueue()
29      {
30          _elements=new Object[64];
31          _growCapacity=32;
32      }
33      
34      public ArrayQueue(int capacity)
35      {
36          _elements=new Object[capacity];
37          _growCapacity=-1;
38      }
39      
40      public ArrayQueue(int initCapacity,int growBy)
41      {
42          _elements=new Object[initCapacity];
43          _growCapacity=growBy;
44      }
45      
46      
47      public synchronized boolean add(E e)
48      {
49          _size++;
50          _elements[_nextSlot++]=e;
51          if (_nextSlot==_elements.length)
52              _nextSlot=0;
53          if (_nextSlot==_nextE)
54          {
55              if (_growCapacity<=0)
56                  throw new IllegalStateException("Full");
57             
58              Object[] elements=new Object[_elements.length+_growCapacity];
59                  
60              int split=_elements.length-_nextE;
61              if (split>0)
62                  System.arraycopy(_elements,_nextE,elements,0,split);
63              if (_nextE!=0)
64                  System.arraycopy(_elements,0,elements,split,_nextSlot);
65              
66              _elements=elements;
67              _nextE=0;
68              _nextSlot=_size;
69          }
70          
71          return true;
72      }
73  
74      public synchronized E element()
75      {
76          if (_nextSlot==_nextE)
77              throw new NoSuchElementException();
78          return (E)_elements[_nextE];
79      }
80  
81      public synchronized boolean offer(E e)
82      {
83          _size++;
84          _elements[_nextSlot++]=e;
85          if (_nextSlot==_elements.length)
86              _nextSlot=0;
87          if (_nextSlot==_nextE)
88          {
89              if (_growCapacity<=0)
90                  return false;
91              
92              Object[] elements=new Object[_elements.length+_growCapacity];
93                  
94              int split=_elements.length-_nextE;
95              if (split>0)
96                  System.arraycopy(_elements,_nextE,elements,0,split);
97              if (_nextE!=0)
98                  System.arraycopy(_elements,0,elements,split,_nextSlot);
99              
100             _elements=elements;
101             _nextE=0;
102             _nextSlot=_size;
103         }
104         
105         return true;
106     }
107 
108     public synchronized E peek()
109     {
110         if (_nextSlot==_nextE)
111             return null;
112         return (E)_elements[_nextE];
113     }
114 
115     public synchronized E poll()
116     {
117         if (_size==0)
118             return null;
119         E e = (E)_elements[_nextE];
120         _elements[_nextE]=null;
121         _size--;
122         if (++_nextE==_elements.length)
123             _nextE=0;
124         return e;
125     }
126     
127     public synchronized E remove()
128     {
129         if (_nextSlot==_nextE)
130             throw new NoSuchElementException();
131         E e = (E)_elements[_nextE++];
132         if (_nextE==_elements.length)
133             _nextE=0;
134         return e;
135     }
136 
137     public synchronized void clear()
138     {
139         _size=0;
140         _nextE=0;
141         _nextSlot=0;
142     }
143 
144     /* ------------------------------------------------------------ */
145     public boolean isEmpty()
146     {
147         return _size==0;
148     }
149 
150     /* ------------------------------------------------------------ */
151     public int size()
152     {
153         return _size;
154     }
155 
156     /* ------------------------------------------------------------ */
157     public synchronized E get(int index)
158     {
159         if (index>=_size)
160             throw new IndexOutOfBoundsException(index+">="+_size);
161         int i = _nextE+index;
162         if (i>=_elements.length)
163             i-=_elements.length;
164         return (E)_elements[i];
165     }
166 
167 }