OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [external/] [jsr166/] [java/] [util/] [concurrent/] [LinkedBlockingDeque.java] - Blame information for rev 768

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 768 jeremybenn
/*
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
        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
        long nanos = unit.toNanos(timeout);
303
        lock.lockInterruptibly();
304
        try {
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
        long nanos = unit.toNanos(timeout);
325
        lock.lockInterruptibly();
326
        try {
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
        long nanos = unit.toNanos(timeout);
402
        lock.lockInterruptibly();
403
        try {
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
        long nanos = unit.toNanos(timeout);
420
        lock.lockInterruptibly();
421
        try {
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}.
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
     * Returns an iterator over the elements in this deque in reverse
878
     * sequential order.  The elements will be returned in order from
879
     * last (tail) to first (head).
880
     * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
881
     * will never throw {@link ConcurrentModificationException},
882
     * and guarantees to traverse elements as they existed upon
883
     * construction of the iterator, and may (but is not guaranteed to)
884
     * reflect any modifications subsequent to construction.
885
     */
886
    public Iterator<E> descendingIterator() {
887
        return new DescendingItr();
888
    }
889
 
890
    /**
891
     * Base class for Iterators for LinkedBlockingDeque
892
     */
893
    private abstract class AbstractItr implements Iterator<E> {
894
        /**
895
         * The next node to return in next
896
         */
897
         Node<E> next;
898
 
899
        /**
900
         * nextItem holds on to item fields because once we claim that
901
         * an element exists in hasNext(), we must return item read
902
         * under lock (in advance()) even if it was in the process of
903
         * being removed when hasNext() was called.
904
         */
905
        E nextItem;
906
 
907
        /**
908
         * Node returned by most recent call to next. Needed by remove.
909
         * Reset to null if this element is deleted by a call to remove.
910
         */
911
        private Node<E> lastRet;
912
 
913
        AbstractItr() {
914
            advance(); // set to initial position
915
        }
916
 
917
        /**
918
         * Advances next, or if not yet initialized, sets to first node.
919
         * Implemented to move forward vs backward in the two subclasses.
920
         */
921
        abstract void advance();
922
 
923
        public boolean hasNext() {
924
            return next != null;
925
        }
926
 
927
        public E next() {
928
            if (next == null)
929
                throw new NoSuchElementException();
930
            lastRet = next;
931
            E x = nextItem;
932
            advance();
933
            return x;
934
        }
935
 
936
        public void remove() {
937
            Node<E> n = lastRet;
938
            if (n == null)
939
                throw new IllegalStateException();
940
            lastRet = null;
941
            // Note: removeNode rescans looking for this node to make
942
            // sure it was not already removed. Otherwise, trying to
943
            // re-remove could corrupt list.
944
            removeNode(n);
945
        }
946
    }
947
 
948
    /** Forward iterator */
949
    private class Itr extends AbstractItr {
950
        void advance() {
951
            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
952
            lock.lock();
953
            try {
954
                next = (next == null)? first : next.next;
955
                nextItem = (next == null)? null : next.item;
956
            } finally {
957
                lock.unlock();
958
            }
959
        }
960
    }
961
 
962
    /**
963
     * Descending iterator for LinkedBlockingDeque
964
     */
965
    private class DescendingItr extends AbstractItr {
966
        void advance() {
967
            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
968
            lock.lock();
969
            try {
970
                next = (next == null)? last : next.prev;
971
                nextItem = (next == null)? null : next.item;
972
            } finally {
973
                lock.unlock();
974
            }
975
        }
976
    }
977
 
978
    /**
979
     * Save the state of this deque to a stream (that is, serialize it).
980
     *
981
     * @serialData The capacity (int), followed by elements (each an
982
     * <tt>Object</tt>) in the proper order, followed by a null
983
     * @param s the stream
984
     */
985
    private void writeObject(java.io.ObjectOutputStream s)
986
        throws java.io.IOException {
987
        lock.lock();
988
        try {
989
            // Write out capacity and any hidden stuff
990
            s.defaultWriteObject();
991
            // Write out all elements in the proper order.
992
            for (Node<E> p = first; p != null; p = p.next)
993
                s.writeObject(p.item);
994
            // Use trailing null as sentinel
995
            s.writeObject(null);
996
        } finally {
997
            lock.unlock();
998
        }
999
    }
1000
 
1001
    /**
1002
     * Reconstitute this deque from a stream (that is,
1003
     * deserialize it).
1004
     * @param s the stream
1005
     */
1006
    private void readObject(java.io.ObjectInputStream s)
1007
        throws java.io.IOException, ClassNotFoundException {
1008
        s.defaultReadObject();
1009
        count = 0;
1010
        first = null;
1011
        last = null;
1012
        // Read in all elements and place in queue
1013
        for (;;) {
1014
            E item = (E)s.readObject();
1015
            if (item == null)
1016
                break;
1017
            add(item);
1018
        }
1019
    }
1020
 
1021
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.