Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8354060

LinkedBlockingDeque.clear() should preserve weakly-consistent iterators

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      LinkedBlockingDeque.clear() should preserve weakly-consistent iterators by linking f.prev and f.next back to f, allowing the iterators to continue from the first or last respectively. This would be consistent with how the other node-based weakly consistent queues LinkedBlockingQueue LinkedTransferQueue, ConcurrentLinkedQueue/Deque work.

      The LBD already supports self-linking, since that is done by the unlinkFirst() and unlinkLast() methods, and the iterators and spliterator thus all support self-linking.

      This can be fixed very easily by linking both f.prev and f.next back to f.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the test code below. Ideally we would want the LinkedBlockingDeque to behave the same as the other concurrent node-based queues. Note that the results for LinkedBlockingDeque are different in the output below.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Testing LinkedBlockingQueue
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      80
      90
      100
      while(poll() != null) and add()
      1
      2
      3
      80
      90
      100

      Testing LinkedTransferQueue
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      80
      90
      100
      while(poll() != null) and add()
      1
      2
      3
      80
      90
      100

      Testing ConcurrentLinkedQueue
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      80
      90
      100
      while(poll() != null) and add()
      1
      2
      3
      80
      90
      100

      Testing ConcurrentLinkedDeque
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      80
      90
      100
      while(poll() != null) and add()
      1
      2
      3
      80
      90
      100

      Testing LinkedBlockingDeque
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      80
      90
      100
      while(poll() != null) and add()
      1
      2
      3
      80
      90
      100

      Testing ArrayBlockingQueue
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      while(poll() != null) and add()
      1
      2
      3

      ACTUAL -
      Testing LinkedBlockingQueue
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      80
      90
      100
      while(poll() != null) and add()
      1
      2
      3
      80
      90
      100

      Testing LinkedTransferQueue
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      80
      90
      100
      while(poll() != null) and add()
      1
      2
      3
      80
      90
      100

      Testing ConcurrentLinkedQueue
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      80
      90
      100
      while(poll() != null) and add()
      1
      2
      3
      80
      90
      100

      Testing ConcurrentLinkedDeque
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      80
      90
      100
      while(poll() != null) and add()
      1
      2
      3
      80
      90
      100

      Testing LinkedBlockingDeque
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      while(poll() != null) and add()
      1
      2
      3
      80
      90
      100

      Testing ArrayBlockingQueue
      clear()
      1
      2
      3
      false
      clear() and add()
      1
      2
      3
      while(poll() != null) and add()
      1
      2
      3


      ---------- BEGIN SOURCE ----------
      import java.util.*;
      import java.util.concurrent.*;

      public class UnlinkingNodesAndWeaklyConsistent {
          public static void main(String... args) {
              test(new LinkedBlockingQueue<Integer>());
              test(new LinkedTransferQueue<Integer>());
              test(new ConcurrentLinkedQueue<Integer>());
              test(new ConcurrentLinkedDeque<Integer>());
              test(new LinkedBlockingDeque<Integer>()); // does not work in its current form
              test(new ArrayBlockingQueue<Integer>(20)); // never continues output after clear()
          }

          private static void test(Queue<Integer> q) {
              System.out.println("Testing " + q.getClass().getSimpleName());
              Collections.addAll(q, 1, 2, 3, 4, 5, 6);

              System.out.println("clear()");
              Iterator<Integer> it = q.iterator();
              System.out.println(it.next()); // 1
              System.out.println(it.next()); // 2
              q.clear();
              System.out.println(it.next()); // 3 - cached
              System.out.println(it.hasNext()); // false

              System.out.println("clear() and add()");
              Collections.addAll(q, 1, 2, 3, 4, 5, 6);
              it = q.iterator();
              System.out.println(it.next()); // 1
              System.out.println(it.next()); // 2
              q.clear();
              q.add(80);
              q.add(90);
              q.add(100);
              // preferred output: 3, 80, 90, 100
              while (it.hasNext()) {
                  System.out.println(it.next());
              }
              q.clear();

              System.out.println("while(poll() != null) and add()");
              Collections.addAll(q, 1, 2, 3, 4, 5, 6);
              it = q.iterator();
              System.out.println(it.next()); // 1
              System.out.println(it.next()); // 2
              while (q.poll() != null) ;
              q.add(80);
              q.add(90);
              q.add(100);
              // preferred output: 3, 80, 90, 100
              while (it.hasNext()) {
                  System.out.println(it.next());
              }

              System.out.println();
          }
      }

      ---------- END SOURCE ----------

            vklang Viktor Klang
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: