ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/ArrayDeque.java
(Generate patch)

Comparing jsr166/src/main/java/util/ArrayDeque.java (file contents):
Revision 1.109 by jsr166, Sat Nov 5 16:21:06 2016 UTC vs.
Revision 1.113 by jsr166, Sun Nov 13 02:10:09 2016 UTC

# Line 317 | Line 317 | public class ArrayDeque<E> extends Abstr
317          final int s = size(), needed;
318          if ((needed = s + c.size() - elements.length + 1) > 0)
319              grow(needed);
320 <        c.forEach((e) -> addLast(e));
320 >        c.forEach(e -> addLast(e));
321          // checkInvariants();
322          return size() > s;
323      }
# Line 469 | Line 469 | public class ArrayDeque<E> extends Abstr
469              final Object[] es = elements;
470              for (int i = tail, end = head, to = (i >= end) ? end : 0;
471                   ; i = es.length, to = end) {
472 <                while (--i >= to)
472 >                for (i--; i > to - 1; i--)
473                      if (o.equals(es[i])) {
474                          delete(i);
475                          return true;
# Line 773 | Line 773 | public class ArrayDeque<E> extends Abstr
773                  throw new ConcurrentModificationException();
774              for (int i = cursor, end = head, to = (i >= end) ? end : 0;
775                   ; i = es.length - 1, to = end) {
776 <                for (; i >= to; i--)
776 >                // hotspot generates faster code than for: i >= to !
777 >                for (; i > to - 1; i--)
778                      action.accept(elementAt(es, i));
779                  if (to == end) {
780                      if (end != head)
781                          throw new ConcurrentModificationException();
782 <                    lastRet = head;
782 >                    lastRet = end;
783                      break;
784                  }
785              }
# Line 949 | Line 950 | public class ArrayDeque<E> extends Abstr
950               ; i = 0, to = end) {
951              for (; i < to; i++)
952                  if (filter.test(elementAt(es, i)))
953 <                    return bulkRemoveModified(filter, i, to);
953 >                    return bulkRemoveModified(filter, i);
954              if (to == end) {
955                  if (end != tail) throw new ConcurrentModificationException();
956                  break;
# Line 958 | Line 959 | public class ArrayDeque<E> extends Abstr
959          return false;
960      }
961  
962 +    // A tiny bit set implementation
963 +
964 +    private static long[] nBits(int n) {
965 +        return new long[((n - 1) >> 6) + 1];
966 +    }
967 +    private static void setBit(long[] bits, int i) {
968 +        bits[i >> 6] |= 1L << i;
969 +    }
970 +    private static boolean isClear(long[] bits, int i) {
971 +        return (bits[i >> 6] & (1L << i)) == 0;
972 +    }
973 +
974      /**
975       * Helper for bulkRemove, in case of at least one deletion.
976 <     * @param i valid index of first element to be deleted
976 >     * Tolerate predicates that reentrantly access the collection for
977 >     * read (but writers still get CME), so traverse once to find
978 >     * elements to delete, a second pass to physically expunge.
979 >     *
980 >     * @param beg valid index of first element to be deleted
981       */
982      private boolean bulkRemoveModified(
983 <        Predicate<? super E> filter, int i, int to) {
983 >        Predicate<? super E> filter, final int beg) {
984          final Object[] es = elements;
985          final int capacity = es.length;
969        // a two-finger algorithm, with hare i reading, tortoise j writing
970        int j = i++;
986          final int end = tail;
987 <        try {
988 <            for (;; j = 0) {    // j rejoins i on second leg
989 <                E e;
990 <                // In this loop, i and j are on the same leg, with i > j
991 <                for (; i < to; i++)
992 <                    if (!filter.test(e = elementAt(es, i)))
993 <                        es[j++] = e;
994 <                if (to == end) break;
995 <                // In this loop, j is on the first leg, i on the second
996 <                for (i = 0, to = end; i < to && j < capacity; i++)
997 <                    if (!filter.test(e = elementAt(es, i)))
998 <                        es[j++] = e;
999 <                if (i >= to) {
1000 <                    if (j == capacity) j = 0; // "corner" case
1001 <                    break;
1002 <                }
987 >        final long[] deathRow = nBits(sub(end, beg, capacity));
988 >        deathRow[0] = 1L;   // set bit 0
989 >        for (int i = beg + 1, to = (i <= end) ? end : es.length, k = beg;
990 >             ; i = 0, to = end, k -= capacity) {
991 >            for (; i < to; i++)
992 >                if (filter.test(elementAt(es, i)))
993 >                    setBit(deathRow, i - k);
994 >            if (to == end) break;
995 >        }
996 >        // a two-finger traversal, with hare i reading, tortoise w writing
997 >        int w = beg;
998 >        for (int i = beg + 1, to = (i <= end) ? end : es.length, k = beg;
999 >             ; w = 0) { // w rejoins i on second leg
1000 >            // In this loop, i and w are on the same leg, with i > w
1001 >            for (; i < to; i++)
1002 >                if (isClear(deathRow, i - k))
1003 >                    es[w++] = es[i];
1004 >            if (to == end) break;
1005 >            // In this loop, w is on the first leg, i on the second
1006 >            for (i = 0, to = end, k -= capacity; i < to && w < capacity; i++)
1007 >                if (isClear(deathRow, i - k))
1008 >                    es[w++] = es[i];
1009 >            if (i >= to) {
1010 >                if (w == capacity) w = 0; // "corner" case
1011 >                break;
1012              }
989            return true;
990        } catch (Throwable ex) {
991            // copy remaining elements
992            for (; i != end; i = inc(i, capacity), j = inc(j, capacity))
993                es[j] = es[i];
994            throw ex;
995        } finally {
996            if (end != tail) throw new ConcurrentModificationException();
997            circularClear(es, tail = j, end);
998            // checkInvariants();
1013          }
1014 +        if (end != tail) throw new ConcurrentModificationException();
1015 +        circularClear(es, tail = w, end);
1016 +        // checkInvariants();
1017 +        return true;
1018      }
1019  
1020      /**

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines