ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ArrayBlockingQueue.java
Revision: 1.117
Committed: Tue Feb 17 18:55:39 2015 UTC (9 years, 3 months ago) by jsr166
Branch: MAIN
Changes since 1.116: +1 -1 lines
Log Message:
standardize code sample idiom: * <pre> {@code

File Contents

# User Rev Content
1 dl 1.2 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3 dl 1.38 * Expert Group and released to the public domain, as explained at
4 jsr166 1.78 * http://creativecommons.org/publicdomain/zero/1.0/
5 dl 1.2 */
6    
7 tim 1.1 package java.util.concurrent;
8 jsr166 1.110
9     import java.lang.ref.WeakReference;
10 jsr166 1.85 import java.util.AbstractQueue;
11     import java.util.Collection;
12     import java.util.Iterator;
13     import java.util.NoSuchElementException;
14 jsr166 1.110 import java.util.Spliterator;
15 dl 1.102 import java.util.Spliterators;
16 jsr166 1.110 import java.util.concurrent.locks.Condition;
17     import java.util.concurrent.locks.ReentrantLock;
18 tim 1.1
19     /**
20 dl 1.25 * A bounded {@linkplain BlockingQueue blocking queue} backed by an
21     * array. This queue orders elements FIFO (first-in-first-out). The
22     * <em>head</em> of the queue is that element that has been on the
23     * queue the longest time. The <em>tail</em> of the queue is that
24     * element that has been on the queue the shortest time. New elements
25     * are inserted at the tail of the queue, and the queue retrieval
26     * operations obtain elements at the head of the queue.
27 dholmes 1.13 *
28 dl 1.40 * <p>This is a classic &quot;bounded buffer&quot;, in which a
29     * fixed-sized array holds elements inserted by producers and
30     * extracted by consumers. Once created, the capacity cannot be
31 jsr166 1.69 * changed. Attempts to {@code put} an element into a full queue
32     * will result in the operation blocking; attempts to {@code take} an
33 dl 1.40 * element from an empty queue will similarly block.
34 dl 1.11 *
35 jsr166 1.72 * <p>This class supports an optional fairness policy for ordering
36 dl 1.42 * waiting producer and consumer threads. By default, this ordering
37     * is not guaranteed. However, a queue constructed with fairness set
38 jsr166 1.69 * to {@code true} grants threads access in FIFO order. Fairness
39 dl 1.42 * generally decreases throughput but reduces variability and avoids
40     * starvation.
41 brian 1.7 *
42 dl 1.43 * <p>This class and its iterator implement all of the
43     * <em>optional</em> methods of the {@link Collection} and {@link
44 jsr166 1.47 * Iterator} interfaces.
45 dl 1.26 *
46 dl 1.41 * <p>This class is a member of the
47 jsr166 1.54 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
48 dl 1.41 * Java Collections Framework</a>.
49     *
50 dl 1.8 * @since 1.5
51     * @author Doug Lea
52 jsr166 1.109 * @param <E> the type of elements held in this queue
53 dl 1.8 */
54 dl 1.5 public class ArrayBlockingQueue<E> extends AbstractQueue<E>
55 tim 1.1 implements BlockingQueue<E>, java.io.Serializable {
56    
57 dl 1.36 /**
58 dl 1.42 * Serialization ID. This class relies on default serialization
59     * even for the items array, which is default-serialized, even if
60     * it is empty. Otherwise it could not be declared final, which is
61 dl 1.36 * necessary here.
62     */
63     private static final long serialVersionUID = -817911632652898426L;
64    
65 jsr166 1.73 /** The queued items */
66 jsr166 1.68 final Object[] items;
67 jsr166 1.73
68     /** items index for next take, poll, peek or remove */
69 jsr166 1.58 int takeIndex;
70 jsr166 1.73
71     /** items index for next put, offer, or add */
72 jsr166 1.58 int putIndex;
73 jsr166 1.73
74     /** Number of elements in the queue */
75 jsr166 1.59 int count;
76 tim 1.12
77 dl 1.5 /*
78 dl 1.36 * Concurrency control uses the classic two-condition algorithm
79 dl 1.5 * found in any textbook.
80     */
81    
82 dl 1.11 /** Main lock guarding all access */
83 jsr166 1.58 final ReentrantLock lock;
84 jsr166 1.85
85 dholmes 1.13 /** Condition for waiting takes */
86 dl 1.37 private final Condition notEmpty;
87 jsr166 1.85
88 dl 1.35 /** Condition for waiting puts */
89 dl 1.37 private final Condition notFull;
90 dl 1.5
91 jsr166 1.89 /**
92     * Shared state for currently active iterators, or null if there
93     * are known not to be any. Allows queue operations to update
94     * iterator state.
95     */
96     transient Itrs itrs = null;
97    
98 dl 1.5 // Internal helper methods
99    
100     /**
101 jsr166 1.113 * Circularly decrements array index i.
102 jsr166 1.71 */
103     final int dec(int i) {
104     return ((i == 0) ? items.length : i) - 1;
105     }
106    
107 jsr166 1.68 /**
108     * Returns item at index i.
109     */
110 jsr166 1.96 @SuppressWarnings("unchecked")
111 jsr166 1.68 final E itemAt(int i) {
112 jsr166 1.96 return (E) items[i];
113 jsr166 1.68 }
114    
115     /**
116     * Throws NullPointerException if argument is null.
117     *
118     * @param v the element
119     */
120     private static void checkNotNull(Object v) {
121     if (v == null)
122     throw new NullPointerException();
123     }
124    
125 dl 1.5 /**
126 jsr166 1.47 * Inserts element at current put position, advances, and signals.
127 dl 1.9 * Call only when holding lock.
128 dl 1.5 */
129 jsr166 1.88 private void enqueue(E x) {
130 jsr166 1.95 // assert lock.getHoldCount() == 1;
131     // assert items[putIndex] == null;
132 dl 1.100 final Object[] items = this.items;
133 dl 1.5 items[putIndex] = x;
134 jsr166 1.116 if (++putIndex == items.length) putIndex = 0;
135 jsr166 1.89 count++;
136 dl 1.9 notEmpty.signal();
137 tim 1.1 }
138 tim 1.12
139 dl 1.5 /**
140 jsr166 1.47 * Extracts element at current take position, advances, and signals.
141 dl 1.9 * Call only when holding lock.
142 dl 1.5 */
143 jsr166 1.88 private E dequeue() {
144 jsr166 1.95 // assert lock.getHoldCount() == 1;
145     // assert items[takeIndex] != null;
146 jsr166 1.68 final Object[] items = this.items;
147 jsr166 1.97 @SuppressWarnings("unchecked")
148     E x = (E) items[takeIndex];
149 dl 1.5 items[takeIndex] = null;
150 jsr166 1.116 if (++takeIndex == items.length) takeIndex = 0;
151 jsr166 1.89 count--;
152     if (itrs != null)
153     itrs.elementDequeued();
154 dl 1.9 notFull.signal();
155 dl 1.5 return x;
156     }
157    
158     /**
159 jsr166 1.90 * Deletes item at array index removeIndex.
160 jsr166 1.89 * Utility for remove(Object) and iterator.remove.
161 dl 1.9 * Call only when holding lock.
162 dl 1.5 */
163 jsr166 1.90 void removeAt(final int removeIndex) {
164 jsr166 1.95 // assert lock.getHoldCount() == 1;
165     // assert items[removeIndex] != null;
166     // assert removeIndex >= 0 && removeIndex < items.length;
167 jsr166 1.68 final Object[] items = this.items;
168 jsr166 1.90 if (removeIndex == takeIndex) {
169 jsr166 1.89 // removing front item; just advance
170 dl 1.9 items[takeIndex] = null;
171 jsr166 1.116 if (++takeIndex == items.length) takeIndex = 0;
172 jsr166 1.90 count--;
173 jsr166 1.89 if (itrs != null)
174     itrs.elementDequeued();
175 tim 1.23 } else {
176 jsr166 1.89 // an "interior" remove
177 jsr166 1.90
178 dl 1.9 // slide over all others up through putIndex.
179 jsr166 1.115 for (int i = removeIndex, putIndex = this.putIndex;;) {
180     int pred = i;
181     if (++i == items.length) i = 0;
182     if (i == putIndex) {
183     items[pred] = null;
184     this.putIndex = pred;
185 dl 1.9 break;
186     }
187 jsr166 1.115 items[pred] = items[i];
188 dl 1.5 }
189 jsr166 1.90 count--;
190     if (itrs != null)
191     itrs.removedAt(removeIndex);
192 dl 1.5 }
193 dl 1.9 notFull.signal();
194 tim 1.1 }
195    
196     /**
197 jsr166 1.69 * Creates an {@code ArrayBlockingQueue} with the given (fixed)
198 dholmes 1.13 * capacity and default access policy.
199 jsr166 1.50 *
200 dholmes 1.13 * @param capacity the capacity of this queue
201 jsr166 1.69 * @throws IllegalArgumentException if {@code capacity < 1}
202 dl 1.5 */
203 dholmes 1.13 public ArrayBlockingQueue(int capacity) {
204 dl 1.36 this(capacity, false);
205 dl 1.5 }
206 dl 1.2
207 dl 1.5 /**
208 jsr166 1.69 * Creates an {@code ArrayBlockingQueue} with the given (fixed)
209 dholmes 1.13 * capacity and the specified access policy.
210 jsr166 1.50 *
211 dholmes 1.13 * @param capacity the capacity of this queue
212 jsr166 1.69 * @param fair if {@code true} then queue accesses for threads blocked
213 jsr166 1.50 * on insertion or removal, are processed in FIFO order;
214 jsr166 1.69 * if {@code false} the access order is unspecified.
215     * @throws IllegalArgumentException if {@code capacity < 1}
216 dl 1.11 */
217 dholmes 1.13 public ArrayBlockingQueue(int capacity, boolean fair) {
218 dl 1.36 if (capacity <= 0)
219     throw new IllegalArgumentException();
220 jsr166 1.68 this.items = new Object[capacity];
221 dl 1.36 lock = new ReentrantLock(fair);
222     notEmpty = lock.newCondition();
223     notFull = lock.newCondition();
224 dl 1.5 }
225    
226 dholmes 1.16 /**
227 jsr166 1.69 * Creates an {@code ArrayBlockingQueue} with the given (fixed)
228 dholmes 1.21 * capacity, the specified access policy and initially containing the
229 tim 1.17 * elements of the given collection,
230 dholmes 1.16 * added in traversal order of the collection's iterator.
231 jsr166 1.50 *
232 dholmes 1.16 * @param capacity the capacity of this queue
233 jsr166 1.69 * @param fair if {@code true} then queue accesses for threads blocked
234 jsr166 1.50 * on insertion or removal, are processed in FIFO order;
235 jsr166 1.69 * if {@code false} the access order is unspecified.
236 dholmes 1.16 * @param c the collection of elements to initially contain
237 jsr166 1.69 * @throws IllegalArgumentException if {@code capacity} is less than
238     * {@code c.size()}, or less than 1.
239 jsr166 1.50 * @throws NullPointerException if the specified collection or any
240     * of its elements are null
241 dholmes 1.16 */
242 tim 1.20 public ArrayBlockingQueue(int capacity, boolean fair,
243 dholmes 1.18 Collection<? extends E> c) {
244 dl 1.36 this(capacity, fair);
245 dholmes 1.16
246 jsr166 1.68 final ReentrantLock lock = this.lock;
247     lock.lock(); // Lock only for visibility, not mutual exclusion
248     try {
249     int i = 0;
250     try {
251     for (E e : c) {
252     checkNotNull(e);
253     items[i++] = e;
254     }
255     } catch (ArrayIndexOutOfBoundsException ex) {
256     throw new IllegalArgumentException();
257     }
258     count = i;
259     putIndex = (i == capacity) ? 0 : i;
260     } finally {
261     lock.unlock();
262     }
263 dholmes 1.16 }
264 dl 1.2
265 dholmes 1.13 /**
266 jsr166 1.50 * Inserts the specified element at the tail of this queue if it is
267     * possible to do so immediately without exceeding the queue's capacity,
268 jsr166 1.69 * returning {@code true} upon success and throwing an
269     * {@code IllegalStateException} if this queue is full.
270 dl 1.25 *
271 jsr166 1.50 * @param e the element to add
272 jsr166 1.69 * @return {@code true} (as specified by {@link Collection#add})
273 jsr166 1.50 * @throws IllegalStateException if this queue is full
274     * @throws NullPointerException if the specified element is null
275     */
276     public boolean add(E e) {
277 jsr166 1.56 return super.add(e);
278 jsr166 1.50 }
279    
280     /**
281     * Inserts the specified element at the tail of this queue if it is
282     * possible to do so immediately without exceeding the queue's capacity,
283 jsr166 1.69 * returning {@code true} upon success and {@code false} if this queue
284 jsr166 1.50 * is full. This method is generally preferable to method {@link #add},
285     * which can fail to insert an element only by throwing an exception.
286     *
287     * @throws NullPointerException if the specified element is null
288 dholmes 1.13 */
289 jsr166 1.49 public boolean offer(E e) {
290 jsr166 1.68 checkNotNull(e);
291 dl 1.36 final ReentrantLock lock = this.lock;
292 dl 1.5 lock.lock();
293     try {
294 jsr166 1.59 if (count == items.length)
295 dl 1.2 return false;
296 dl 1.5 else {
297 jsr166 1.88 enqueue(e);
298 dl 1.5 return true;
299     }
300 tim 1.23 } finally {
301 tim 1.12 lock.unlock();
302 dl 1.2 }
303 dl 1.5 }
304 dl 1.2
305 dholmes 1.13 /**
306 jsr166 1.50 * Inserts the specified element at the tail of this queue, waiting
307     * for space to become available if the queue is full.
308     *
309     * @throws InterruptedException {@inheritDoc}
310     * @throws NullPointerException {@inheritDoc}
311     */
312     public void put(E e) throws InterruptedException {
313 jsr166 1.68 checkNotNull(e);
314 jsr166 1.50 final ReentrantLock lock = this.lock;
315     lock.lockInterruptibly();
316     try {
317 jsr166 1.59 while (count == items.length)
318 jsr166 1.58 notFull.await();
319 jsr166 1.88 enqueue(e);
320 jsr166 1.50 } finally {
321     lock.unlock();
322     }
323     }
324    
325     /**
326     * Inserts the specified element at the tail of this queue, waiting
327     * up to the specified wait time for space to become available if
328     * the queue is full.
329     *
330     * @throws InterruptedException {@inheritDoc}
331     * @throws NullPointerException {@inheritDoc}
332 brian 1.7 */
333 jsr166 1.49 public boolean offer(E e, long timeout, TimeUnit unit)
334 dholmes 1.13 throws InterruptedException {
335 dl 1.2
336 jsr166 1.68 checkNotNull(e);
337 jsr166 1.56 long nanos = unit.toNanos(timeout);
338 dl 1.36 final ReentrantLock lock = this.lock;
339 dl 1.5 lock.lockInterruptibly();
340     try {
341 jsr166 1.59 while (count == items.length) {
342 dl 1.5 if (nanos <= 0)
343     return false;
344 jsr166 1.58 nanos = notFull.awaitNanos(nanos);
345 dl 1.5 }
346 jsr166 1.88 enqueue(e);
347 jsr166 1.58 return true;
348 tim 1.23 } finally {
349 dl 1.5 lock.unlock();
350 dl 1.2 }
351 dl 1.5 }
352 dl 1.2
353 dholmes 1.13 public E poll() {
354 dl 1.36 final ReentrantLock lock = this.lock;
355 dholmes 1.13 lock.lock();
356     try {
357 jsr166 1.88 return (count == 0) ? null : dequeue();
358 tim 1.23 } finally {
359 tim 1.15 lock.unlock();
360 dholmes 1.13 }
361     }
362    
363 jsr166 1.50 public E take() throws InterruptedException {
364     final ReentrantLock lock = this.lock;
365     lock.lockInterruptibly();
366     try {
367 jsr166 1.59 while (count == 0)
368 jsr166 1.58 notEmpty.await();
369 jsr166 1.88 return dequeue();
370 jsr166 1.50 } finally {
371     lock.unlock();
372     }
373     }
374    
375 dl 1.5 public E poll(long timeout, TimeUnit unit) throws InterruptedException {
376 jsr166 1.56 long nanos = unit.toNanos(timeout);
377 dl 1.36 final ReentrantLock lock = this.lock;
378 dl 1.5 lock.lockInterruptibly();
379     try {
380 jsr166 1.59 while (count == 0) {
381 dl 1.5 if (nanos <= 0)
382     return null;
383 jsr166 1.58 nanos = notEmpty.awaitNanos(nanos);
384 dl 1.2 }
385 jsr166 1.88 return dequeue();
386 tim 1.23 } finally {
387 dl 1.5 lock.unlock();
388     }
389     }
390 dl 1.2
391 dholmes 1.13 public E peek() {
392 dl 1.36 final ReentrantLock lock = this.lock;
393 dholmes 1.13 lock.lock();
394     try {
395 jsr166 1.99 return itemAt(takeIndex); // null when queue is empty
396 tim 1.23 } finally {
397 dholmes 1.13 lock.unlock();
398     }
399     }
400    
401     // this doc comment is overridden to remove the reference to collections
402     // greater in size than Integer.MAX_VALUE
403 tim 1.15 /**
404 dl 1.25 * Returns the number of elements in this queue.
405     *
406 jsr166 1.50 * @return the number of elements in this queue
407 dholmes 1.13 */
408     public int size() {
409 dl 1.36 final ReentrantLock lock = this.lock;
410 dholmes 1.13 lock.lock();
411     try {
412     return count;
413 tim 1.23 } finally {
414 dholmes 1.13 lock.unlock();
415     }
416     }
417    
418     // this doc comment is a modified copy of the inherited doc comment,
419     // without the reference to unlimited queues.
420 tim 1.15 /**
421 jsr166 1.48 * Returns the number of additional elements that this queue can ideally
422     * (in the absence of memory or resource constraints) accept without
423 dholmes 1.13 * blocking. This is always equal to the initial capacity of this queue
424 jsr166 1.69 * less the current {@code size} of this queue.
425 jsr166 1.48 *
426     * <p>Note that you <em>cannot</em> always tell if an attempt to insert
427 jsr166 1.69 * an element will succeed by inspecting {@code remainingCapacity}
428 jsr166 1.48 * because it may be the case that another thread is about to
429 jsr166 1.50 * insert or remove an element.
430 dholmes 1.13 */
431     public int remainingCapacity() {
432 dl 1.36 final ReentrantLock lock = this.lock;
433 dholmes 1.13 lock.lock();
434     try {
435     return items.length - count;
436 tim 1.23 } finally {
437 dholmes 1.13 lock.unlock();
438     }
439     }
440    
441 jsr166 1.50 /**
442     * Removes a single instance of the specified element from this queue,
443 jsr166 1.69 * if it is present. More formally, removes an element {@code e} such
444     * that {@code o.equals(e)}, if this queue contains one or more such
445 jsr166 1.50 * elements.
446 jsr166 1.69 * Returns {@code true} if this queue contained the specified element
447 jsr166 1.50 * (or equivalently, if this queue changed as a result of the call).
448     *
449 jsr166 1.64 * <p>Removal of interior elements in circular array based queues
450 dl 1.60 * is an intrinsically slow and disruptive operation, so should
451     * be undertaken only in exceptional circumstances, ideally
452     * only when the queue is known not to be accessible by other
453     * threads.
454     *
455 jsr166 1.50 * @param o element to be removed from this queue, if present
456 jsr166 1.69 * @return {@code true} if this queue changed as a result of the call
457 jsr166 1.50 */
458     public boolean remove(Object o) {
459     if (o == null) return false;
460     final ReentrantLock lock = this.lock;
461     lock.lock();
462     try {
463 jsr166 1.86 if (count > 0) {
464 jsr166 1.114 final Object[] items = this.items;
465 jsr166 1.86 final int putIndex = this.putIndex;
466     int i = takeIndex;
467     do {
468     if (o.equals(items[i])) {
469     removeAt(i);
470     return true;
471     }
472 jsr166 1.116 if (++i == items.length) i = 0;
473 dl 1.100 } while (i != putIndex);
474 jsr166 1.50 }
475 jsr166 1.68 return false;
476 jsr166 1.50 } finally {
477     lock.unlock();
478     }
479     }
480 dholmes 1.13
481 jsr166 1.50 /**
482 jsr166 1.69 * Returns {@code true} if this queue contains the specified element.
483     * More formally, returns {@code true} if and only if this queue contains
484     * at least one element {@code e} such that {@code o.equals(e)}.
485 jsr166 1.50 *
486     * @param o object to be checked for containment in this queue
487 jsr166 1.69 * @return {@code true} if this queue contains the specified element
488 jsr166 1.50 */
489 dholmes 1.21 public boolean contains(Object o) {
490     if (o == null) return false;
491 dl 1.36 final ReentrantLock lock = this.lock;
492 dl 1.5 lock.lock();
493     try {
494 jsr166 1.86 if (count > 0) {
495 jsr166 1.114 final Object[] items = this.items;
496 jsr166 1.86 final int putIndex = this.putIndex;
497     int i = takeIndex;
498     do {
499     if (o.equals(items[i]))
500     return true;
501 jsr166 1.116 if (++i == items.length) i = 0;
502 dl 1.100 } while (i != putIndex);
503 jsr166 1.86 }
504 dl 1.2 return false;
505 tim 1.23 } finally {
506 dl 1.5 lock.unlock();
507     }
508     }
509 brian 1.7
510 jsr166 1.50 /**
511     * Returns an array containing all of the elements in this queue, in
512     * proper sequence.
513     *
514     * <p>The returned array will be "safe" in that no references to it are
515     * maintained by this queue. (In other words, this method must allocate
516     * a new array). The caller is thus free to modify the returned array.
517 jsr166 1.51 *
518 jsr166 1.50 * <p>This method acts as bridge between array-based and collection-based
519     * APIs.
520     *
521     * @return an array containing all of the elements in this queue
522     */
523 dl 1.5 public Object[] toArray() {
524 dl 1.36 final ReentrantLock lock = this.lock;
525 dl 1.5 lock.lock();
526     try {
527 jsr166 1.68 final int count = this.count;
528 jsr166 1.114 final Object[] a = new Object[count];
529 jsr166 1.98 int n = items.length - takeIndex;
530     if (count <= n)
531     System.arraycopy(items, takeIndex, a, 0, count);
532     else {
533     System.arraycopy(items, takeIndex, a, 0, n);
534     System.arraycopy(items, 0, a, n, count - n);
535     }
536 jsr166 1.114 return a;
537 tim 1.23 } finally {
538 dl 1.5 lock.unlock();
539     }
540     }
541 brian 1.7
542 jsr166 1.50 /**
543     * Returns an array containing all of the elements in this queue, in
544     * proper sequence; the runtime type of the returned array is that of
545     * the specified array. If the queue fits in the specified array, it
546     * is returned therein. Otherwise, a new array is allocated with the
547     * runtime type of the specified array and the size of this queue.
548     *
549     * <p>If this queue fits in the specified array with room to spare
550     * (i.e., the array has more elements than this queue), the element in
551     * the array immediately following the end of the queue is set to
552 jsr166 1.69 * {@code null}.
553 jsr166 1.50 *
554     * <p>Like the {@link #toArray()} method, this method acts as bridge between
555     * array-based and collection-based APIs. Further, this method allows
556     * precise control over the runtime type of the output array, and may,
557     * under certain circumstances, be used to save allocation costs.
558     *
559 jsr166 1.69 * <p>Suppose {@code x} is a queue known to contain only strings.
560 jsr166 1.50 * The following code can be used to dump the queue into a newly
561 jsr166 1.69 * allocated array of {@code String}:
562 jsr166 1.50 *
563 jsr166 1.117 * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
564 jsr166 1.50 *
565 jsr166 1.69 * Note that {@code toArray(new Object[0])} is identical in function to
566     * {@code toArray()}.
567 jsr166 1.50 *
568     * @param a the array into which the elements of the queue are to
569     * be stored, if it is big enough; otherwise, a new array of the
570     * same runtime type is allocated for this purpose
571     * @return an array containing all of the elements in this queue
572     * @throws ArrayStoreException if the runtime type of the specified array
573     * is not a supertype of the runtime type of every element in
574     * this queue
575     * @throws NullPointerException if the specified array is null
576     */
577 jsr166 1.68 @SuppressWarnings("unchecked")
578 dl 1.5 public <T> T[] toArray(T[] a) {
579 jsr166 1.68 final Object[] items = this.items;
580 dl 1.36 final ReentrantLock lock = this.lock;
581 dl 1.5 lock.lock();
582     try {
583 jsr166 1.68 final int count = this.count;
584     final int len = a.length;
585     if (len < count)
586 dholmes 1.16 a = (T[])java.lang.reflect.Array.newInstance(
587 jsr166 1.68 a.getClass().getComponentType(), count);
588 jsr166 1.98 int n = items.length - takeIndex;
589     if (count <= n)
590     System.arraycopy(items, takeIndex, a, 0, count);
591     else {
592     System.arraycopy(items, takeIndex, a, 0, n);
593     System.arraycopy(items, 0, a, n, count - n);
594     }
595 jsr166 1.68 if (len > count)
596 dl 1.5 a[count] = null;
597 tim 1.23 } finally {
598 dl 1.5 lock.unlock();
599     }
600 dl 1.100 return a;
601 dl 1.5 }
602 dl 1.6
603     public String toString() {
604 dl 1.36 final ReentrantLock lock = this.lock;
605 dl 1.6 lock.lock();
606     try {
607 jsr166 1.68 int k = count;
608     if (k == 0)
609     return "[]";
610    
611 dl 1.100 final Object[] items = this.items;
612 jsr166 1.68 StringBuilder sb = new StringBuilder();
613     sb.append('[');
614 dl 1.100 for (int i = takeIndex; ; ) {
615 jsr166 1.68 Object e = items[i];
616     sb.append(e == this ? "(this Collection)" : e);
617     if (--k == 0)
618     return sb.append(']').toString();
619     sb.append(',').append(' ');
620 jsr166 1.116 if (++i == items.length) i = 0;
621 jsr166 1.68 }
622 tim 1.23 } finally {
623 dl 1.6 lock.unlock();
624     }
625     }
626 tim 1.12
627 dl 1.44 /**
628     * Atomically removes all of the elements from this queue.
629     * The queue will be empty after this call returns.
630     */
631 dl 1.30 public void clear() {
632 jsr166 1.68 final Object[] items = this.items;
633 dl 1.36 final ReentrantLock lock = this.lock;
634 dl 1.30 lock.lock();
635     try {
636 jsr166 1.86 int k = count;
637     if (k > 0) {
638     final int putIndex = this.putIndex;
639     int i = takeIndex;
640     do {
641     items[i] = null;
642 jsr166 1.116 if (++i == items.length) i = 0;
643 dl 1.100 } while (i != putIndex);
644 jsr166 1.86 takeIndex = putIndex;
645     count = 0;
646 jsr166 1.89 if (itrs != null)
647     itrs.queueIsEmpty();
648 jsr166 1.86 for (; k > 0 && lock.hasWaiters(notFull); k--)
649     notFull.signal();
650     }
651 dl 1.30 } finally {
652     lock.unlock();
653     }
654     }
655    
656 jsr166 1.50 /**
657     * @throws UnsupportedOperationException {@inheritDoc}
658     * @throws ClassCastException {@inheritDoc}
659     * @throws NullPointerException {@inheritDoc}
660     * @throws IllegalArgumentException {@inheritDoc}
661     */
662 dl 1.30 public int drainTo(Collection<? super E> c) {
663 jsr166 1.81 return drainTo(c, Integer.MAX_VALUE);
664 dl 1.30 }
665    
666 jsr166 1.50 /**
667     * @throws UnsupportedOperationException {@inheritDoc}
668     * @throws ClassCastException {@inheritDoc}
669     * @throws NullPointerException {@inheritDoc}
670     * @throws IllegalArgumentException {@inheritDoc}
671     */
672 dl 1.30 public int drainTo(Collection<? super E> c, int maxElements) {
673 jsr166 1.68 checkNotNull(c);
674 dl 1.30 if (c == this)
675     throw new IllegalArgumentException();
676     if (maxElements <= 0)
677     return 0;
678 jsr166 1.68 final Object[] items = this.items;
679 dl 1.36 final ReentrantLock lock = this.lock;
680 dl 1.30 lock.lock();
681     try {
682 jsr166 1.82 int n = Math.min(maxElements, count);
683     int take = takeIndex;
684     int i = 0;
685     try {
686     while (i < n) {
687 jsr166 1.97 @SuppressWarnings("unchecked")
688     E x = (E) items[take];
689 jsr166 1.84 c.add(x);
690 jsr166 1.82 items[take] = null;
691 jsr166 1.116 if (++take == items.length) take = 0;
692 jsr166 1.86 i++;
693 jsr166 1.82 }
694     return n;
695     } finally {
696     // Restore invariants even if c.add() threw
697 jsr166 1.89 if (i > 0) {
698     count -= i;
699     takeIndex = take;
700     if (itrs != null) {
701     if (count == 0)
702     itrs.queueIsEmpty();
703     else if (i > take)
704     itrs.takeIndexWrapped();
705     }
706     for (; i > 0 && lock.hasWaiters(notFull); i--)
707     notFull.signal();
708     }
709 dl 1.30 }
710     } finally {
711     lock.unlock();
712     }
713     }
714    
715 brian 1.7 /**
716 dl 1.75 * Returns an iterator over the elements in this queue in proper sequence.
717 jsr166 1.77 * The elements will be returned in order from first (head) to last (tail).
718     *
719 jsr166 1.106 * <p>The returned iterator is
720     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
721 brian 1.7 *
722 jsr166 1.50 * @return an iterator over the elements in this queue in proper sequence
723 brian 1.7 */
724 dl 1.5 public Iterator<E> iterator() {
725 jsr166 1.68 return new Itr();
726 dl 1.5 }
727 dl 1.8
728     /**
729 jsr166 1.94 * Shared data between iterators and their queue, allowing queue
730 jsr166 1.89 * modifications to update iterators when elements are removed.
731     *
732 jsr166 1.94 * This adds a lot of complexity for the sake of correctly
733     * handling some uncommon operations, but the combination of
734     * circular-arrays and supporting interior removes (i.e., those
735     * not at head) would cause iterators to sometimes lose their
736     * places and/or (re)report elements they shouldn't. To avoid
737     * this, when a queue has one or more iterators, it keeps iterator
738     * state consistent by:
739     *
740     * (1) keeping track of the number of "cycles", that is, the
741     * number of times takeIndex has wrapped around to 0.
742     * (2) notifying all iterators via the callback removedAt whenever
743     * an interior element is removed (and thus other elements may
744     * be shifted).
745     *
746     * These suffice to eliminate iterator inconsistencies, but
747     * unfortunately add the secondary responsibility of maintaining
748     * the list of iterators. We track all active iterators in a
749     * simple linked list (accessed only when the queue's lock is
750     * held) of weak references to Itr. The list is cleaned up using
751     * 3 different mechanisms:
752 jsr166 1.89 *
753     * (1) Whenever a new iterator is created, do some O(1) checking for
754     * stale list elements.
755     *
756     * (2) Whenever takeIndex wraps around to 0, check for iterators
757     * that have been unused for more than one wrap-around cycle.
758     *
759     * (3) Whenever the queue becomes empty, all iterators are notified
760     * and this entire data structure is discarded.
761     *
762 jsr166 1.94 * So in addition to the removedAt callback that is necessary for
763     * correctness, iterators have the shutdown and takeIndexWrapped
764     * callbacks that help remove stale iterators from the list.
765     *
766     * Whenever a list element is examined, it is expunged if either
767     * the GC has determined that the iterator is discarded, or if the
768     * iterator reports that it is "detached" (does not need any
769     * further state updates). Overhead is maximal when takeIndex
770     * never advances, iterators are discarded before they are
771     * exhausted, and all removals are interior removes, in which case
772     * all stale iterators are discovered by the GC. But even in this
773     * case we don't increase the amortized complexity.
774     *
775     * Care must be taken to keep list sweeping methods from
776     * reentrantly invoking another such method, causing subtle
777     * corruption bugs.
778 jsr166 1.89 */
779     class Itrs {
780    
781     /**
782     * Node in a linked list of weak iterator references.
783     */
784     private class Node extends WeakReference<Itr> {
785     Node next;
786    
787     Node(Itr iterator, Node next) {
788     super(iterator);
789     this.next = next;
790     }
791     }
792    
793     /** Incremented whenever takeIndex wraps around to 0 */
794 jsr166 1.108 int cycles;
795 jsr166 1.89
796     /** Linked list of weak iterator references */
797 jsr166 1.93 private Node head;
798 jsr166 1.89
799     /** Used to expunge stale iterators */
800 jsr166 1.108 private Node sweeper;
801 jsr166 1.89
802     private static final int SHORT_SWEEP_PROBES = 4;
803     private static final int LONG_SWEEP_PROBES = 16;
804    
805 jsr166 1.93 Itrs(Itr initial) {
806     register(initial);
807     }
808    
809 jsr166 1.89 /**
810     * Sweeps itrs, looking for and expunging stale iterators.
811     * If at least one was found, tries harder to find more.
812 jsr166 1.94 * Called only from iterating thread.
813 jsr166 1.89 *
814     * @param tryHarder whether to start in try-harder mode, because
815     * there is known to be at least one iterator to collect
816     */
817     void doSomeSweeping(boolean tryHarder) {
818 jsr166 1.95 // assert lock.getHoldCount() == 1;
819     // assert head != null;
820 jsr166 1.89 int probes = tryHarder ? LONG_SWEEP_PROBES : SHORT_SWEEP_PROBES;
821     Node o, p;
822     final Node sweeper = this.sweeper;
823 jsr166 1.93 boolean passedGo; // to limit search to one full sweep
824 jsr166 1.89
825 jsr166 1.93 if (sweeper == null) {
826     o = null;
827     p = head;
828     passedGo = true;
829     } else {
830 jsr166 1.89 o = sweeper;
831     p = o.next;
832 jsr166 1.93 passedGo = false;
833 jsr166 1.89 }
834    
835 jsr166 1.93 for (; probes > 0; probes--) {
836     if (p == null) {
837     if (passedGo)
838     break;
839     o = null;
840     p = head;
841     passedGo = true;
842     }
843 jsr166 1.89 final Itr it = p.get();
844     final Node next = p.next;
845     if (it == null || it.isDetached()) {
846     // found a discarded/exhausted iterator
847     probes = LONG_SWEEP_PROBES; // "try harder"
848     // unlink p
849     p.clear();
850     p.next = null;
851 jsr166 1.93 if (o == null) {
852 jsr166 1.89 head = next;
853 jsr166 1.93 if (next == null) {
854     // We've run out of iterators to track; retire
855     itrs = null;
856     return;
857     }
858     }
859 jsr166 1.89 else
860     o.next = next;
861     } else {
862     o = p;
863     }
864     p = next;
865     }
866    
867     this.sweeper = (p == null) ? null : o;
868     }
869    
870     /**
871     * Adds a new iterator to the linked list of tracked iterators.
872     */
873     void register(Itr itr) {
874 jsr166 1.95 // assert lock.getHoldCount() == 1;
875 jsr166 1.89 head = new Node(itr, head);
876     }
877    
878     /**
879     * Called whenever takeIndex wraps around to 0.
880     *
881     * Notifies all iterators, and expunges any that are now stale.
882     */
883     void takeIndexWrapped() {
884 jsr166 1.95 // assert lock.getHoldCount() == 1;
885 jsr166 1.89 cycles++;
886     for (Node o = null, p = head; p != null;) {
887     final Itr it = p.get();
888     final Node next = p.next;
889     if (it == null || it.takeIndexWrapped()) {
890     // unlink p
891 jsr166 1.95 // assert it == null || it.isDetached();
892 jsr166 1.89 p.clear();
893     p.next = null;
894     if (o == null)
895     head = next;
896     else
897     o.next = next;
898     } else {
899     o = p;
900     }
901     p = next;
902     }
903     if (head == null) // no more iterators to track
904     itrs = null;
905     }
906    
907     /**
908 jsr166 1.107 * Called whenever an interior remove (not at takeIndex) occurred.
909 jsr166 1.93 *
910     * Notifies all iterators, and expunges any that are now stale.
911 jsr166 1.89 */
912 jsr166 1.90 void removedAt(int removedIndex) {
913 jsr166 1.89 for (Node o = null, p = head; p != null;) {
914     final Itr it = p.get();
915     final Node next = p.next;
916 jsr166 1.90 if (it == null || it.removedAt(removedIndex)) {
917 jsr166 1.89 // unlink p
918 jsr166 1.95 // assert it == null || it.isDetached();
919 jsr166 1.89 p.clear();
920     p.next = null;
921     if (o == null)
922     head = next;
923     else
924     o.next = next;
925     } else {
926     o = p;
927     }
928     p = next;
929     }
930     if (head == null) // no more iterators to track
931     itrs = null;
932     }
933    
934     /**
935     * Called whenever the queue becomes empty.
936     *
937     * Notifies all active iterators that the queue is empty,
938     * clears all weak refs, and unlinks the itrs datastructure.
939     */
940     void queueIsEmpty() {
941 jsr166 1.95 // assert lock.getHoldCount() == 1;
942 jsr166 1.89 for (Node p = head; p != null; p = p.next) {
943     Itr it = p.get();
944     if (it != null) {
945     p.clear();
946     it.shutdown();
947     }
948     }
949     head = null;
950     itrs = null;
951     }
952    
953     /**
954 jsr166 1.90 * Called whenever an element has been dequeued (at takeIndex).
955 jsr166 1.89 */
956     void elementDequeued() {
957 jsr166 1.95 // assert lock.getHoldCount() == 1;
958 jsr166 1.89 if (count == 0)
959     queueIsEmpty();
960     else if (takeIndex == 0)
961     takeIndexWrapped();
962     }
963     }
964    
965     /**
966     * Iterator for ArrayBlockingQueue.
967     *
968     * To maintain weak consistency with respect to puts and takes, we
969     * read ahead one slot, so as to not report hasNext true but then
970     * not have an element to return.
971     *
972     * We switch into "detached" mode (allowing prompt unlinking from
973     * itrs without help from the GC) when all indices are negative, or
974     * when hasNext returns false for the first time. This allows the
975     * iterator to track concurrent updates completely accurately,
976     * except for the corner case of the user calling Iterator.remove()
977     * after hasNext() returned false. Even in this case, we ensure
978     * that we don't remove the wrong element by keeping track of the
979     * expected element to remove, in lastItem. Yes, we may fail to
980     * remove lastItem from the queue if it moved due to an interleaved
981     * interior remove while in detached mode.
982 dl 1.8 */
983 dl 1.5 private class Itr implements Iterator<E> {
984 jsr166 1.91 /** Index to look for new nextItem; NONE at end */
985 jsr166 1.89 private int cursor;
986    
987     /** Element to be returned by next call to next(); null if none */
988     private E nextItem;
989    
990 jsr166 1.91 /** Index of nextItem; NONE if none, REMOVED if removed elsewhere */
991 jsr166 1.89 private int nextIndex;
992    
993     /** Last element returned; null if none or not detached. */
994     private E lastItem;
995    
996 jsr166 1.91 /** Index of lastItem, NONE if none, REMOVED if removed elsewhere */
997 jsr166 1.89 private int lastRet;
998    
999 jsr166 1.91 /** Previous value of takeIndex, or DETACHED when detached */
1000 jsr166 1.89 private int prevTakeIndex;
1001    
1002     /** Previous value of iters.cycles */
1003     private int prevCycles;
1004 tim 1.12
1005 jsr166 1.91 /** Special index value indicating "not available" or "undefined" */
1006     private static final int NONE = -1;
1007    
1008     /**
1009     * Special index value indicating "removed elsewhere", that is,
1010     * removed by some operation other than a call to this.remove().
1011     */
1012     private static final int REMOVED = -2;
1013    
1014     /** Special value for prevTakeIndex indicating "detached mode" */
1015     private static final int DETACHED = -3;
1016    
1017 dl 1.66 Itr() {
1018 jsr166 1.95 // assert lock.getHoldCount() == 0;
1019 jsr166 1.91 lastRet = NONE;
1020 jsr166 1.68 final ReentrantLock lock = ArrayBlockingQueue.this.lock;
1021     lock.lock();
1022     try {
1023 jsr166 1.89 if (count == 0) {
1024 jsr166 1.95 // assert itrs == null;
1025 jsr166 1.91 cursor = NONE;
1026     nextIndex = NONE;
1027     prevTakeIndex = DETACHED;
1028 jsr166 1.89 } else {
1029     final int takeIndex = ArrayBlockingQueue.this.takeIndex;
1030     prevTakeIndex = takeIndex;
1031 jsr166 1.68 nextItem = itemAt(nextIndex = takeIndex);
1032 jsr166 1.89 cursor = incCursor(takeIndex);
1033     if (itrs == null) {
1034 jsr166 1.93 itrs = new Itrs(this);
1035 jsr166 1.89 } else {
1036     itrs.register(this); // in this order
1037     itrs.doSomeSweeping(false);
1038     }
1039     prevCycles = itrs.cycles;
1040 jsr166 1.95 // assert takeIndex >= 0;
1041     // assert prevTakeIndex == takeIndex;
1042     // assert nextIndex >= 0;
1043     // assert nextItem != null;
1044 jsr166 1.89 }
1045 jsr166 1.68 } finally {
1046     lock.unlock();
1047     }
1048 dl 1.5 }
1049 tim 1.12
1050 jsr166 1.89 boolean isDetached() {
1051 jsr166 1.95 // assert lock.getHoldCount() == 1;
1052 jsr166 1.89 return prevTakeIndex < 0;
1053     }
1054    
1055     private int incCursor(int index) {
1056 jsr166 1.95 // assert lock.getHoldCount() == 1;
1057 jsr166 1.116 if (++index == items.length) index = 0;
1058     if (index == putIndex) index = NONE;
1059 jsr166 1.89 return index;
1060     }
1061    
1062     /**
1063     * Returns true if index is invalidated by the given number of
1064     * dequeues, starting from prevTakeIndex.
1065     */
1066     private boolean invalidated(int index, int prevTakeIndex,
1067     long dequeues, int length) {
1068     if (index < 0)
1069     return false;
1070     int distance = index - prevTakeIndex;
1071     if (distance < 0)
1072     distance += length;
1073     return dequeues > distance;
1074     }
1075    
1076     /**
1077     * Adjusts indices to incorporate all dequeues since the last
1078     * operation on this iterator. Call only from iterating thread.
1079     */
1080     private void incorporateDequeues() {
1081 jsr166 1.95 // assert lock.getHoldCount() == 1;
1082     // assert itrs != null;
1083     // assert !isDetached();
1084     // assert count > 0;
1085 jsr166 1.89
1086     final int cycles = itrs.cycles;
1087     final int takeIndex = ArrayBlockingQueue.this.takeIndex;
1088     final int prevCycles = this.prevCycles;
1089     final int prevTakeIndex = this.prevTakeIndex;
1090    
1091     if (cycles != prevCycles || takeIndex != prevTakeIndex) {
1092     final int len = items.length;
1093     // how far takeIndex has advanced since the previous
1094     // operation of this iterator
1095     long dequeues = (cycles - prevCycles) * len
1096     + (takeIndex - prevTakeIndex);
1097    
1098     // Check indices for invalidation
1099     if (invalidated(lastRet, prevTakeIndex, dequeues, len))
1100 jsr166 1.91 lastRet = REMOVED;
1101 jsr166 1.89 if (invalidated(nextIndex, prevTakeIndex, dequeues, len))
1102 jsr166 1.91 nextIndex = REMOVED;
1103 jsr166 1.89 if (invalidated(cursor, prevTakeIndex, dequeues, len))
1104     cursor = takeIndex;
1105    
1106     if (cursor < 0 && nextIndex < 0 && lastRet < 0)
1107     detach();
1108     else {
1109     this.prevCycles = cycles;
1110     this.prevTakeIndex = takeIndex;
1111     }
1112     }
1113     }
1114    
1115     /**
1116     * Called when itrs should stop tracking this iterator, either
1117     * because there are no more indices to update (cursor < 0 &&
1118     * nextIndex < 0 && lastRet < 0) or as a special exception, when
1119     * lastRet >= 0, because hasNext() is about to return false for the
1120     * first time. Call only from iterating thread.
1121     */
1122     private void detach() {
1123     // Switch to detached mode
1124 jsr166 1.95 // assert lock.getHoldCount() == 1;
1125     // assert cursor == NONE;
1126     // assert nextIndex < 0;
1127     // assert lastRet < 0 || nextItem == null;
1128     // assert lastRet < 0 ^ lastItem != null;
1129 jsr166 1.89 if (prevTakeIndex >= 0) {
1130 jsr166 1.95 // assert itrs != null;
1131 jsr166 1.91 prevTakeIndex = DETACHED;
1132 jsr166 1.89 // try to unlink from itrs (but not too hard)
1133     itrs.doSomeSweeping(true);
1134     }
1135     }
1136    
1137     /**
1138     * For performance reasons, we would like not to acquire a lock in
1139     * hasNext in the common case. To allow for this, we only access
1140     * fields (i.e. nextItem) that are not modified by update operations
1141     * triggered by queue modifications.
1142     */
1143 dl 1.5 public boolean hasNext() {
1144 jsr166 1.95 // assert lock.getHoldCount() == 0;
1145 jsr166 1.89 if (nextItem != null)
1146     return true;
1147     noNext();
1148     return false;
1149     }
1150    
1151     private void noNext() {
1152     final ReentrantLock lock = ArrayBlockingQueue.this.lock;
1153     lock.lock();
1154     try {
1155 jsr166 1.95 // assert cursor == NONE;
1156     // assert nextIndex == NONE;
1157 jsr166 1.89 if (!isDetached()) {
1158 jsr166 1.95 // assert lastRet >= 0;
1159 jsr166 1.89 incorporateDequeues(); // might update lastRet
1160     if (lastRet >= 0) {
1161     lastItem = itemAt(lastRet);
1162 jsr166 1.95 // assert lastItem != null;
1163 jsr166 1.89 detach();
1164     }
1165     }
1166 jsr166 1.95 // assert isDetached();
1167     // assert lastRet < 0 ^ lastItem != null;
1168 jsr166 1.89 } finally {
1169     lock.unlock();
1170     }
1171 dl 1.5 }
1172 tim 1.12
1173 dl 1.5 public E next() {
1174 jsr166 1.95 // assert lock.getHoldCount() == 0;
1175 jsr166 1.89 final E x = nextItem;
1176     if (x == null)
1177     throw new NoSuchElementException();
1178 dl 1.66 final ReentrantLock lock = ArrayBlockingQueue.this.lock;
1179     lock.lock();
1180     try {
1181 jsr166 1.92 if (!isDetached())
1182 jsr166 1.89 incorporateDequeues();
1183 jsr166 1.95 // assert nextIndex != NONE;
1184     // assert lastItem == null;
1185 dl 1.66 lastRet = nextIndex;
1186 jsr166 1.89 final int cursor = this.cursor;
1187     if (cursor >= 0) {
1188     nextItem = itemAt(nextIndex = cursor);
1189 jsr166 1.95 // assert nextItem != null;
1190 jsr166 1.89 this.cursor = incCursor(cursor);
1191     } else {
1192 jsr166 1.91 nextIndex = NONE;
1193 jsr166 1.89 nextItem = null;
1194     }
1195 dl 1.66 } finally {
1196     lock.unlock();
1197 dl 1.2 }
1198 jsr166 1.89 return x;
1199 dl 1.5 }
1200 tim 1.12
1201 dl 1.5 public void remove() {
1202 jsr166 1.95 // assert lock.getHoldCount() == 0;
1203 dl 1.36 final ReentrantLock lock = ArrayBlockingQueue.this.lock;
1204 dl 1.5 lock.lock();
1205     try {
1206 jsr166 1.92 if (!isDetached())
1207     incorporateDequeues(); // might update lastRet or detach
1208     final int lastRet = this.lastRet;
1209     this.lastRet = NONE;
1210 jsr166 1.89 if (lastRet >= 0) {
1211 jsr166 1.92 if (!isDetached())
1212     removeAt(lastRet);
1213     else {
1214     final E lastItem = this.lastItem;
1215 jsr166 1.95 // assert lastItem != null;
1216 jsr166 1.92 this.lastItem = null;
1217 jsr166 1.89 if (itemAt(lastRet) == lastItem)
1218     removeAt(lastRet);
1219     }
1220 jsr166 1.91 } else if (lastRet == NONE)
1221 dl 1.66 throw new IllegalStateException();
1222 jsr166 1.91 // else lastRet == REMOVED and the last returned element was
1223 jsr166 1.89 // previously asynchronously removed via an operation other
1224     // than this.remove(), so nothing to do.
1225    
1226     if (cursor < 0 && nextIndex < 0)
1227     detach();
1228     } finally {
1229     lock.unlock();
1230 jsr166 1.95 // assert lastRet == NONE;
1231     // assert lastItem == null;
1232 jsr166 1.89 }
1233     }
1234    
1235     /**
1236     * Called to notify the iterator that the queue is empty, or that it
1237     * has fallen hopelessly behind, so that it should abandon any
1238     * further iteration, except possibly to return one more element
1239     * from next(), as promised by returning true from hasNext().
1240     */
1241     void shutdown() {
1242 jsr166 1.95 // assert lock.getHoldCount() == 1;
1243 jsr166 1.91 cursor = NONE;
1244 jsr166 1.89 if (nextIndex >= 0)
1245 jsr166 1.91 nextIndex = REMOVED;
1246 jsr166 1.89 if (lastRet >= 0) {
1247 jsr166 1.91 lastRet = REMOVED;
1248 jsr166 1.61 lastItem = null;
1249 jsr166 1.89 }
1250 jsr166 1.91 prevTakeIndex = DETACHED;
1251 jsr166 1.89 // Don't set nextItem to null because we must continue to be
1252     // able to return it on next().
1253     //
1254     // Caller will unlink from itrs when convenient.
1255     }
1256    
1257     private int distance(int index, int prevTakeIndex, int length) {
1258     int distance = index - prevTakeIndex;
1259     if (distance < 0)
1260     distance += length;
1261     return distance;
1262     }
1263    
1264     /**
1265 jsr166 1.107 * Called whenever an interior remove (not at takeIndex) occurred.
1266 jsr166 1.89 *
1267 jsr166 1.90 * @return true if this iterator should be unlinked from itrs
1268 jsr166 1.89 */
1269 jsr166 1.90 boolean removedAt(int removedIndex) {
1270 jsr166 1.95 // assert lock.getHoldCount() == 1;
1271 jsr166 1.89 if (isDetached())
1272     return true;
1273    
1274     final int takeIndex = ArrayBlockingQueue.this.takeIndex;
1275     final int prevTakeIndex = this.prevTakeIndex;
1276     final int len = items.length;
1277 jsr166 1.112 // distance from prevTakeIndex to removedIndex
1278 jsr166 1.89 final int removedDistance =
1279 jsr166 1.112 len * (itrs.cycles - this.prevCycles
1280     + ((removedIndex < takeIndex) ? 1 : 0))
1281     + (removedIndex - prevTakeIndex);
1282     // assert itrs.cycles - this.prevCycles >= 0;
1283     // assert itrs.cycles - this.prevCycles <= 1;
1284     // assert removedDistance > 0;
1285     // assert removedIndex != takeIndex;
1286 jsr166 1.89 int cursor = this.cursor;
1287     if (cursor >= 0) {
1288     int x = distance(cursor, prevTakeIndex, len);
1289     if (x == removedDistance) {
1290 jsr166 1.90 if (cursor == putIndex)
1291 jsr166 1.91 this.cursor = cursor = NONE;
1292 jsr166 1.89 }
1293     else if (x > removedDistance) {
1294 jsr166 1.95 // assert cursor != prevTakeIndex;
1295 jsr166 1.89 this.cursor = cursor = dec(cursor);
1296 jsr166 1.71 }
1297 dl 1.5 }
1298 jsr166 1.89 int lastRet = this.lastRet;
1299     if (lastRet >= 0) {
1300     int x = distance(lastRet, prevTakeIndex, len);
1301     if (x == removedDistance)
1302 jsr166 1.91 this.lastRet = lastRet = REMOVED;
1303 jsr166 1.89 else if (x > removedDistance)
1304     this.lastRet = lastRet = dec(lastRet);
1305     }
1306     int nextIndex = this.nextIndex;
1307     if (nextIndex >= 0) {
1308     int x = distance(nextIndex, prevTakeIndex, len);
1309     if (x == removedDistance)
1310 jsr166 1.91 this.nextIndex = nextIndex = REMOVED;
1311 jsr166 1.89 else if (x > removedDistance)
1312     this.nextIndex = nextIndex = dec(nextIndex);
1313     }
1314 jsr166 1.112 if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
1315 jsr166 1.91 this.prevTakeIndex = DETACHED;
1316 jsr166 1.89 return true;
1317     }
1318     return false;
1319     }
1320    
1321     /**
1322     * Called whenever takeIndex wraps around to zero.
1323     *
1324 jsr166 1.90 * @return true if this iterator should be unlinked from itrs
1325 jsr166 1.89 */
1326     boolean takeIndexWrapped() {
1327 jsr166 1.95 // assert lock.getHoldCount() == 1;
1328 jsr166 1.89 if (isDetached())
1329     return true;
1330     if (itrs.cycles - prevCycles > 1) {
1331     // All the elements that existed at the time of the last
1332     // operation are gone, so abandon further iteration.
1333     shutdown();
1334     return true;
1335     }
1336     return false;
1337 dl 1.5 }
1338 jsr166 1.89
1339     // /** Uncomment for debugging. */
1340     // public String toString() {
1341     // return ("cursor=" + cursor + " " +
1342     // "nextIndex=" + nextIndex + " " +
1343     // "lastRet=" + lastRet + " " +
1344     // "nextItem=" + nextItem + " " +
1345     // "lastItem=" + lastItem + " " +
1346     // "prevCycles=" + prevCycles + " " +
1347     // "prevTakeIndex=" + prevTakeIndex + " " +
1348     // "size()=" + size() + " " +
1349     // "remainingCapacity()=" + remainingCapacity());
1350     // }
1351 tim 1.1 }
1352 dl 1.100
1353 jsr166 1.105 /**
1354     * Returns a {@link Spliterator} over the elements in this queue.
1355     *
1356 jsr166 1.106 * <p>The returned spliterator is
1357     * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
1358     *
1359 jsr166 1.105 * <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
1360     * {@link Spliterator#ORDERED}, and {@link Spliterator#NONNULL}.
1361     *
1362     * @implNote
1363     * The {@code Spliterator} implements {@code trySplit} to permit limited
1364     * parallelism.
1365     *
1366     * @return a {@code Spliterator} over the elements in this queue
1367     * @since 1.8
1368     */
1369 dl 1.103 public Spliterator<E> spliterator() {
1370 dl 1.102 return Spliterators.spliterator
1371 dl 1.100 (this, Spliterator.ORDERED | Spliterator.NONNULL |
1372     Spliterator.CONCURRENT);
1373     }
1374    
1375 tim 1.1 }