1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.util;
15
16 import java.util.AbstractList;
17 import java.util.NoSuchElementException;
18 import java.util.Queue;
19
20
21
22
23
24
25
26
27
28
29 public class ArrayQueue<E> extends AbstractList<E> implements Queue<E>
30 {
31 public static final int DEFAULT_CAPACITY = 64;
32 public static final int DEFAULT_GROWTH = 32;
33
34 protected final Object _lock;
35 protected final int _growCapacity;
36 protected Object[] _elements;
37 protected int _nextE;
38 protected int _nextSlot;
39 protected int _size;
40
41
42 public ArrayQueue()
43 {
44 this(DEFAULT_CAPACITY, -1);
45 }
46
47
48 public ArrayQueue(int capacity)
49 {
50 this(capacity, -1);
51 }
52
53
54 public ArrayQueue(int initCapacity, int growBy)
55 {
56 this(initCapacity, growBy, null);
57 }
58
59
60 public ArrayQueue(int initCapacity, int growBy, Object lock)
61 {
62 _lock = lock == null ? this : lock;
63 _growCapacity = growBy;
64 _elements = new Object[initCapacity];
65 }
66
67
68 public int getCapacity()
69 {
70 synchronized (_lock)
71 {
72 return _elements.length;
73 }
74 }
75
76
77 @Override
78 public boolean add(E e)
79 {
80 if (!offer(e))
81 throw new IllegalStateException("Full");
82 return true;
83 }
84
85
86 public boolean offer(E e)
87 {
88 synchronized (_lock)
89 {
90 return enqueue(e);
91 }
92 }
93
94
95 private boolean enqueue(E e)
96 {
97 if (_size == _elements.length && !grow())
98 return false;
99
100 _size++;
101 _elements[_nextSlot++] = e;
102 if (_nextSlot == _elements.length)
103 _nextSlot = 0;
104
105 return true;
106 }
107
108
109
110
111
112
113
114
115 public void addUnsafe(E e)
116 {
117 if (!enqueue(e))
118 throw new IllegalStateException("Full");
119 }
120
121
122 public E element()
123 {
124 synchronized (_lock)
125 {
126 if (isEmpty())
127 throw new NoSuchElementException();
128 return at(_nextE);
129 }
130 }
131
132 @SuppressWarnings("unchecked")
133 private E at(int index)
134 {
135 return (E)_elements[index];
136 }
137
138
139 public E peek()
140 {
141 synchronized (_lock)
142 {
143 if (isEmpty())
144 return null;
145 return at(_nextE);
146 }
147 }
148
149
150 public E poll()
151 {
152 synchronized (_lock)
153 {
154 if (_size == 0)
155 return null;
156 return dequeue();
157 }
158 }
159
160
161 private E dequeue()
162 {
163 E e = at(_nextE);
164 _elements[_nextE] = null;
165 _size--;
166 if (++_nextE == _elements.length)
167 _nextE = 0;
168 return e;
169 }
170
171
172 public E remove()
173 {
174 synchronized (_lock)
175 {
176 if (_size == 0)
177 throw new NoSuchElementException();
178 return dequeue();
179 }
180 }
181
182
183 @Override
184 public void clear()
185 {
186 synchronized (_lock)
187 {
188 _size = 0;
189 _nextE = 0;
190 _nextSlot = 0;
191 }
192 }
193
194
195 @Override
196 public boolean isEmpty()
197 {
198 synchronized (_lock)
199 {
200 return _size == 0;
201 }
202 }
203
204
205 @Override
206 public int size()
207 {
208 synchronized (_lock)
209 {
210 return _size;
211 }
212 }
213
214
215 @Override
216 public E get(int index)
217 {
218 synchronized (_lock)
219 {
220 if (index < 0 || index >= _size)
221 throw new IndexOutOfBoundsException("!(" + 0 + "<" + index + "<=" + _size + ")");
222 return getUnsafe(index);
223 }
224 }
225
226
227
228
229
230
231
232
233
234 public E getUnsafe(int index)
235 {
236 int i = (_nextE + index) % _elements.length;
237 return at(i);
238 }
239
240
241 @Override
242 public E remove(int index)
243 {
244 synchronized (_lock)
245 {
246 if (index < 0 || index >= _size)
247 throw new IndexOutOfBoundsException("!(" + 0 + "<" + index + "<=" + _size + ")");
248
249 int i = (_nextE + index) % _elements.length;
250 E old = at(i);
251
252 if (i < _nextSlot)
253 {
254
255
256 System.arraycopy(_elements, i + 1, _elements, i, _nextSlot - i);
257 _nextSlot--;
258 _size--;
259 }
260 else
261 {
262
263
264 System.arraycopy(_elements, i + 1, _elements, i, _elements.length - i - 1);
265 if (_nextSlot > 0)
266 {
267 _elements[_elements.length - 1] = _elements[0];
268 System.arraycopy(_elements, 1, _elements, 0, _nextSlot - 1);
269 _nextSlot--;
270 }
271 else
272 _nextSlot = _elements.length - 1;
273
274 _size--;
275 }
276
277 return old;
278 }
279 }
280
281
282 @Override
283 public E set(int index, E element)
284 {
285 synchronized (_lock)
286 {
287 if (index < 0 || index >= _size)
288 throw new IndexOutOfBoundsException("!(" + 0 + "<" + index + "<=" + _size + ")");
289
290 int i = _nextE + index;
291 if (i >= _elements.length)
292 i -= _elements.length;
293 E old = at(i);
294 _elements[i] = element;
295 return old;
296 }
297 }
298
299
300 @Override
301 public void add(int index, E element)
302 {
303 synchronized (_lock)
304 {
305 if (index < 0 || index > _size)
306 throw new IndexOutOfBoundsException("!(" + 0 + "<" + index + "<=" + _size + ")");
307
308 if (_size == _elements.length && !grow())
309 throw new IllegalStateException("Full");
310
311 if (index == _size)
312 {
313 add(element);
314 }
315 else
316 {
317 int i = _nextE + index;
318 if (i >= _elements.length)
319 i -= _elements.length;
320
321 _size++;
322 _nextSlot++;
323 if (_nextSlot == _elements.length)
324 _nextSlot = 0;
325
326 if (i < _nextSlot)
327 {
328
329
330
331
332 System.arraycopy(_elements, i, _elements, i + 1, _nextSlot - i);
333 _elements[i] = element;
334 }
335 else
336 {
337
338
339 if (_nextSlot > 0)
340 {
341 System.arraycopy(_elements, 0, _elements, 1, _nextSlot);
342 _elements[0] = _elements[_elements.length - 1];
343 }
344
345 System.arraycopy(_elements, i, _elements, i + 1, _elements.length - i - 1);
346 _elements[i] = element;
347 }
348 }
349 }
350 }
351
352
353 protected boolean grow()
354 {
355 synchronized (_lock)
356 {
357 if (_growCapacity <= 0)
358 return false;
359
360 Object[] elements = new Object[_elements.length + _growCapacity];
361
362 int split = _elements.length - _nextE;
363 if (split > 0)
364 System.arraycopy(_elements, _nextE, elements, 0, split);
365 if (_nextE != 0)
366 System.arraycopy(_elements, 0, elements, split, _nextSlot);
367
368 _elements = elements;
369 _nextE = 0;
370 _nextSlot = _size;
371 return true;
372 }
373 }
374 }