ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ArrayBlockingQueue.java
Revision: 1.81
Committed: Mon Jun 20 08:33:02 2011 UTC (12 years, 11 months ago) by jsr166
Branch: MAIN
Changes since 1.80: +4 -30 lines
Log Message:
drainTo(c) should delegate to drainTo(c, maxElements)

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 dl 1.11 import java.util.concurrent.locks.*;
9 tim 1.1 import java.util.*;
10    
11     /**
12 dl 1.25 * A bounded {@linkplain BlockingQueue blocking queue} backed by an
13     * array. This queue orders elements FIFO (first-in-first-out). The
14     * <em>head</em> of the queue is that element that has been on the
15     * queue the longest time. The <em>tail</em> of the queue is that
16     * element that has been on the queue the shortest time. New elements
17     * are inserted at the tail of the queue, and the queue retrieval
18     * operations obtain elements at the head of the queue.
19 dholmes 1.13 *
20 dl 1.40 * <p>This is a classic &quot;bounded buffer&quot;, in which a
21     * fixed-sized array holds elements inserted by producers and
22     * extracted by consumers. Once created, the capacity cannot be
23 jsr166 1.69 * changed. Attempts to {@code put} an element into a full queue
24     * will result in the operation blocking; attempts to {@code take} an
25 dl 1.40 * element from an empty queue will similarly block.
26 dl 1.11 *
27 jsr166 1.72 * <p>This class supports an optional fairness policy for ordering
28 dl 1.42 * waiting producer and consumer threads. By default, this ordering
29     * is not guaranteed. However, a queue constructed with fairness set
30 jsr166 1.69 * to {@code true} grants threads access in FIFO order. Fairness
31 dl 1.42 * generally decreases throughput but reduces variability and avoids
32     * starvation.
33 brian 1.7 *
34 dl 1.43 * <p>This class and its iterator implement all of the
35     * <em>optional</em> methods of the {@link Collection} and {@link
36 jsr166 1.47 * Iterator} interfaces.
37 dl 1.26 *
38 dl 1.41 * <p>This class is a member of the
39 jsr166 1.54 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
40 dl 1.41 * Java Collections Framework</a>.
41     *
42 dl 1.8 * @since 1.5
43     * @author Doug Lea
44 dl 1.33 * @param <E> the type of elements held in this collection
45 dl 1.8 */
46 dl 1.5 public class ArrayBlockingQueue<E> extends AbstractQueue<E>
47 tim 1.1 implements BlockingQueue<E>, java.io.Serializable {
48    
49 dl 1.36 /**
50 dl 1.42 * Serialization ID. This class relies on default serialization
51     * even for the items array, which is default-serialized, even if
52     * it is empty. Otherwise it could not be declared final, which is
53 dl 1.36 * necessary here.
54     */
55     private static final long serialVersionUID = -817911632652898426L;
56    
57 jsr166 1.73 /** The queued items */
58 jsr166 1.68 final Object[] items;
59 jsr166 1.73
60     /** items index for next take, poll, peek or remove */
61 jsr166 1.58 int takeIndex;
62 jsr166 1.73
63     /** items index for next put, offer, or add */
64 jsr166 1.58 int putIndex;
65 jsr166 1.73
66     /** Number of elements in the queue */
67 jsr166 1.59 int count;
68 tim 1.12
69 dl 1.5 /*
70 dl 1.36 * Concurrency control uses the classic two-condition algorithm
71 dl 1.5 * found in any textbook.
72     */
73    
74 dl 1.11 /** Main lock guarding all access */
75 jsr166 1.58 final ReentrantLock lock;
76 dholmes 1.13 /** Condition for waiting takes */
77 dl 1.37 private final Condition notEmpty;
78 dl 1.35 /** Condition for waiting puts */
79 dl 1.37 private final Condition notFull;
80 dl 1.5
81     // Internal helper methods
82    
83     /**
84     * Circularly increment i.
85     */
86 dl 1.40 final int inc(int i) {
87 jsr166 1.58 return (++i == items.length) ? 0 : i;
88 dl 1.5 }
89    
90 jsr166 1.71 /**
91     * Circularly decrement i.
92     */
93     final int dec(int i) {
94     return ((i == 0) ? items.length : i) - 1;
95     }
96    
97 jsr166 1.68 @SuppressWarnings("unchecked")
98     static <E> E cast(Object item) {
99     return (E) item;
100     }
101    
102     /**
103     * Returns item at index i.
104     */
105     final E itemAt(int i) {
106 jsr166 1.79 return ArrayBlockingQueue.<E>cast(items[i]);
107 jsr166 1.68 }
108    
109     /**
110     * Throws NullPointerException if argument is null.
111     *
112     * @param v the element
113     */
114     private static void checkNotNull(Object v) {
115     if (v == null)
116     throw new NullPointerException();
117     }
118    
119 dl 1.5 /**
120 jsr166 1.47 * Inserts element at current put position, advances, and signals.
121 dl 1.9 * Call only when holding lock.
122 dl 1.5 */
123     private void insert(E x) {
124     items[putIndex] = x;
125     putIndex = inc(putIndex);
126     ++count;
127 dl 1.9 notEmpty.signal();
128 tim 1.1 }
129 tim 1.12
130 dl 1.5 /**
131 jsr166 1.47 * Extracts element at current take position, advances, and signals.
132 dl 1.9 * Call only when holding lock.
133 dl 1.5 */
134 dholmes 1.13 private E extract() {
135 jsr166 1.68 final Object[] items = this.items;
136 jsr166 1.79 E x = ArrayBlockingQueue.<E>cast(items[takeIndex]);
137 dl 1.5 items[takeIndex] = null;
138     takeIndex = inc(takeIndex);
139     --count;
140 dl 1.9 notFull.signal();
141 dl 1.5 return x;
142     }
143    
144     /**
145 jsr166 1.68 * Deletes item at position i.
146     * Utility for remove and iterator.remove.
147 dl 1.9 * Call only when holding lock.
148 dl 1.5 */
149     void removeAt(int i) {
150 jsr166 1.68 final Object[] items = this.items;
151 dl 1.9 // if removing front item, just advance
152     if (i == takeIndex) {
153     items[takeIndex] = null;
154     takeIndex = inc(takeIndex);
155 tim 1.23 } else {
156 dl 1.9 // slide over all others up through putIndex.
157     for (;;) {
158     int nexti = inc(i);
159     if (nexti != putIndex) {
160     items[i] = items[nexti];
161     i = nexti;
162 tim 1.23 } else {
163 dl 1.9 items[i] = null;
164     putIndex = i;
165     break;
166     }
167 dl 1.5 }
168     }
169 dl 1.9 --count;
170     notFull.signal();
171 tim 1.1 }
172    
173     /**
174 jsr166 1.69 * Creates an {@code ArrayBlockingQueue} with the given (fixed)
175 dholmes 1.13 * capacity and default access policy.
176 jsr166 1.50 *
177 dholmes 1.13 * @param capacity the capacity of this queue
178 jsr166 1.69 * @throws IllegalArgumentException if {@code capacity < 1}
179 dl 1.5 */
180 dholmes 1.13 public ArrayBlockingQueue(int capacity) {
181 dl 1.36 this(capacity, false);
182 dl 1.5 }
183 dl 1.2
184 dl 1.5 /**
185 jsr166 1.69 * Creates an {@code ArrayBlockingQueue} with the given (fixed)
186 dholmes 1.13 * capacity and the specified access policy.
187 jsr166 1.50 *
188 dholmes 1.13 * @param capacity the capacity of this queue
189 jsr166 1.69 * @param fair if {@code true} then queue accesses for threads blocked
190 jsr166 1.50 * on insertion or removal, are processed in FIFO order;
191 jsr166 1.69 * if {@code false} the access order is unspecified.
192     * @throws IllegalArgumentException if {@code capacity < 1}
193 dl 1.11 */
194 dholmes 1.13 public ArrayBlockingQueue(int capacity, boolean fair) {
195 dl 1.36 if (capacity <= 0)
196     throw new IllegalArgumentException();
197 jsr166 1.68 this.items = new Object[capacity];
198 dl 1.36 lock = new ReentrantLock(fair);
199     notEmpty = lock.newCondition();
200     notFull = lock.newCondition();
201 dl 1.5 }
202    
203 dholmes 1.16 /**
204 jsr166 1.69 * Creates an {@code ArrayBlockingQueue} with the given (fixed)
205 dholmes 1.21 * capacity, the specified access policy and initially containing the
206 tim 1.17 * elements of the given collection,
207 dholmes 1.16 * added in traversal order of the collection's iterator.
208 jsr166 1.50 *
209 dholmes 1.16 * @param capacity the capacity of this queue
210 jsr166 1.69 * @param fair if {@code true} then queue accesses for threads blocked
211 jsr166 1.50 * on insertion or removal, are processed in FIFO order;
212 jsr166 1.69 * if {@code false} the access order is unspecified.
213 dholmes 1.16 * @param c the collection of elements to initially contain
214 jsr166 1.69 * @throws IllegalArgumentException if {@code capacity} is less than
215     * {@code c.size()}, or less than 1.
216 jsr166 1.50 * @throws NullPointerException if the specified collection or any
217     * of its elements are null
218 dholmes 1.16 */
219 tim 1.20 public ArrayBlockingQueue(int capacity, boolean fair,
220 dholmes 1.18 Collection<? extends E> c) {
221 dl 1.36 this(capacity, fair);
222 dholmes 1.16
223 jsr166 1.68 final ReentrantLock lock = this.lock;
224     lock.lock(); // Lock only for visibility, not mutual exclusion
225     try {
226     int i = 0;
227     try {
228     for (E e : c) {
229     checkNotNull(e);
230     items[i++] = e;
231     }
232     } catch (ArrayIndexOutOfBoundsException ex) {
233     throw new IllegalArgumentException();
234     }
235     count = i;
236     putIndex = (i == capacity) ? 0 : i;
237     } finally {
238     lock.unlock();
239     }
240 dholmes 1.16 }
241 dl 1.2
242 dholmes 1.13 /**
243 jsr166 1.50 * Inserts the specified element at the tail of this queue if it is
244     * possible to do so immediately without exceeding the queue's capacity,
245 jsr166 1.69 * returning {@code true} upon success and throwing an
246     * {@code IllegalStateException} if this queue is full.
247 dl 1.25 *
248 jsr166 1.50 * @param e the element to add
249 jsr166 1.69 * @return {@code true} (as specified by {@link Collection#add})
250 jsr166 1.50 * @throws IllegalStateException if this queue is full
251     * @throws NullPointerException if the specified element is null
252     */
253     public boolean add(E e) {
254 jsr166 1.56 return super.add(e);
255 jsr166 1.50 }
256    
257     /**
258     * Inserts the specified element at the tail of this queue if it is
259     * possible to do so immediately without exceeding the queue's capacity,
260 jsr166 1.69 * returning {@code true} upon success and {@code false} if this queue
261 jsr166 1.50 * is full. This method is generally preferable to method {@link #add},
262     * which can fail to insert an element only by throwing an exception.
263     *
264     * @throws NullPointerException if the specified element is null
265 dholmes 1.13 */
266 jsr166 1.49 public boolean offer(E e) {
267 jsr166 1.68 checkNotNull(e);
268 dl 1.36 final ReentrantLock lock = this.lock;
269 dl 1.5 lock.lock();
270     try {
271 jsr166 1.59 if (count == items.length)
272 dl 1.2 return false;
273 dl 1.5 else {
274 jsr166 1.49 insert(e);
275 dl 1.5 return true;
276     }
277 tim 1.23 } finally {
278 tim 1.12 lock.unlock();
279 dl 1.2 }
280 dl 1.5 }
281 dl 1.2
282 dholmes 1.13 /**
283 jsr166 1.50 * Inserts the specified element at the tail of this queue, waiting
284     * for space to become available if the queue is full.
285     *
286     * @throws InterruptedException {@inheritDoc}
287     * @throws NullPointerException {@inheritDoc}
288     */
289     public void put(E e) throws InterruptedException {
290 jsr166 1.68 checkNotNull(e);
291 jsr166 1.50 final ReentrantLock lock = this.lock;
292     lock.lockInterruptibly();
293     try {
294 jsr166 1.59 while (count == items.length)
295 jsr166 1.58 notFull.await();
296 jsr166 1.50 insert(e);
297     } finally {
298     lock.unlock();
299     }
300     }
301    
302     /**
303     * Inserts the specified element at the tail of this queue, waiting
304     * up to the specified wait time for space to become available if
305     * the queue is full.
306     *
307     * @throws InterruptedException {@inheritDoc}
308     * @throws NullPointerException {@inheritDoc}
309 brian 1.7 */
310 jsr166 1.49 public boolean offer(E e, long timeout, TimeUnit unit)
311 dholmes 1.13 throws InterruptedException {
312 dl 1.2
313 jsr166 1.68 checkNotNull(e);
314 jsr166 1.56 long nanos = unit.toNanos(timeout);
315 dl 1.36 final ReentrantLock lock = this.lock;
316 dl 1.5 lock.lockInterruptibly();
317     try {
318 jsr166 1.59 while (count == items.length) {
319 dl 1.5 if (nanos <= 0)
320     return false;
321 jsr166 1.58 nanos = notFull.awaitNanos(nanos);
322 dl 1.5 }
323 jsr166 1.58 insert(e);
324     return true;
325 tim 1.23 } finally {
326 dl 1.5 lock.unlock();
327 dl 1.2 }
328 dl 1.5 }
329 dl 1.2
330 dholmes 1.13 public E poll() {
331 dl 1.36 final ReentrantLock lock = this.lock;
332 dholmes 1.13 lock.lock();
333     try {
334 jsr166 1.59 return (count == 0) ? null : extract();
335 tim 1.23 } finally {
336 tim 1.15 lock.unlock();
337 dholmes 1.13 }
338     }
339    
340 jsr166 1.50 public E take() throws InterruptedException {
341     final ReentrantLock lock = this.lock;
342     lock.lockInterruptibly();
343     try {
344 jsr166 1.59 while (count == 0)
345 jsr166 1.58 notEmpty.await();
346     return extract();
347 jsr166 1.50 } finally {
348     lock.unlock();
349     }
350     }
351    
352 dl 1.5 public E poll(long timeout, TimeUnit unit) throws InterruptedException {
353 jsr166 1.56 long nanos = unit.toNanos(timeout);
354 dl 1.36 final ReentrantLock lock = this.lock;
355 dl 1.5 lock.lockInterruptibly();
356     try {
357 jsr166 1.59 while (count == 0) {
358 dl 1.5 if (nanos <= 0)
359     return null;
360 jsr166 1.58 nanos = notEmpty.awaitNanos(nanos);
361 dl 1.2 }
362 jsr166 1.58 return extract();
363 tim 1.23 } finally {
364 dl 1.5 lock.unlock();
365     }
366     }
367 dl 1.2
368 dholmes 1.13 public E peek() {
369 dl 1.36 final ReentrantLock lock = this.lock;
370 dholmes 1.13 lock.lock();
371     try {
372 jsr166 1.68 return (count == 0) ? null : itemAt(takeIndex);
373 tim 1.23 } finally {
374 dholmes 1.13 lock.unlock();
375     }
376     }
377    
378     // this doc comment is overridden to remove the reference to collections
379     // greater in size than Integer.MAX_VALUE
380 tim 1.15 /**
381 dl 1.25 * Returns the number of elements in this queue.
382     *
383 jsr166 1.50 * @return the number of elements in this queue
384 dholmes 1.13 */
385     public int size() {
386 dl 1.36 final ReentrantLock lock = this.lock;
387 dholmes 1.13 lock.lock();
388     try {
389     return count;
390 tim 1.23 } finally {
391 dholmes 1.13 lock.unlock();
392     }
393     }
394    
395     // this doc comment is a modified copy of the inherited doc comment,
396     // without the reference to unlimited queues.
397 tim 1.15 /**
398 jsr166 1.48 * Returns the number of additional elements that this queue can ideally
399     * (in the absence of memory or resource constraints) accept without
400 dholmes 1.13 * blocking. This is always equal to the initial capacity of this queue
401 jsr166 1.69 * less the current {@code size} of this queue.
402 jsr166 1.48 *
403     * <p>Note that you <em>cannot</em> always tell if an attempt to insert
404 jsr166 1.69 * an element will succeed by inspecting {@code remainingCapacity}
405 jsr166 1.48 * because it may be the case that another thread is about to
406 jsr166 1.50 * insert or remove an element.
407 dholmes 1.13 */
408     public int remainingCapacity() {
409 dl 1.36 final ReentrantLock lock = this.lock;
410 dholmes 1.13 lock.lock();
411     try {
412     return items.length - count;
413 tim 1.23 } finally {
414 dholmes 1.13 lock.unlock();
415     }
416     }
417    
418 jsr166 1.50 /**
419     * Removes a single instance of the specified element from this queue,
420 jsr166 1.69 * if it is present. More formally, removes an element {@code e} such
421     * that {@code o.equals(e)}, if this queue contains one or more such
422 jsr166 1.50 * elements.
423 jsr166 1.69 * Returns {@code true} if this queue contained the specified element
424 jsr166 1.50 * (or equivalently, if this queue changed as a result of the call).
425     *
426 jsr166 1.64 * <p>Removal of interior elements in circular array based queues
427 dl 1.60 * is an intrinsically slow and disruptive operation, so should
428     * be undertaken only in exceptional circumstances, ideally
429     * only when the queue is known not to be accessible by other
430     * threads.
431     *
432 jsr166 1.50 * @param o element to be removed from this queue, if present
433 jsr166 1.69 * @return {@code true} if this queue changed as a result of the call
434 jsr166 1.50 */
435     public boolean remove(Object o) {
436     if (o == null) return false;
437 jsr166 1.68 final Object[] items = this.items;
438 jsr166 1.50 final ReentrantLock lock = this.lock;
439     lock.lock();
440     try {
441 jsr166 1.68 for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) {
442 jsr166 1.50 if (o.equals(items[i])) {
443     removeAt(i);
444     return true;
445     }
446     }
447 jsr166 1.68 return false;
448 jsr166 1.50 } finally {
449     lock.unlock();
450     }
451     }
452 dholmes 1.13
453 jsr166 1.50 /**
454 jsr166 1.69 * Returns {@code true} if this queue contains the specified element.
455     * More formally, returns {@code true} if and only if this queue contains
456     * at least one element {@code e} such that {@code o.equals(e)}.
457 jsr166 1.50 *
458     * @param o object to be checked for containment in this queue
459 jsr166 1.69 * @return {@code true} if this queue contains the specified element
460 jsr166 1.50 */
461 dholmes 1.21 public boolean contains(Object o) {
462     if (o == null) return false;
463 jsr166 1.68 final Object[] items = this.items;
464 dl 1.36 final ReentrantLock lock = this.lock;
465 dl 1.5 lock.lock();
466     try {
467 jsr166 1.68 for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
468 dholmes 1.21 if (o.equals(items[i]))
469 dl 1.2 return true;
470     return false;
471 tim 1.23 } finally {
472 dl 1.5 lock.unlock();
473     }
474     }
475 brian 1.7
476 jsr166 1.50 /**
477     * Returns an array containing all of the elements in this queue, in
478     * proper sequence.
479     *
480     * <p>The returned array will be "safe" in that no references to it are
481     * maintained by this queue. (In other words, this method must allocate
482     * a new array). The caller is thus free to modify the returned array.
483 jsr166 1.51 *
484 jsr166 1.50 * <p>This method acts as bridge between array-based and collection-based
485     * APIs.
486     *
487     * @return an array containing all of the elements in this queue
488     */
489 dl 1.5 public Object[] toArray() {
490 jsr166 1.68 final Object[] items = this.items;
491 dl 1.36 final ReentrantLock lock = this.lock;
492 dl 1.5 lock.lock();
493     try {
494 jsr166 1.68 final int count = this.count;
495 dl 1.34 Object[] a = new Object[count];
496 jsr166 1.68 for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
497     a[k] = items[i];
498 dl 1.2 return a;
499 tim 1.23 } finally {
500 dl 1.5 lock.unlock();
501     }
502     }
503 brian 1.7
504 jsr166 1.50 /**
505     * Returns an array containing all of the elements in this queue, in
506     * proper sequence; the runtime type of the returned array is that of
507     * the specified array. If the queue fits in the specified array, it
508     * is returned therein. Otherwise, a new array is allocated with the
509     * runtime type of the specified array and the size of this queue.
510     *
511     * <p>If this queue fits in the specified array with room to spare
512     * (i.e., the array has more elements than this queue), the element in
513     * the array immediately following the end of the queue is set to
514 jsr166 1.69 * {@code null}.
515 jsr166 1.50 *
516     * <p>Like the {@link #toArray()} method, this method acts as bridge between
517     * array-based and collection-based APIs. Further, this method allows
518     * precise control over the runtime type of the output array, and may,
519     * under certain circumstances, be used to save allocation costs.
520     *
521 jsr166 1.69 * <p>Suppose {@code x} is a queue known to contain only strings.
522 jsr166 1.50 * The following code can be used to dump the queue into a newly
523 jsr166 1.69 * allocated array of {@code String}:
524 jsr166 1.50 *
525 jsr166 1.80 * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
526 jsr166 1.50 *
527 jsr166 1.69 * Note that {@code toArray(new Object[0])} is identical in function to
528     * {@code toArray()}.
529 jsr166 1.50 *
530     * @param a the array into which the elements of the queue are to
531     * be stored, if it is big enough; otherwise, a new array of the
532     * same runtime type is allocated for this purpose
533     * @return an array containing all of the elements in this queue
534     * @throws ArrayStoreException if the runtime type of the specified array
535     * is not a supertype of the runtime type of every element in
536     * this queue
537     * @throws NullPointerException if the specified array is null
538     */
539 jsr166 1.68 @SuppressWarnings("unchecked")
540 dl 1.5 public <T> T[] toArray(T[] a) {
541 jsr166 1.68 final Object[] items = this.items;
542 dl 1.36 final ReentrantLock lock = this.lock;
543 dl 1.5 lock.lock();
544     try {
545 jsr166 1.68 final int count = this.count;
546     final int len = a.length;
547     if (len < count)
548 dholmes 1.16 a = (T[])java.lang.reflect.Array.newInstance(
549 jsr166 1.68 a.getClass().getComponentType(), count);
550     for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
551     a[k] = (T) items[i];
552     if (len > count)
553 dl 1.5 a[count] = null;
554 dl 1.2 return a;
555 tim 1.23 } finally {
556 dl 1.5 lock.unlock();
557     }
558     }
559 dl 1.6
560     public String toString() {
561 dl 1.36 final ReentrantLock lock = this.lock;
562 dl 1.6 lock.lock();
563     try {
564 jsr166 1.68 int k = count;
565     if (k == 0)
566     return "[]";
567    
568     StringBuilder sb = new StringBuilder();
569     sb.append('[');
570     for (int i = takeIndex; ; i = inc(i)) {
571     Object e = items[i];
572     sb.append(e == this ? "(this Collection)" : e);
573     if (--k == 0)
574     return sb.append(']').toString();
575     sb.append(',').append(' ');
576     }
577 tim 1.23 } finally {
578 dl 1.6 lock.unlock();
579     }
580     }
581 tim 1.12
582 dl 1.44 /**
583     * Atomically removes all of the elements from this queue.
584     * The queue will be empty after this call returns.
585     */
586 dl 1.30 public void clear() {
587 jsr166 1.68 final Object[] items = this.items;
588 dl 1.36 final ReentrantLock lock = this.lock;
589 dl 1.30 lock.lock();
590     try {
591 jsr166 1.68 for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
592 dl 1.30 items[i] = null;
593     count = 0;
594     putIndex = 0;
595     takeIndex = 0;
596     notFull.signalAll();
597     } finally {
598     lock.unlock();
599     }
600     }
601    
602 jsr166 1.50 /**
603     * @throws UnsupportedOperationException {@inheritDoc}
604     * @throws ClassCastException {@inheritDoc}
605     * @throws NullPointerException {@inheritDoc}
606     * @throws IllegalArgumentException {@inheritDoc}
607     */
608 dl 1.30 public int drainTo(Collection<? super E> c) {
609 jsr166 1.81 return drainTo(c, Integer.MAX_VALUE);
610 dl 1.30 }
611    
612 jsr166 1.50 /**
613     * @throws UnsupportedOperationException {@inheritDoc}
614     * @throws ClassCastException {@inheritDoc}
615     * @throws NullPointerException {@inheritDoc}
616     * @throws IllegalArgumentException {@inheritDoc}
617     */
618 dl 1.30 public int drainTo(Collection<? super E> c, int maxElements) {
619 jsr166 1.68 checkNotNull(c);
620 dl 1.30 if (c == this)
621     throw new IllegalArgumentException();
622     if (maxElements <= 0)
623     return 0;
624 jsr166 1.68 final Object[] items = this.items;
625 dl 1.36 final ReentrantLock lock = this.lock;
626 dl 1.30 lock.lock();
627     try {
628     int i = takeIndex;
629 jsr166 1.81 int max = Math.min(maxElements, count);
630     int n;
631     for (n = 0; n < max; n++) {
632 jsr166 1.79 c.add(ArrayBlockingQueue.<E>cast(items[i]));
633 dl 1.30 items[i] = null;
634     i = inc(i);
635     }
636     if (n > 0) {
637     count -= n;
638     takeIndex = i;
639     notFull.signalAll();
640     }
641     return n;
642     } finally {
643     lock.unlock();
644     }
645     }
646    
647 brian 1.7 /**
648 dl 1.75 * Returns an iterator over the elements in this queue in proper sequence.
649 jsr166 1.77 * The elements will be returned in order from first (head) to last (tail).
650     *
651     * <p>The returned {@code Iterator} is a "weakly consistent" iterator that
652     * will never throw {@link java.util.ConcurrentModificationException
653     * ConcurrentModificationException},
654 dl 1.75 * and guarantees to traverse elements as they existed upon
655     * construction of the iterator, and may (but is not guaranteed to)
656     * reflect any modifications subsequent to construction.
657 brian 1.7 *
658 jsr166 1.50 * @return an iterator over the elements in this queue in proper sequence
659 brian 1.7 */
660 dl 1.5 public Iterator<E> iterator() {
661 jsr166 1.68 return new Itr();
662 dl 1.5 }
663 dl 1.8
664     /**
665 dl 1.60 * Iterator for ArrayBlockingQueue. To maintain weak consistency
666     * with respect to puts and takes, we (1) read ahead one slot, so
667     * as to not report hasNext true but then not have an element to
668 dl 1.75 * return -- however we later recheck this slot to use the most
669     * current value; (2) ensure that each array slot is traversed at
670     * most once (by tracking "remaining" elements); (3) skip over
671     * null slots, which can occur if takes race ahead of iterators.
672 dl 1.60 * However, for circular array-based queues, we cannot rely on any
673     * well established definition of what it means to be weakly
674     * consistent with respect to interior removes since these may
675     * require slot overwrites in the process of sliding elements to
676     * cover gaps. So we settle for resiliency, operating on
677 jsr166 1.62 * established apparent nexts, which may miss some elements that
678 dl 1.66 * have moved between calls to next.
679 dl 1.8 */
680 dl 1.5 private class Itr implements Iterator<E> {
681 dl 1.60 private int remaining; // Number of elements yet to be returned
682     private int nextIndex; // Index of element to be returned by next
683     private E nextItem; // Element to be returned by next call to next
684     private E lastItem; // Element returned by last call to next
685     private int lastRet; // Index of last element returned, or -1 if none
686 tim 1.12
687 dl 1.66 Itr() {
688 jsr166 1.68 final ReentrantLock lock = ArrayBlockingQueue.this.lock;
689     lock.lock();
690     try {
691     lastRet = -1;
692     if ((remaining = count) > 0)
693     nextItem = itemAt(nextIndex = takeIndex);
694     } finally {
695     lock.unlock();
696     }
697 dl 1.5 }
698 tim 1.12
699 dl 1.5 public boolean hasNext() {
700 dl 1.60 return remaining > 0;
701 dl 1.5 }
702 tim 1.12
703 dl 1.5 public E next() {
704 dl 1.66 final ReentrantLock lock = ArrayBlockingQueue.this.lock;
705     lock.lock();
706     try {
707 dl 1.67 if (remaining <= 0)
708     throw new NoSuchElementException();
709 dl 1.66 lastRet = nextIndex;
710 dl 1.75 E x = itemAt(nextIndex); // check for fresher value
711     if (x == null) {
712     x = nextItem; // we are forced to report old value
713     lastItem = null; // but ensure remove fails
714 dl 1.66 }
715 dl 1.75 else
716     lastItem = x;
717     while (--remaining > 0 && // skip over nulls
718     (nextItem = itemAt(nextIndex = inc(nextIndex))) == null)
719     ;
720 dl 1.66 return x;
721     } finally {
722     lock.unlock();
723 dl 1.2 }
724 dl 1.5 }
725 tim 1.12
726 dl 1.5 public void remove() {
727 dl 1.36 final ReentrantLock lock = ArrayBlockingQueue.this.lock;
728 dl 1.5 lock.lock();
729     try {
730 dl 1.66 int i = lastRet;
731     if (i == -1)
732     throw new IllegalStateException();
733 dl 1.2 lastRet = -1;
734 jsr166 1.61 E x = lastItem;
735     lastItem = null;
736 jsr166 1.71 // only remove if item still at index
737 dl 1.75 if (x != null && x == items[i]) {
738 jsr166 1.71 boolean removingHead = (i == takeIndex);
739     removeAt(i);
740     if (!removingHead)
741     nextIndex = dec(nextIndex);
742     }
743 tim 1.23 } finally {
744 dl 1.5 lock.unlock();
745     }
746     }
747 tim 1.1 }
748 dl 1.60
749 tim 1.1 }