ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ArrayBlockingQueue.java
Revision: 1.78
Committed: Tue Mar 15 19:47:03 2011 UTC (13 years, 2 months ago) by jsr166
Branch: MAIN
CVS Tags: release-1_7_0
Changes since 1.77: +1 -1 lines
Log Message:
Update Creative Commons license URL in legal notices

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.70 return this.<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.70 E x = this.<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     * <pre>
526     * String[] y = x.toArray(new String[0]);</pre>
527     *
528 jsr166 1.69 * Note that {@code toArray(new Object[0])} is identical in function to
529     * {@code toArray()}.
530 jsr166 1.50 *
531     * @param a the array into which the elements of the queue are to
532     * be stored, if it is big enough; otherwise, a new array of the
533     * same runtime type is allocated for this purpose
534     * @return an array containing all of the elements in this queue
535     * @throws ArrayStoreException if the runtime type of the specified array
536     * is not a supertype of the runtime type of every element in
537     * this queue
538     * @throws NullPointerException if the specified array is null
539     */
540 jsr166 1.68 @SuppressWarnings("unchecked")
541 dl 1.5 public <T> T[] toArray(T[] a) {
542 jsr166 1.68 final Object[] items = this.items;
543 dl 1.36 final ReentrantLock lock = this.lock;
544 dl 1.5 lock.lock();
545     try {
546 jsr166 1.68 final int count = this.count;
547     final int len = a.length;
548     if (len < count)
549 dholmes 1.16 a = (T[])java.lang.reflect.Array.newInstance(
550 jsr166 1.68 a.getClass().getComponentType(), count);
551     for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
552     a[k] = (T) items[i];
553     if (len > count)
554 dl 1.5 a[count] = null;
555 dl 1.2 return a;
556 tim 1.23 } finally {
557 dl 1.5 lock.unlock();
558     }
559     }
560 dl 1.6
561     public String toString() {
562 dl 1.36 final ReentrantLock lock = this.lock;
563 dl 1.6 lock.lock();
564     try {
565 jsr166 1.68 int k = count;
566     if (k == 0)
567     return "[]";
568    
569     StringBuilder sb = new StringBuilder();
570     sb.append('[');
571     for (int i = takeIndex; ; i = inc(i)) {
572     Object e = items[i];
573     sb.append(e == this ? "(this Collection)" : e);
574     if (--k == 0)
575     return sb.append(']').toString();
576     sb.append(',').append(' ');
577     }
578 tim 1.23 } finally {
579 dl 1.6 lock.unlock();
580     }
581     }
582 tim 1.12
583 dl 1.44 /**
584     * Atomically removes all of the elements from this queue.
585     * The queue will be empty after this call returns.
586     */
587 dl 1.30 public void clear() {
588 jsr166 1.68 final Object[] items = this.items;
589 dl 1.36 final ReentrantLock lock = this.lock;
590 dl 1.30 lock.lock();
591     try {
592 jsr166 1.68 for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
593 dl 1.30 items[i] = null;
594     count = 0;
595     putIndex = 0;
596     takeIndex = 0;
597     notFull.signalAll();
598     } finally {
599     lock.unlock();
600     }
601     }
602    
603 jsr166 1.50 /**
604     * @throws UnsupportedOperationException {@inheritDoc}
605     * @throws ClassCastException {@inheritDoc}
606     * @throws NullPointerException {@inheritDoc}
607     * @throws IllegalArgumentException {@inheritDoc}
608     */
609 dl 1.30 public int drainTo(Collection<? super E> c) {
610 jsr166 1.68 checkNotNull(c);
611 dl 1.30 if (c == this)
612     throw new IllegalArgumentException();
613 jsr166 1.68 final Object[] items = this.items;
614 dl 1.36 final ReentrantLock lock = this.lock;
615 dl 1.30 lock.lock();
616     try {
617     int i = takeIndex;
618     int n = 0;
619     int max = count;
620     while (n < max) {
621 jsr166 1.70 c.add(this.<E>cast(items[i]));
622 dl 1.30 items[i] = null;
623     i = inc(i);
624     ++n;
625     }
626     if (n > 0) {
627     count = 0;
628     putIndex = 0;
629     takeIndex = 0;
630     notFull.signalAll();
631     }
632     return n;
633     } finally {
634     lock.unlock();
635     }
636     }
637    
638 jsr166 1.50 /**
639     * @throws UnsupportedOperationException {@inheritDoc}
640     * @throws ClassCastException {@inheritDoc}
641     * @throws NullPointerException {@inheritDoc}
642     * @throws IllegalArgumentException {@inheritDoc}
643     */
644 dl 1.30 public int drainTo(Collection<? super E> c, int maxElements) {
645 jsr166 1.68 checkNotNull(c);
646 dl 1.30 if (c == this)
647     throw new IllegalArgumentException();
648     if (maxElements <= 0)
649     return 0;
650 jsr166 1.68 final Object[] items = this.items;
651 dl 1.36 final ReentrantLock lock = this.lock;
652 dl 1.30 lock.lock();
653     try {
654     int i = takeIndex;
655     int n = 0;
656 jsr166 1.58 int max = (maxElements < count) ? maxElements : count;
657 dl 1.30 while (n < max) {
658 jsr166 1.70 c.add(this.<E>cast(items[i]));
659 dl 1.30 items[i] = null;
660     i = inc(i);
661     ++n;
662     }
663     if (n > 0) {
664     count -= n;
665     takeIndex = i;
666     notFull.signalAll();
667     }
668     return n;
669     } finally {
670     lock.unlock();
671     }
672     }
673    
674 brian 1.7 /**
675 dl 1.75 * Returns an iterator over the elements in this queue in proper sequence.
676 jsr166 1.77 * The elements will be returned in order from first (head) to last (tail).
677     *
678     * <p>The returned {@code Iterator} is a "weakly consistent" iterator that
679     * will never throw {@link java.util.ConcurrentModificationException
680     * ConcurrentModificationException},
681 dl 1.75 * and guarantees to traverse elements as they existed upon
682     * construction of the iterator, and may (but is not guaranteed to)
683     * reflect any modifications subsequent to construction.
684 brian 1.7 *
685 jsr166 1.50 * @return an iterator over the elements in this queue in proper sequence
686 brian 1.7 */
687 dl 1.5 public Iterator<E> iterator() {
688 jsr166 1.68 return new Itr();
689 dl 1.5 }
690 dl 1.8
691     /**
692 dl 1.60 * Iterator for ArrayBlockingQueue. To maintain weak consistency
693     * with respect to puts and takes, we (1) read ahead one slot, so
694     * as to not report hasNext true but then not have an element to
695 dl 1.75 * return -- however we later recheck this slot to use the most
696     * current value; (2) ensure that each array slot is traversed at
697     * most once (by tracking "remaining" elements); (3) skip over
698     * null slots, which can occur if takes race ahead of iterators.
699 dl 1.60 * However, for circular array-based queues, we cannot rely on any
700     * well established definition of what it means to be weakly
701     * consistent with respect to interior removes since these may
702     * require slot overwrites in the process of sliding elements to
703     * cover gaps. So we settle for resiliency, operating on
704 jsr166 1.62 * established apparent nexts, which may miss some elements that
705 dl 1.66 * have moved between calls to next.
706 dl 1.8 */
707 dl 1.5 private class Itr implements Iterator<E> {
708 dl 1.60 private int remaining; // Number of elements yet to be returned
709     private int nextIndex; // Index of element to be returned by next
710     private E nextItem; // Element to be returned by next call to next
711     private E lastItem; // Element returned by last call to next
712     private int lastRet; // Index of last element returned, or -1 if none
713 tim 1.12
714 dl 1.66 Itr() {
715 jsr166 1.68 final ReentrantLock lock = ArrayBlockingQueue.this.lock;
716     lock.lock();
717     try {
718     lastRet = -1;
719     if ((remaining = count) > 0)
720     nextItem = itemAt(nextIndex = takeIndex);
721     } finally {
722     lock.unlock();
723     }
724 dl 1.5 }
725 tim 1.12
726 dl 1.5 public boolean hasNext() {
727 dl 1.60 return remaining > 0;
728 dl 1.5 }
729 tim 1.12
730 dl 1.5 public E next() {
731 dl 1.66 final ReentrantLock lock = ArrayBlockingQueue.this.lock;
732     lock.lock();
733     try {
734 dl 1.67 if (remaining <= 0)
735     throw new NoSuchElementException();
736 dl 1.66 lastRet = nextIndex;
737 dl 1.75 E x = itemAt(nextIndex); // check for fresher value
738     if (x == null) {
739     x = nextItem; // we are forced to report old value
740     lastItem = null; // but ensure remove fails
741 dl 1.66 }
742 dl 1.75 else
743     lastItem = x;
744     while (--remaining > 0 && // skip over nulls
745     (nextItem = itemAt(nextIndex = inc(nextIndex))) == null)
746     ;
747 dl 1.66 return x;
748     } finally {
749     lock.unlock();
750 dl 1.2 }
751 dl 1.5 }
752 tim 1.12
753 dl 1.5 public void remove() {
754 dl 1.36 final ReentrantLock lock = ArrayBlockingQueue.this.lock;
755 dl 1.5 lock.lock();
756     try {
757 dl 1.66 int i = lastRet;
758     if (i == -1)
759     throw new IllegalStateException();
760 dl 1.2 lastRet = -1;
761 jsr166 1.61 E x = lastItem;
762     lastItem = null;
763 jsr166 1.71 // only remove if item still at index
764 dl 1.75 if (x != null && x == items[i]) {
765 jsr166 1.71 boolean removingHead = (i == takeIndex);
766     removeAt(i);
767     if (!removingHead)
768     nextIndex = dec(nextIndex);
769     }
770 tim 1.23 } finally {
771 dl 1.5 lock.unlock();
772     }
773     }
774 tim 1.1 }
775 dl 1.60
776 tim 1.1 }