--- old/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java Mon Nov 8 13:53:28 2010 +++ new/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java Mon Nov 8 13:53:27 2010 @@ -126,10 +126,8 @@ */ Node next; - Node(E x, Node p, Node n) { + Node(E x) { item = x; - prev = p; - next = n; } } @@ -199,7 +197,7 @@ for (E e : c) { if (e == null) throw new NullPointerException(); - if (!linkLast(e)) + if (!linkLast(new Node(e))) throw new IllegalStateException("Deque full"); } } finally { @@ -211,19 +209,19 @@ // Basic linking and unlinking operations, called only while holding lock /** - * Links e as first element, or returns false if full. + * Links node as first element, or returns false if full. */ - private boolean linkFirst(E e) { + private boolean linkFirst(Node node) { // assert lock.isHeldByCurrentThread(); if (count >= capacity) return false; Node f = first; - Node x = new Node(e, null, f); - first = x; + node.next = f; + first = node; if (last == null) - last = x; + last = node; else - f.prev = x; + f.prev = node; ++count; notEmpty.signal(); return true; @@ -230,19 +228,19 @@ } /** - * Links e as last element, or returns false if full. + * Links node as last element, or returns false if full. */ - private boolean linkLast(E e) { + private boolean linkLast(Node node) { // assert lock.isHeldByCurrentThread(); if (count >= capacity) return false; Node l = last; - Node x = new Node(e, l, null); - last = x; + node.prev = l; + last = node; if (first == null) - first = x; + first = node; else - l.next = x; + l.next = node; ++count; notEmpty.signal(); return true; @@ -339,10 +337,11 @@ */ public boolean offerFirst(E e) { if (e == null) throw new NullPointerException(); + Node node = new Node(e); final ReentrantLock lock = this.lock; lock.lock(); try { - return linkFirst(e); + return linkFirst(node); } finally { lock.unlock(); } @@ -353,10 +352,11 @@ */ public boolean offerLast(E e) { if (e == null) throw new NullPointerException(); + Node node = new Node(e); final ReentrantLock lock = this.lock; lock.lock(); try { - return linkLast(e); + return linkLast(node); } finally { lock.unlock(); } @@ -368,10 +368,11 @@ */ public void putFirst(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); + Node node = new Node(e); final ReentrantLock lock = this.lock; lock.lock(); try { - while (!linkFirst(e)) + while (!linkFirst(node)) notFull.await(); } finally { lock.unlock(); @@ -384,10 +385,11 @@ */ public void putLast(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); + Node node = new Node(e); final ReentrantLock lock = this.lock; lock.lock(); try { - while (!linkLast(e)) + while (!linkLast(node)) notFull.await(); } finally { lock.unlock(); @@ -401,11 +403,12 @@ public boolean offerFirst(E e, long timeout, TimeUnit unit) throws InterruptedException { if (e == null) throw new NullPointerException(); + Node node = new Node(e); long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - while (!linkFirst(e)) { + while (!linkFirst(node)) { if (nanos <= 0) return false; nanos = notFull.awaitNanos(nanos); @@ -423,11 +426,12 @@ public boolean offerLast(E e, long timeout, TimeUnit unit) throws InterruptedException { if (e == null) throw new NullPointerException(); + Node node = new Node(e); long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - while (!linkLast(e)) { + while (!linkLast(node)) { if (nanos <= 0) return false; nanos = notFull.awaitNanos(nanos); @@ -955,7 +959,20 @@ final ReentrantLock lock = this.lock; lock.lock(); try { - return super.toString(); + Node p = first; + if (p == null) + return "[]"; + + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (;;) { + E e = p.item; + sb.append(e == this ? "(this Collection)" : e); + p = p.next; + if (p == null) + return sb.append(']').toString(); + sb.append(',').append(' '); + } } finally { lock.unlock(); } @@ -1054,6 +1071,26 @@ } /** + * Returns the successor node of the given non-null, but + * possibly previously deleted, node. + */ + private Node succ(Node n) { + // Chains of deleted nodes ending in null or self-links + // are possible if multiple interior nodes are removed. + for (;;) { + Node s = nextNode(n); + if (s == null) + return null; + else if (s.item != null) + return s; + else if (s == n) + return firstNode(); + else + n = s; + } + } + + /** * Advances next. */ void advance() { @@ -1061,16 +1098,7 @@ lock.lock(); try { // assert next != null; - Node s = nextNode(next); - if (s == next) { - next = firstNode(); - } else { - // Skip over removed nodes. - // May be necessary if multiple interior Nodes are removed. - while (s != null && s.item == null) - s = nextNode(s); - next = s; - } + next = succ(next); nextItem = (next == null) ? null : next.item; } finally { lock.unlock();