ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ArrayBlockingQueue.java
Revision: 1.68
Committed: Thu Sep 30 00:24:20 2010 UTC (13 years, 8 months ago) by jsr166
Branch: MAIN
Changes since 1.67: +100 -75 lines
Log Message:
fix javac warnings; optimize copy constructor, toString

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