ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/LinkedBlockingDeque.java
Revision: 1.20
Committed: Sun Feb 15 23:41:38 2009 UTC (15 years, 3 months ago) by dl
Branch: MAIN
Changes since 1.19: +2 -0 lines
Log Message:
Null fields on unlink to help GC

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/licenses/publicdomain
5 */
6
7 package java.util.concurrent;
8 import java.util.*;
9 import java.util.concurrent.locks.*;
10
11 /**
12 * An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
13 * linked nodes.
14 *
15 * <p> The optional capacity bound constructor argument serves as a
16 * way to prevent excessive expansion. The capacity, if unspecified,
17 * is equal to {@link Integer#MAX_VALUE}. Linked nodes are
18 * dynamically created upon each insertion unless this would bring the
19 * deque above capacity.
20 *
21 * <p>Most operations run in constant time (ignoring time spent
22 * blocking). Exceptions include {@link #remove(Object) remove},
23 * {@link #removeFirstOccurrence removeFirstOccurrence}, {@link
24 * #removeLastOccurrence removeLastOccurrence}, {@link #contains
25 * contains}, {@link #iterator iterator.remove()}, and the bulk
26 * operations, all of which run in linear time.
27 *
28 * <p>This class and its iterator implement all of the
29 * <em>optional</em> methods of the {@link Collection} and {@link
30 * Iterator} interfaces.
31 *
32 * <p>This class is a member of the
33 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
34 * Java Collections Framework</a>.
35 *
36 * @since 1.6
37 * @author Doug Lea
38 * @param <E> the type of elements held in this collection
39 */
40 public class LinkedBlockingDeque<E>
41 extends AbstractQueue<E>
42 implements BlockingDeque<E>, java.io.Serializable {
43
44 /*
45 * Implemented as a simple doubly-linked list protected by a
46 * single lock and using conditions to manage blocking.
47 */
48
49 /*
50 * We have "diamond" multiple interface/abstract class inheritance
51 * here, and that introduces ambiguities. Often we want the
52 * BlockingDeque javadoc combined with the AbstractQueue
53 * implementation, so a lot of method specs are duplicated here.
54 */
55
56 private static final long serialVersionUID = -387911632671998426L;
57
58 /** Doubly-linked list node class */
59 static final class Node<E> {
60 E item;
61 Node<E> prev;
62 Node<E> next;
63 Node(E x, Node<E> p, Node<E> n) {
64 item = x;
65 prev = p;
66 next = n;
67 }
68 }
69
70 /** Pointer to first node */
71 private transient Node<E> first;
72 /** Pointer to last node */
73 private transient Node<E> last;
74 /** Number of items in the deque */
75 private transient int count;
76 /** Maximum number of items in the deque */
77 private final int capacity;
78 /** Main lock guarding all access */
79 private final ReentrantLock lock = new ReentrantLock();
80 /** Condition for waiting takes */
81 private final Condition notEmpty = lock.newCondition();
82 /** Condition for waiting puts */
83 private final Condition notFull = lock.newCondition();
84
85 /**
86 * Creates a <tt>LinkedBlockingDeque</tt> with a capacity of
87 * {@link Integer#MAX_VALUE}.
88 */
89 public LinkedBlockingDeque() {
90 this(Integer.MAX_VALUE);
91 }
92
93 /**
94 * Creates a <tt>LinkedBlockingDeque</tt> with the given (fixed) capacity.
95 *
96 * @param capacity the capacity of this deque
97 * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
98 */
99 public LinkedBlockingDeque(int capacity) {
100 if (capacity <= 0) throw new IllegalArgumentException();
101 this.capacity = capacity;
102 }
103
104 /**
105 * Creates a <tt>LinkedBlockingDeque</tt> with a capacity of
106 * {@link Integer#MAX_VALUE}, initially containing the elements of
107 * the given collection, added in traversal order of the
108 * collection's iterator.
109 *
110 * @param c the collection of elements to initially contain
111 * @throws NullPointerException if the specified collection or any
112 * of its elements are null
113 */
114 public LinkedBlockingDeque(Collection<? extends E> c) {
115 this(Integer.MAX_VALUE);
116 for (E e : c)
117 add(e);
118 }
119
120
121 // Basic linking and unlinking operations, called only while holding lock
122
123 /**
124 * Links e as first element, or returns false if full.
125 */
126 private boolean linkFirst(E e) {
127 if (count >= capacity)
128 return false;
129 ++count;
130 Node<E> f = first;
131 Node<E> x = new Node<E>(e, null, f);
132 first = x;
133 if (last == null)
134 last = x;
135 else
136 f.prev = x;
137 notEmpty.signal();
138 return true;
139 }
140
141 /**
142 * Links e as last element, or returns false if full.
143 */
144 private boolean linkLast(E e) {
145 if (count >= capacity)
146 return false;
147 ++count;
148 Node<E> l = last;
149 Node<E> x = new Node<E>(e, l, null);
150 last = x;
151 if (first == null)
152 first = x;
153 else
154 l.next = x;
155 notEmpty.signal();
156 return true;
157 }
158
159 /**
160 * Removes and returns first element, or null if empty.
161 */
162 private E unlinkFirst() {
163 Node<E> f = first;
164 if (f == null)
165 return null;
166 Node<E> n = f.next;
167 f.next = null; // help GC
168 first = n;
169 if (n == null)
170 last = null;
171 else
172 n.prev = null;
173 --count;
174 notFull.signal();
175 return f.item;
176 }
177
178 /**
179 * Removes and returns last element, or null if empty.
180 */
181 private E unlinkLast() {
182 Node<E> l = last;
183 if (l == null)
184 return null;
185 Node<E> p = l.prev;
186 l.prev = null; // help GC
187 last = p;
188 if (p == null)
189 first = null;
190 else
191 p.next = null;
192 --count;
193 notFull.signal();
194 return l.item;
195 }
196
197 /**
198 * Unlink e
199 */
200 private void unlink(Node<E> x) {
201 Node<E> p = x.prev;
202 Node<E> n = x.next;
203 if (p == null) {
204 if (n == null)
205 first = last = null;
206 else {
207 n.prev = null;
208 first = n;
209 }
210 } else if (n == null) {
211 p.next = null;
212 last = p;
213 } else {
214 p.next = n;
215 n.prev = p;
216 }
217 --count;
218 notFull.signalAll();
219 }
220
221 // BlockingDeque methods
222
223 /**
224 * @throws IllegalStateException {@inheritDoc}
225 * @throws NullPointerException {@inheritDoc}
226 */
227 public void addFirst(E e) {
228 if (!offerFirst(e))
229 throw new IllegalStateException("Deque full");
230 }
231
232 /**
233 * @throws IllegalStateException {@inheritDoc}
234 * @throws NullPointerException {@inheritDoc}
235 */
236 public void addLast(E e) {
237 if (!offerLast(e))
238 throw new IllegalStateException("Deque full");
239 }
240
241 /**
242 * @throws NullPointerException {@inheritDoc}
243 */
244 public boolean offerFirst(E e) {
245 if (e == null) throw new NullPointerException();
246 lock.lock();
247 try {
248 return linkFirst(e);
249 } finally {
250 lock.unlock();
251 }
252 }
253
254 /**
255 * @throws NullPointerException {@inheritDoc}
256 */
257 public boolean offerLast(E e) {
258 if (e == null) throw new NullPointerException();
259 lock.lock();
260 try {
261 return linkLast(e);
262 } finally {
263 lock.unlock();
264 }
265 }
266
267 /**
268 * @throws NullPointerException {@inheritDoc}
269 * @throws InterruptedException {@inheritDoc}
270 */
271 public void putFirst(E e) throws InterruptedException {
272 if (e == null) throw new NullPointerException();
273 lock.lock();
274 try {
275 while (!linkFirst(e))
276 notFull.await();
277 } finally {
278 lock.unlock();
279 }
280 }
281
282 /**
283 * @throws NullPointerException {@inheritDoc}
284 * @throws InterruptedException {@inheritDoc}
285 */
286 public void putLast(E e) throws InterruptedException {
287 if (e == null) throw new NullPointerException();
288 lock.lock();
289 try {
290 while (!linkLast(e))
291 notFull.await();
292 } finally {
293 lock.unlock();
294 }
295 }
296
297 /**
298 * @throws NullPointerException {@inheritDoc}
299 * @throws InterruptedException {@inheritDoc}
300 */
301 public boolean offerFirst(E e, long timeout, TimeUnit unit)
302 throws InterruptedException {
303 if (e == null) throw new NullPointerException();
304 long nanos = unit.toNanos(timeout);
305 lock.lockInterruptibly();
306 try {
307 for (;;) {
308 if (linkFirst(e))
309 return true;
310 if (nanos <= 0)
311 return false;
312 nanos = notFull.awaitNanos(nanos);
313 }
314 } finally {
315 lock.unlock();
316 }
317 }
318
319 /**
320 * @throws NullPointerException {@inheritDoc}
321 * @throws InterruptedException {@inheritDoc}
322 */
323 public boolean offerLast(E e, long timeout, TimeUnit unit)
324 throws InterruptedException {
325 if (e == null) throw new NullPointerException();
326 long nanos = unit.toNanos(timeout);
327 lock.lockInterruptibly();
328 try {
329 for (;;) {
330 if (linkLast(e))
331 return true;
332 if (nanos <= 0)
333 return false;
334 nanos = notFull.awaitNanos(nanos);
335 }
336 } finally {
337 lock.unlock();
338 }
339 }
340
341 /**
342 * @throws NoSuchElementException {@inheritDoc}
343 */
344 public E removeFirst() {
345 E x = pollFirst();
346 if (x == null) throw new NoSuchElementException();
347 return x;
348 }
349
350 /**
351 * @throws NoSuchElementException {@inheritDoc}
352 */
353 public E removeLast() {
354 E x = pollLast();
355 if (x == null) throw new NoSuchElementException();
356 return x;
357 }
358
359 public E pollFirst() {
360 lock.lock();
361 try {
362 return unlinkFirst();
363 } finally {
364 lock.unlock();
365 }
366 }
367
368 public E pollLast() {
369 lock.lock();
370 try {
371 return unlinkLast();
372 } finally {
373 lock.unlock();
374 }
375 }
376
377 public E takeFirst() throws InterruptedException {
378 lock.lock();
379 try {
380 E x;
381 while ( (x = unlinkFirst()) == null)
382 notEmpty.await();
383 return x;
384 } finally {
385 lock.unlock();
386 }
387 }
388
389 public E takeLast() throws InterruptedException {
390 lock.lock();
391 try {
392 E x;
393 while ( (x = unlinkLast()) == null)
394 notEmpty.await();
395 return x;
396 } finally {
397 lock.unlock();
398 }
399 }
400
401 public E pollFirst(long timeout, TimeUnit unit)
402 throws InterruptedException {
403 long nanos = unit.toNanos(timeout);
404 lock.lockInterruptibly();
405 try {
406 for (;;) {
407 E x = unlinkFirst();
408 if (x != null)
409 return x;
410 if (nanos <= 0)
411 return null;
412 nanos = notEmpty.awaitNanos(nanos);
413 }
414 } finally {
415 lock.unlock();
416 }
417 }
418
419 public E pollLast(long timeout, TimeUnit unit)
420 throws InterruptedException {
421 long nanos = unit.toNanos(timeout);
422 lock.lockInterruptibly();
423 try {
424 for (;;) {
425 E x = unlinkLast();
426 if (x != null)
427 return x;
428 if (nanos <= 0)
429 return null;
430 nanos = notEmpty.awaitNanos(nanos);
431 }
432 } finally {
433 lock.unlock();
434 }
435 }
436
437 /**
438 * @throws NoSuchElementException {@inheritDoc}
439 */
440 public E getFirst() {
441 E x = peekFirst();
442 if (x == null) throw new NoSuchElementException();
443 return x;
444 }
445
446 /**
447 * @throws NoSuchElementException {@inheritDoc}
448 */
449 public E getLast() {
450 E x = peekLast();
451 if (x == null) throw new NoSuchElementException();
452 return x;
453 }
454
455 public E peekFirst() {
456 lock.lock();
457 try {
458 return (first == null) ? null : first.item;
459 } finally {
460 lock.unlock();
461 }
462 }
463
464 public E peekLast() {
465 lock.lock();
466 try {
467 return (last == null) ? null : last.item;
468 } finally {
469 lock.unlock();
470 }
471 }
472
473 public boolean removeFirstOccurrence(Object o) {
474 if (o == null) return false;
475 lock.lock();
476 try {
477 for (Node<E> p = first; p != null; p = p.next) {
478 if (o.equals(p.item)) {
479 unlink(p);
480 return true;
481 }
482 }
483 return false;
484 } finally {
485 lock.unlock();
486 }
487 }
488
489 public boolean removeLastOccurrence(Object o) {
490 if (o == null) return false;
491 lock.lock();
492 try {
493 for (Node<E> p = last; p != null; p = p.prev) {
494 if (o.equals(p.item)) {
495 unlink(p);
496 return true;
497 }
498 }
499 return false;
500 } finally {
501 lock.unlock();
502 }
503 }
504
505 // BlockingQueue methods
506
507 /**
508 * Inserts the specified element at the end of this deque unless it would
509 * violate capacity restrictions. When using a capacity-restricted deque,
510 * it is generally preferable to use method {@link #offer(Object) offer}.
511 *
512 * <p>This method is equivalent to {@link #addLast}.
513 *
514 * @throws IllegalStateException if the element cannot be added at this
515 * time due to capacity restrictions
516 * @throws NullPointerException if the specified element is null
517 */
518 public boolean add(E e) {
519 addLast(e);
520 return true;
521 }
522
523 /**
524 * @throws NullPointerException if the specified element is null
525 */
526 public boolean offer(E e) {
527 return offerLast(e);
528 }
529
530 /**
531 * @throws NullPointerException {@inheritDoc}
532 * @throws InterruptedException {@inheritDoc}
533 */
534 public void put(E e) throws InterruptedException {
535 putLast(e);
536 }
537
538 /**
539 * @throws NullPointerException {@inheritDoc}
540 * @throws InterruptedException {@inheritDoc}
541 */
542 public boolean offer(E e, long timeout, TimeUnit unit)
543 throws InterruptedException {
544 return offerLast(e, timeout, unit);
545 }
546
547 /**
548 * Retrieves and removes the head of the queue represented by this deque.
549 * This method differs from {@link #poll poll} only in that it throws an
550 * exception if this deque is empty.
551 *
552 * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
553 *
554 * @return the head of the queue represented by this deque
555 * @throws NoSuchElementException if this deque is empty
556 */
557 public E remove() {
558 return removeFirst();
559 }
560
561 public E poll() {
562 return pollFirst();
563 }
564
565 public E take() throws InterruptedException {
566 return takeFirst();
567 }
568
569 public E poll(long timeout, TimeUnit unit) throws InterruptedException {
570 return pollFirst(timeout, unit);
571 }
572
573 /**
574 * Retrieves, but does not remove, the head of the queue represented by
575 * this deque. This method differs from {@link #peek peek} only in that
576 * it throws an exception if this deque is empty.
577 *
578 * <p>This method is equivalent to {@link #getFirst() getFirst}.
579 *
580 * @return the head of the queue represented by this deque
581 * @throws NoSuchElementException if this deque is empty
582 */
583 public E element() {
584 return getFirst();
585 }
586
587 public E peek() {
588 return peekFirst();
589 }
590
591 /**
592 * Returns the number of additional elements that this deque can ideally
593 * (in the absence of memory or resource constraints) accept without
594 * blocking. This is always equal to the initial capacity of this deque
595 * less the current <tt>size</tt> of this deque.
596 *
597 * <p>Note that you <em>cannot</em> always tell if an attempt to insert
598 * an element will succeed by inspecting <tt>remainingCapacity</tt>
599 * because it may be the case that another thread is about to
600 * insert or remove an element.
601 */
602 public int remainingCapacity() {
603 lock.lock();
604 try {
605 return capacity - count;
606 } finally {
607 lock.unlock();
608 }
609 }
610
611 /**
612 * @throws UnsupportedOperationException {@inheritDoc}
613 * @throws ClassCastException {@inheritDoc}
614 * @throws NullPointerException {@inheritDoc}
615 * @throws IllegalArgumentException {@inheritDoc}
616 */
617 public int drainTo(Collection<? super E> c) {
618 if (c == null)
619 throw new NullPointerException();
620 if (c == this)
621 throw new IllegalArgumentException();
622 lock.lock();
623 try {
624 for (Node<E> p = first; p != null; p = p.next)
625 c.add(p.item);
626 int n = count;
627 count = 0;
628 first = last = null;
629 notFull.signalAll();
630 return n;
631 } finally {
632 lock.unlock();
633 }
634 }
635
636 /**
637 * @throws UnsupportedOperationException {@inheritDoc}
638 * @throws ClassCastException {@inheritDoc}
639 * @throws NullPointerException {@inheritDoc}
640 * @throws IllegalArgumentException {@inheritDoc}
641 */
642 public int drainTo(Collection<? super E> c, int maxElements) {
643 if (c == null)
644 throw new NullPointerException();
645 if (c == this)
646 throw new IllegalArgumentException();
647 lock.lock();
648 try {
649 int n = 0;
650 while (n < maxElements && first != null) {
651 c.add(first.item);
652 first.prev = null;
653 first = first.next;
654 --count;
655 ++n;
656 }
657 if (first == null)
658 last = null;
659 notFull.signalAll();
660 return n;
661 } finally {
662 lock.unlock();
663 }
664 }
665
666 // Stack methods
667
668 /**
669 * @throws IllegalStateException {@inheritDoc}
670 * @throws NullPointerException {@inheritDoc}
671 */
672 public void push(E e) {
673 addFirst(e);
674 }
675
676 /**
677 * @throws NoSuchElementException {@inheritDoc}
678 */
679 public E pop() {
680 return removeFirst();
681 }
682
683 // Collection methods
684
685 /**
686 * Removes the first occurrence of the specified element from this deque.
687 * If the deque does not contain the element, it is unchanged.
688 * More formally, removes the first element <tt>e</tt> such that
689 * <tt>o.equals(e)</tt> (if such an element exists).
690 * Returns <tt>true</tt> if this deque contained the specified element
691 * (or equivalently, if this deque changed as a result of the call).
692 *
693 * <p>This method is equivalent to
694 * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
695 *
696 * @param o element to be removed from this deque, if present
697 * @return <tt>true</tt> if this deque changed as a result of the call
698 */
699 public boolean remove(Object o) {
700 return removeFirstOccurrence(o);
701 }
702
703 /**
704 * Returns the number of elements in this deque.
705 *
706 * @return the number of elements in this deque
707 */
708 public int size() {
709 lock.lock();
710 try {
711 return count;
712 } finally {
713 lock.unlock();
714 }
715 }
716
717 /**
718 * Returns <tt>true</tt> if this deque contains the specified element.
719 * More formally, returns <tt>true</tt> if and only if this deque contains
720 * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
721 *
722 * @param o object to be checked for containment in this deque
723 * @return <tt>true</tt> if this deque contains the specified element
724 */
725 public boolean contains(Object o) {
726 if (o == null) return false;
727 lock.lock();
728 try {
729 for (Node<E> p = first; p != null; p = p.next)
730 if (o.equals(p.item))
731 return true;
732 return false;
733 } finally {
734 lock.unlock();
735 }
736 }
737
738 /**
739 * Variant of removeFirstOccurrence needed by iterator.remove.
740 * Searches for the node, not its contents.
741 */
742 boolean removeNode(Node<E> e) {
743 lock.lock();
744 try {
745 for (Node<E> p = first; p != null; p = p.next) {
746 if (p == e) {
747 unlink(p);
748 return true;
749 }
750 }
751 return false;
752 } finally {
753 lock.unlock();
754 }
755 }
756
757 /**
758 * Returns an array containing all of the elements in this deque, in
759 * proper sequence (from first to last element).
760 *
761 * <p>The returned array will be "safe" in that no references to it are
762 * maintained by this deque. (In other words, this method must allocate
763 * a new array). The caller is thus free to modify the returned array.
764 *
765 * <p>This method acts as bridge between array-based and collection-based
766 * APIs.
767 *
768 * @return an array containing all of the elements in this deque
769 */
770 public Object[] toArray() {
771 lock.lock();
772 try {
773 Object[] a = new Object[count];
774 int k = 0;
775 for (Node<E> p = first; p != null; p = p.next)
776 a[k++] = p.item;
777 return a;
778 } finally {
779 lock.unlock();
780 }
781 }
782
783 /**
784 * Returns an array containing all of the elements in this deque, in
785 * proper sequence; the runtime type of the returned array is that of
786 * the specified array. If the deque fits in the specified array, it
787 * is returned therein. Otherwise, a new array is allocated with the
788 * runtime type of the specified array and the size of this deque.
789 *
790 * <p>If this deque fits in the specified array with room to spare
791 * (i.e., the array has more elements than this deque), the element in
792 * the array immediately following the end of the deque is set to
793 * <tt>null</tt>.
794 *
795 * <p>Like the {@link #toArray()} method, this method acts as bridge between
796 * array-based and collection-based APIs. Further, this method allows
797 * precise control over the runtime type of the output array, and may,
798 * under certain circumstances, be used to save allocation costs.
799 *
800 * <p>Suppose <tt>x</tt> is a deque known to contain only strings.
801 * The following code can be used to dump the deque into a newly
802 * allocated array of <tt>String</tt>:
803 *
804 * <pre>
805 * String[] y = x.toArray(new String[0]);</pre>
806 *
807 * Note that <tt>toArray(new Object[0])</tt> is identical in function to
808 * <tt>toArray()</tt>.
809 *
810 * @param a the array into which the elements of the deque are to
811 * be stored, if it is big enough; otherwise, a new array of the
812 * same runtime type is allocated for this purpose
813 * @return an array containing all of the elements in this deque
814 * @throws ArrayStoreException if the runtime type of the specified array
815 * is not a supertype of the runtime type of every element in
816 * this deque
817 * @throws NullPointerException if the specified array is null
818 */
819 public <T> T[] toArray(T[] a) {
820 lock.lock();
821 try {
822 if (a.length < count)
823 a = (T[])java.lang.reflect.Array.newInstance(
824 a.getClass().getComponentType(),
825 count
826 );
827
828 int k = 0;
829 for (Node<E> p = first; p != null; p = p.next)
830 a[k++] = (T)p.item;
831 if (a.length > k)
832 a[k] = null;
833 return a;
834 } finally {
835 lock.unlock();
836 }
837 }
838
839 public String toString() {
840 lock.lock();
841 try {
842 return super.toString();
843 } finally {
844 lock.unlock();
845 }
846 }
847
848 /**
849 * Atomically removes all of the elements from this deque.
850 * The deque will be empty after this call returns.
851 */
852 public void clear() {
853 lock.lock();
854 try {
855 first = last = null;
856 count = 0;
857 notFull.signalAll();
858 } finally {
859 lock.unlock();
860 }
861 }
862
863 /**
864 * Returns an iterator over the elements in this deque in proper sequence.
865 * The elements will be returned in order from first (head) to last (tail).
866 * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
867 * will never throw {@link ConcurrentModificationException},
868 * and guarantees to traverse elements as they existed upon
869 * construction of the iterator, and may (but is not guaranteed to)
870 * reflect any modifications subsequent to construction.
871 *
872 * @return an iterator over the elements in this deque in proper sequence
873 */
874 public Iterator<E> iterator() {
875 return new Itr();
876 }
877
878 /**
879 * Returns an iterator over the elements in this deque in reverse
880 * sequential order. The elements will be returned in order from
881 * last (tail) to first (head).
882 * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
883 * will never throw {@link ConcurrentModificationException},
884 * and guarantees to traverse elements as they existed upon
885 * construction of the iterator, and may (but is not guaranteed to)
886 * reflect any modifications subsequent to construction.
887 */
888 public Iterator<E> descendingIterator() {
889 return new DescendingItr();
890 }
891
892 /**
893 * Base class for Iterators for LinkedBlockingDeque
894 */
895 private abstract class AbstractItr implements Iterator<E> {
896 /**
897 * The next node to return in next
898 */
899 Node<E> next;
900
901 /**
902 * nextItem holds on to item fields because once we claim that
903 * an element exists in hasNext(), we must return item read
904 * under lock (in advance()) even if it was in the process of
905 * being removed when hasNext() was called.
906 */
907 E nextItem;
908
909 /**
910 * Node returned by most recent call to next. Needed by remove.
911 * Reset to null if this element is deleted by a call to remove.
912 */
913 private Node<E> lastRet;
914
915 AbstractItr() {
916 advance(); // set to initial position
917 }
918
919 /**
920 * Advances next, or if not yet initialized, sets to first node.
921 * Implemented to move forward vs backward in the two subclasses.
922 */
923 abstract void advance();
924
925 public boolean hasNext() {
926 return next != null;
927 }
928
929 public E next() {
930 if (next == null)
931 throw new NoSuchElementException();
932 lastRet = next;
933 E x = nextItem;
934 advance();
935 return x;
936 }
937
938 public void remove() {
939 Node<E> n = lastRet;
940 if (n == null)
941 throw new IllegalStateException();
942 lastRet = null;
943 // Note: removeNode rescans looking for this node to make
944 // sure it was not already removed. Otherwise, trying to
945 // re-remove could corrupt list.
946 removeNode(n);
947 }
948 }
949
950 /** Forward iterator */
951 private class Itr extends AbstractItr {
952 void advance() {
953 final ReentrantLock lock = LinkedBlockingDeque.this.lock;
954 lock.lock();
955 try {
956 next = (next == null)? first : next.next;
957 nextItem = (next == null)? null : next.item;
958 } finally {
959 lock.unlock();
960 }
961 }
962 }
963
964 /**
965 * Descending iterator for LinkedBlockingDeque
966 */
967 private class DescendingItr extends AbstractItr {
968 void advance() {
969 final ReentrantLock lock = LinkedBlockingDeque.this.lock;
970 lock.lock();
971 try {
972 next = (next == null)? last : next.prev;
973 nextItem = (next == null)? null : next.item;
974 } finally {
975 lock.unlock();
976 }
977 }
978 }
979
980 /**
981 * Save the state of this deque to a stream (that is, serialize it).
982 *
983 * @serialData The capacity (int), followed by elements (each an
984 * <tt>Object</tt>) in the proper order, followed by a null
985 * @param s the stream
986 */
987 private void writeObject(java.io.ObjectOutputStream s)
988 throws java.io.IOException {
989 lock.lock();
990 try {
991 // Write out capacity and any hidden stuff
992 s.defaultWriteObject();
993 // Write out all elements in the proper order.
994 for (Node<E> p = first; p != null; p = p.next)
995 s.writeObject(p.item);
996 // Use trailing null as sentinel
997 s.writeObject(null);
998 } finally {
999 lock.unlock();
1000 }
1001 }
1002
1003 /**
1004 * Reconstitute this deque from a stream (that is,
1005 * deserialize it).
1006 * @param s the stream
1007 */
1008 private void readObject(java.io.ObjectInputStream s)
1009 throws java.io.IOException, ClassNotFoundException {
1010 s.defaultReadObject();
1011 count = 0;
1012 first = null;
1013 last = null;
1014 // Read in all elements and place in queue
1015 for (;;) {
1016 E item = (E)s.readObject();
1017 if (item == null)
1018 break;
1019 add(item);
1020 }
1021 }
1022
1023 }