ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ArrayBlockingQueue.java
Revision: 1.115
Committed: Sun Feb 15 17:04:49 2015 UTC (9 years, 3 months ago) by jsr166
Branch: MAIN
Changes since 1.114: +7 -11 lines
Log Message:
improve removeAt bytecode

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