ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/LinkedBlockingDeque.java
Revision: 1.12
Committed: Sat May 28 15:08:57 2005 UTC (19 years ago) by jsr166
Branch: MAIN
Changes since 1.11: +1 -1 lines
Log Message:
whitespace

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}/../guide/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 first = n;
168 if (n == null)
169 last = null;
170 else
171 n.prev = null;
172 --count;
173 notFull.signal();
174 return f.item;
175 }
176
177 /**
178 * Removes and returns last element, or null if empty.
179 */
180 private E unlinkLast() {
181 Node<E> l = last;
182 if (l == null)
183 return null;
184 Node<E> p = l.prev;
185 last = p;
186 if (p == null)
187 first = null;
188 else
189 p.next = null;
190 --count;
191 notFull.signal();
192 return l.item;
193 }
194
195 /**
196 * Unlink e
197 */
198 private void unlink(Node<E> x) {
199 Node<E> p = x.prev;
200 Node<E> n = x.next;
201 if (p == null) {
202 if (n == null)
203 first = last = null;
204 else {
205 n.prev = null;
206 first = n;
207 }
208 } else if (n == null) {
209 p.next = null;
210 last = p;
211 } else {
212 p.next = n;
213 n.prev = p;
214 }
215 --count;
216 notFull.signalAll();
217 }
218
219 // BlockingDeque methods
220
221 /**
222 * @throws IllegalStateException {@inheritDoc}
223 * @throws NullPointerException {@inheritDoc}
224 */
225 public void addFirst(E e) {
226 if (!offerFirst(e))
227 throw new IllegalStateException("Deque full");
228 }
229
230 /**
231 * @throws IllegalStateException {@inheritDoc}
232 * @throws NullPointerException {@inheritDoc}
233 */
234 public void addLast(E e) {
235 if (!offerLast(e))
236 throw new IllegalStateException("Deque full");
237 }
238
239 /**
240 * @throws NullPointerException {@inheritDoc}
241 */
242 public boolean offerFirst(E e) {
243 if (e == null) throw new NullPointerException();
244 lock.lock();
245 try {
246 return linkFirst(e);
247 } finally {
248 lock.unlock();
249 }
250 }
251
252 /**
253 * @throws NullPointerException {@inheritDoc}
254 */
255 public boolean offerLast(E e) {
256 if (e == null) throw new NullPointerException();
257 lock.lock();
258 try {
259 return linkLast(e);
260 } finally {
261 lock.unlock();
262 }
263 }
264
265 /**
266 * @throws NullPointerException {@inheritDoc}
267 * @throws InterruptedException {@inheritDoc}
268 */
269 public void putFirst(E e) throws InterruptedException {
270 if (e == null) throw new NullPointerException();
271 lock.lock();
272 try {
273 while (!linkFirst(e))
274 notFull.await();
275 } finally {
276 lock.unlock();
277 }
278 }
279
280 /**
281 * @throws NullPointerException {@inheritDoc}
282 * @throws InterruptedException {@inheritDoc}
283 */
284 public void putLast(E e) throws InterruptedException {
285 if (e == null) throw new NullPointerException();
286 lock.lock();
287 try {
288 while (!linkLast(e))
289 notFull.await();
290 } finally {
291 lock.unlock();
292 }
293 }
294
295 /**
296 * @throws NullPointerException {@inheritDoc}
297 * @throws InterruptedException {@inheritDoc}
298 */
299 public boolean offerFirst(E e, long timeout, TimeUnit unit)
300 throws InterruptedException {
301 if (e == null) throw new NullPointerException();
302 lock.lockInterruptibly();
303 try {
304 long nanos = unit.toNanos(timeout);
305 for (;;) {
306 if (linkFirst(e))
307 return true;
308 if (nanos <= 0)
309 return false;
310 nanos = notFull.awaitNanos(nanos);
311 }
312 } finally {
313 lock.unlock();
314 }
315 }
316
317 /**
318 * @throws NullPointerException {@inheritDoc}
319 * @throws InterruptedException {@inheritDoc}
320 */
321 public boolean offerLast(E e, long timeout, TimeUnit unit)
322 throws InterruptedException {
323 if (e == null) throw new NullPointerException();
324 lock.lockInterruptibly();
325 try {
326 long nanos = unit.toNanos(timeout);
327 for (;;) {
328 if (linkLast(e))
329 return true;
330 if (nanos <= 0)
331 return false;
332 nanos = notFull.awaitNanos(nanos);
333 }
334 } finally {
335 lock.unlock();
336 }
337 }
338
339 /**
340 * @throws NoSuchElementException {@inheritDoc}
341 */
342 public E removeFirst() {
343 E x = pollFirst();
344 if (x == null) throw new NoSuchElementException();
345 return x;
346 }
347
348 /**
349 * @throws NoSuchElementException {@inheritDoc}
350 */
351 public E removeLast() {
352 E x = pollLast();
353 if (x == null) throw new NoSuchElementException();
354 return x;
355 }
356
357 public E pollFirst() {
358 lock.lock();
359 try {
360 return unlinkFirst();
361 } finally {
362 lock.unlock();
363 }
364 }
365
366 public E pollLast() {
367 lock.lock();
368 try {
369 return unlinkLast();
370 } finally {
371 lock.unlock();
372 }
373 }
374
375 public E takeFirst() throws InterruptedException {
376 lock.lock();
377 try {
378 E x;
379 while ( (x = unlinkFirst()) == null)
380 notEmpty.await();
381 return x;
382 } finally {
383 lock.unlock();
384 }
385 }
386
387 public E takeLast() throws InterruptedException {
388 lock.lock();
389 try {
390 E x;
391 while ( (x = unlinkLast()) == null)
392 notEmpty.await();
393 return x;
394 } finally {
395 lock.unlock();
396 }
397 }
398
399 public E pollFirst(long timeout, TimeUnit unit)
400 throws InterruptedException {
401 lock.lockInterruptibly();
402 try {
403 long nanos = unit.toNanos(timeout);
404 for (;;) {
405 E x = unlinkFirst();
406 if (x != null)
407 return x;
408 if (nanos <= 0)
409 return null;
410 nanos = notEmpty.awaitNanos(nanos);
411 }
412 } finally {
413 lock.unlock();
414 }
415 }
416
417 public E pollLast(long timeout, TimeUnit unit)
418 throws InterruptedException {
419 lock.lockInterruptibly();
420 try {
421 long nanos = unit.toNanos(timeout);
422 for (;;) {
423 E x = unlinkLast();
424 if (x != null)
425 return x;
426 if (nanos <= 0)
427 return null;
428 nanos = notEmpty.awaitNanos(nanos);
429 }
430 } finally {
431 lock.unlock();
432 }
433 }
434
435 /**
436 * @throws NoSuchElementException {@inheritDoc}
437 */
438 public E getFirst() {
439 E x = peekFirst();
440 if (x == null) throw new NoSuchElementException();
441 return x;
442 }
443
444 /**
445 * @throws NoSuchElementException {@inheritDoc}
446 */
447 public E getLast() {
448 E x = peekLast();
449 if (x == null) throw new NoSuchElementException();
450 return x;
451 }
452
453 public E peekFirst() {
454 lock.lock();
455 try {
456 return (first == null) ? null : first.item;
457 } finally {
458 lock.unlock();
459 }
460 }
461
462 public E peekLast() {
463 lock.lock();
464 try {
465 return (last == null) ? null : last.item;
466 } finally {
467 lock.unlock();
468 }
469 }
470
471 public boolean removeFirstOccurrence(Object o) {
472 if (o == null) return false;
473 lock.lock();
474 try {
475 for (Node<E> p = first; p != null; p = p.next) {
476 if (o.equals(p.item)) {
477 unlink(p);
478 return true;
479 }
480 }
481 return false;
482 } finally {
483 lock.unlock();
484 }
485 }
486
487 public boolean removeLastOccurrence(Object o) {
488 if (o == null) return false;
489 lock.lock();
490 try {
491 for (Node<E> p = last; p != null; p = p.prev) {
492 if (o.equals(p.item)) {
493 unlink(p);
494 return true;
495 }
496 }
497 return false;
498 } finally {
499 lock.unlock();
500 }
501 }
502
503 // BlockingQueue methods
504
505 /**
506 * Inserts the specified element at the end of this deque unless it would
507 * violate capacity restrictions. When using a capacity-restricted deque,
508 * it is generally preferable to use method {@link #offer(Object) offer}.
509 *
510 * <p>This method is equivalent to {@link #addLast(Object) addLast}.
511 *
512 * @throws IllegalStateException if the element cannot be added at this
513 * time due to capacity restrictions
514 * @throws NullPointerException if the specified element is null
515 */
516 public boolean add(E e) {
517 addLast(e);
518 return true;
519 }
520
521 /**
522 * @throws NullPointerException if the specified element is null
523 */
524 public boolean offer(E e) {
525 return offerLast(e);
526 }
527
528 /**
529 * @throws NullPointerException {@inheritDoc}
530 * @throws InterruptedException {@inheritDoc}
531 */
532 public void put(E e) throws InterruptedException {
533 putLast(e);
534 }
535
536 /**
537 * @throws NullPointerException {@inheritDoc}
538 * @throws InterruptedException {@inheritDoc}
539 */
540 public boolean offer(E e, long timeout, TimeUnit unit)
541 throws InterruptedException {
542 return offerLast(e, timeout, unit);
543 }
544
545 /**
546 * Retrieves and removes the head of the queue represented by this deque.
547 * This method differs from {@link #poll poll} only in that it throws an
548 * exception if this deque is empty.
549 *
550 * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
551 *
552 * @return the head of the queue represented by this deque
553 * @throws NoSuchElementException if this deque is empty
554 */
555 public E remove() {
556 return removeFirst();
557 }
558
559 public E poll() {
560 return pollFirst();
561 }
562
563 public E take() throws InterruptedException {
564 return takeFirst();
565 }
566
567 public E poll(long timeout, TimeUnit unit) throws InterruptedException {
568 return pollFirst(timeout, unit);
569 }
570
571 /**
572 * Retrieves, but does not remove, the head of the queue represented by
573 * this deque. This method differs from {@link #peek peek} only in that
574 * it throws an exception if this deque is empty.
575 *
576 * <p>This method is equivalent to {@link #getFirst() getFirst}.
577 *
578 * @return the head of the queue represented by this deque
579 * @throws NoSuchElementException if this deque is empty
580 */
581 public E element() {
582 return getFirst();
583 }
584
585 public E peek() {
586 return peekFirst();
587 }
588
589 /**
590 * Returns the number of additional elements that this deque can ideally
591 * (in the absence of memory or resource constraints) accept without
592 * blocking. This is always equal to the initial capacity of this deque
593 * less the current <tt>size</tt> of this deque.
594 *
595 * <p>Note that you <em>cannot</em> always tell if an attempt to insert
596 * an element will succeed by inspecting <tt>remainingCapacity</tt>
597 * because it may be the case that another thread is about to
598 * insert or remove an element.
599 */
600 public int remainingCapacity() {
601 lock.lock();
602 try {
603 return capacity - count;
604 } finally {
605 lock.unlock();
606 }
607 }
608
609 /**
610 * @throws UnsupportedOperationException {@inheritDoc}
611 * @throws ClassCastException {@inheritDoc}
612 * @throws NullPointerException {@inheritDoc}
613 * @throws IllegalArgumentException {@inheritDoc}
614 */
615 public int drainTo(Collection<? super E> c) {
616 if (c == null)
617 throw new NullPointerException();
618 if (c == this)
619 throw new IllegalArgumentException();
620 lock.lock();
621 try {
622 for (Node<E> p = first; p != null; p = p.next)
623 c.add(p.item);
624 int n = count;
625 count = 0;
626 first = last = null;
627 notFull.signalAll();
628 return n;
629 } finally {
630 lock.unlock();
631 }
632 }
633
634 /**
635 * @throws UnsupportedOperationException {@inheritDoc}
636 * @throws ClassCastException {@inheritDoc}
637 * @throws NullPointerException {@inheritDoc}
638 * @throws IllegalArgumentException {@inheritDoc}
639 */
640 public int drainTo(Collection<? super E> c, int maxElements) {
641 if (c == null)
642 throw new NullPointerException();
643 if (c == this)
644 throw new IllegalArgumentException();
645 lock.lock();
646 try {
647 int n = 0;
648 while (n < maxElements && first != null) {
649 c.add(first.item);
650 first.prev = null;
651 first = first.next;
652 --count;
653 ++n;
654 }
655 if (first == null)
656 last = null;
657 notFull.signalAll();
658 return n;
659 } finally {
660 lock.unlock();
661 }
662 }
663
664 // Stack methods
665
666 /**
667 * @throws IllegalStateException {@inheritDoc}
668 * @throws NullPointerException {@inheritDoc}
669 */
670 public void push(E e) {
671 addFirst(e);
672 }
673
674 /**
675 * @throws NoSuchElementException {@inheritDoc}
676 */
677 public E pop() {
678 return removeFirst();
679 }
680
681 // Collection methods
682
683 /**
684 * Removes the first occurrence of the specified element from this deque.
685 * If the deque does not contain the element, it is unchanged.
686 * More formally, removes the first element <tt>e</tt> such that
687 * <tt>o.equals(e)</tt> (if such an element exists).
688 * Returns <tt>true</tt> if this deque contained the specified element
689 * (or equivalently, if this deque changed as a result of the call).
690 *
691 * <p>This method is equivalent to
692 * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
693 *
694 * @param o element to be removed from this deque, if present
695 * @return <tt>true</tt> if this deque changed as a result of the call
696 */
697 public boolean remove(Object o) {
698 return removeFirstOccurrence(o);
699 }
700
701 /**
702 * Returns the number of elements in this deque.
703 *
704 * @return the number of elements in this deque
705 */
706 public int size() {
707 lock.lock();
708 try {
709 return count;
710 } finally {
711 lock.unlock();
712 }
713 }
714
715 /**
716 * Returns <tt>true</tt> if this deque contains the specified element.
717 * More formally, returns <tt>true</tt> if and only if this deque contains
718 * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
719 *
720 * @param o object to be checked for containment in this deque
721 * @return <tt>true</tt> if this deque contains the specified element
722 */
723 public boolean contains(Object o) {
724 if (o == null) return false;
725 lock.lock();
726 try {
727 for (Node<E> p = first; p != null; p = p.next)
728 if (o.equals(p.item))
729 return true;
730 return false;
731 } finally {
732 lock.unlock();
733 }
734 }
735
736 /**
737 * Variant of removeFirstOccurrence needed by iterator.remove.
738 * Searches for the node, not its contents.
739 */
740 boolean removeNode(Node<E> e) {
741 lock.lock();
742 try {
743 for (Node<E> p = first; p != null; p = p.next) {
744 if (p == e) {
745 unlink(p);
746 return true;
747 }
748 }
749 return false;
750 } finally {
751 lock.unlock();
752 }
753 }
754
755 /**
756 * Returns an array containing all of the elements in this deque, in
757 * proper sequence (from first to last element).
758 *
759 * <p>The returned array will be "safe" in that no references to it are
760 * maintained by this deque. (In other words, this method must allocate
761 * a new array). The caller is thus free to modify the returned array.
762 *
763 * <p>This method acts as bridge between array-based and collection-based
764 * APIs.
765 *
766 * @return an array containing all of the elements in this deque
767 */
768 public Object[] toArray() {
769 lock.lock();
770 try {
771 Object[] a = new Object[count];
772 int k = 0;
773 for (Node<E> p = first; p != null; p = p.next)
774 a[k++] = p.item;
775 return a;
776 } finally {
777 lock.unlock();
778 }
779 }
780
781 /**
782 * Returns an array containing all of the elements in this deque, in
783 * proper sequence; the runtime type of the returned array is that of
784 * the specified array. If the deque fits in the specified array, it
785 * is returned therein. Otherwise, a new array is allocated with the
786 * runtime type of the specified array and the size of this deque.
787 *
788 * <p>If this deque fits in the specified array with room to spare
789 * (i.e., the array has more elements than this deque), the element in
790 * the array immediately following the end of the deque is set to
791 * <tt>null</tt>.
792 *
793 * <p>Like the {@link #toArray()} method, this method acts as bridge between
794 * array-based and collection-based APIs. Further, this method allows
795 * precise control over the runtime type of the output array, and may,
796 * under certain circumstances, be used to save allocation costs.
797 *
798 * <p>Suppose <tt>x</tt> is a deque known to contain only strings.
799 * The following code can be used to dump the deque into a newly
800 * allocated array of <tt>String</tt>:
801 *
802 * <pre>
803 * String[] y = x.toArray(new String[0]);</pre>
804 *
805 * Note that <tt>toArray(new Object[0])</tt> is identical in function to
806 * <tt>toArray()</tt>.
807 *
808 * @param a the array into which the elements of the deque are to
809 * be stored, if it is big enough; otherwise, a new array of the
810 * same runtime type is allocated for this purpose
811 * @return an array containing all of the elements in this deque
812 * @throws ArrayStoreException if the runtime type of the specified array
813 * is not a supertype of the runtime type of every element in
814 * this deque
815 * @throws NullPointerException if the specified array is null
816 */
817 public <T> T[] toArray(T[] a) {
818 lock.lock();
819 try {
820 if (a.length < count)
821 a = (T[])java.lang.reflect.Array.newInstance(
822 a.getClass().getComponentType(),
823 count
824 );
825
826 int k = 0;
827 for (Node<E> p = first; p != null; p = p.next)
828 a[k++] = (T)p.item;
829 if (a.length > k)
830 a[k] = null;
831 return a;
832 } finally {
833 lock.unlock();
834 }
835 }
836
837 public String toString() {
838 lock.lock();
839 try {
840 return super.toString();
841 } finally {
842 lock.unlock();
843 }
844 }
845
846 /**
847 * Atomically removes all of the elements from this deque.
848 * The deque will be empty after this call returns.
849 */
850 public void clear() {
851 lock.lock();
852 try {
853 first = last = null;
854 count = 0;
855 notFull.signalAll();
856 } finally {
857 lock.unlock();
858 }
859 }
860
861 /**
862 * Returns an iterator over the elements in this deque in proper sequence.
863 * The elements will be returned in order from first (head) to last (tail).
864 * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
865 * will never throw {@link ConcurrentModificationException},
866 * and guarantees to traverse elements as they existed upon
867 * construction of the iterator, and may (but is not guaranteed to)
868 * reflect any modifications subsequent to construction.
869 *
870 * @return an iterator over the elements in this deque in proper sequence
871 */
872 public Iterator<E> iterator() {
873 return new Itr();
874 }
875
876 /**
877 * Iterator for LinkedBlockingDeque
878 */
879 private class Itr implements Iterator<E> {
880 private Node<E> next;
881
882 /**
883 * nextItem holds on to item fields because once we claim that
884 * an element exists in hasNext(), we must return item read
885 * under lock (in advance()) even if it was in the process of
886 * being removed when hasNext() was called.
887 */
888 private E nextItem;
889
890 /**
891 * Node returned by most recent call to next. Needed by remove.
892 * Reset to null if this element is deleted by a call to remove.
893 */
894 private Node<E> last;
895
896 Itr() {
897 advance();
898 }
899
900 /**
901 * Advances next, or if not yet initialized, sets to first node.
902 */
903 private void advance() {
904 final ReentrantLock lock = LinkedBlockingDeque.this.lock;
905 lock.lock();
906 try {
907 next = (next == null)? first : next.next;
908 nextItem = (next == null)? null : next.item;
909 } finally {
910 lock.unlock();
911 }
912 }
913
914 public boolean hasNext() {
915 return next != null;
916 }
917
918 public E next() {
919 if (next == null)
920 throw new NoSuchElementException();
921 last = next;
922 E x = nextItem;
923 advance();
924 return x;
925 }
926
927 public void remove() {
928 Node<E> n = last;
929 if (n == null)
930 throw new IllegalStateException();
931 last = null;
932 // Note: removeNode rescans looking for this node to make
933 // sure it was not already removed. Otherwise, trying to
934 // re-remove could corrupt list.
935 removeNode(n);
936 }
937 }
938
939 /**
940 * Save the state of this deque to a stream (that is, serialize it).
941 *
942 * @serialData The capacity (int), followed by elements (each an
943 * <tt>Object</tt>) in the proper order, followed by a null
944 * @param s the stream
945 */
946 private void writeObject(java.io.ObjectOutputStream s)
947 throws java.io.IOException {
948 lock.lock();
949 try {
950 // Write out capacity and any hidden stuff
951 s.defaultWriteObject();
952 // Write out all elements in the proper order.
953 for (Node<E> p = first; p != null; p = p.next)
954 s.writeObject(p.item);
955 // Use trailing null as sentinel
956 s.writeObject(null);
957 } finally {
958 lock.unlock();
959 }
960 }
961
962 /**
963 * Reconstitute this deque from a stream (that is,
964 * deserialize it).
965 * @param s the stream
966 */
967 private void readObject(java.io.ObjectInputStream s)
968 throws java.io.IOException, ClassNotFoundException {
969 s.defaultReadObject();
970 count = 0;
971 first = null;
972 last = null;
973 // Read in all elements and place in queue
974 for (;;) {
975 E item = (E)s.readObject();
976 if (item == null)
977 break;
978 add(item);
979 }
980 }
981
982 }