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

Comparing jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java (file contents):
Revision 1.123 by jsr166, Sun Jan 4 09:15:11 2015 UTC vs.
Revision 1.124 by jsr166, Sun Jan 25 20:07:01 2015 UTC

# Line 28 | Line 28 | import java.util.NoSuchElementException;
28   import java.util.RandomAccess;
29   import java.util.Spliterator;
30   import java.util.Spliterators;
31 import java.util.concurrent.locks.ReentrantLock;
31   import java.util.function.Consumer;
32   import java.util.function.Predicate;
33   import java.util.function.UnaryOperator;
# Line 74 | Line 73 | public class CopyOnWriteArrayList<E>
73      implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
74      private static final long serialVersionUID = 8673264195747942595L;
75  
76 <    /** The lock protecting all mutators */
77 <    final transient ReentrantLock lock = new ReentrantLock();
76 >    /**
77 >     * The lock protecting all mutators.  (We have a mild preference
78 >     * for builtin monitors over ReentrantLock when either will do.)
79 >     */
80 >    final transient Object lock = new Object();
81  
82      /** The array, accessed only via getArray/setArray. */
83      private transient volatile Object[] array;
# Line 384 | Line 386 | public class CopyOnWriteArrayList<E>
386       * @throws IndexOutOfBoundsException {@inheritDoc}
387       */
388      public E set(int index, E element) {
389 <        final ReentrantLock lock = this.lock;
388 <        lock.lock();
389 <        try {
389 >        synchronized (lock) {
390              Object[] elements = getArray();
391              E oldValue = get(elements, index);
392  
# Line 400 | Line 400 | public class CopyOnWriteArrayList<E>
400                  setArray(elements);
401              }
402              return oldValue;
403        } finally {
404            lock.unlock();
403          }
404      }
405  
# Line 412 | Line 410 | public class CopyOnWriteArrayList<E>
410       * @return {@code true} (as specified by {@link Collection#add})
411       */
412      public boolean add(E e) {
413 <        final ReentrantLock lock = this.lock;
416 <        lock.lock();
417 <        try {
413 >        synchronized (lock) {
414              Object[] elements = getArray();
415              int len = elements.length;
416              Object[] newElements = Arrays.copyOf(elements, len + 1);
417              newElements[len] = e;
418              setArray(newElements);
419              return true;
424        } finally {
425            lock.unlock();
420          }
421      }
422  
# Line 434 | Line 428 | public class CopyOnWriteArrayList<E>
428       * @throws IndexOutOfBoundsException {@inheritDoc}
429       */
430      public void add(int index, E element) {
431 <        final ReentrantLock lock = this.lock;
438 <        lock.lock();
439 <        try {
431 >        synchronized (lock) {
432              Object[] elements = getArray();
433              int len = elements.length;
434              if (index > len || index < 0)
# Line 454 | Line 446 | public class CopyOnWriteArrayList<E>
446              }
447              newElements[index] = element;
448              setArray(newElements);
457        } finally {
458            lock.unlock();
449          }
450      }
451  
# Line 467 | Line 457 | public class CopyOnWriteArrayList<E>
457       * @throws IndexOutOfBoundsException {@inheritDoc}
458       */
459      public E remove(int index) {
460 <        final ReentrantLock lock = this.lock;
471 <        lock.lock();
472 <        try {
460 >        synchronized (lock) {
461              Object[] elements = getArray();
462              int len = elements.length;
463              E oldValue = get(elements, index);
# Line 484 | Line 472 | public class CopyOnWriteArrayList<E>
472                  setArray(newElements);
473              }
474              return oldValue;
487        } finally {
488            lock.unlock();
475          }
476      }
477  
# Line 512 | Line 498 | public class CopyOnWriteArrayList<E>
498       * recent snapshot contains o at the given index.
499       */
500      private boolean remove(Object o, Object[] snapshot, int index) {
501 <        final ReentrantLock lock = this.lock;
516 <        lock.lock();
517 <        try {
501 >        synchronized (lock) {
502              Object[] current = getArray();
503              int len = current.length;
504              if (snapshot != current) findIndex: {
# Line 540 | Line 524 | public class CopyOnWriteArrayList<E>
524                               len - index - 1);
525              setArray(newElements);
526              return true;
543        } finally {
544            lock.unlock();
527          }
528      }
529  
# Line 558 | Line 540 | public class CopyOnWriteArrayList<E>
540       *         ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
541       */
542      void removeRange(int fromIndex, int toIndex) {
543 <        final ReentrantLock lock = this.lock;
562 <        lock.lock();
563 <        try {
543 >        synchronized (lock) {
544              Object[] elements = getArray();
545              int len = elements.length;
546  
# Line 577 | Line 557 | public class CopyOnWriteArrayList<E>
557                                   fromIndex, numMoved);
558                  setArray(newElements);
559              }
580        } finally {
581            lock.unlock();
560          }
561      }
562  
# Line 599 | Line 577 | public class CopyOnWriteArrayList<E>
577       * recent snapshot does not contain e.
578       */
579      private boolean addIfAbsent(E e, Object[] snapshot) {
580 <        final ReentrantLock lock = this.lock;
603 <        lock.lock();
604 <        try {
580 >        synchronized (lock) {
581              Object[] current = getArray();
582              int len = current.length;
583              if (snapshot != current) {
# Line 617 | Line 593 | public class CopyOnWriteArrayList<E>
593              newElements[len] = e;
594              setArray(newElements);
595              return true;
620        } finally {
621            lock.unlock();
596          }
597      }
598  
# Line 660 | Line 634 | public class CopyOnWriteArrayList<E>
634       */
635      public boolean removeAll(Collection<?> c) {
636          if (c == null) throw new NullPointerException();
637 <        final ReentrantLock lock = this.lock;
664 <        lock.lock();
665 <        try {
637 >        synchronized (lock) {
638              Object[] elements = getArray();
639              int len = elements.length;
640              if (len != 0) {
# Line 680 | Line 652 | public class CopyOnWriteArrayList<E>
652                  }
653              }
654              return false;
683        } finally {
684            lock.unlock();
655          }
656      }
657  
# Line 703 | Line 673 | public class CopyOnWriteArrayList<E>
673       */
674      public boolean retainAll(Collection<?> c) {
675          if (c == null) throw new NullPointerException();
676 <        final ReentrantLock lock = this.lock;
707 <        lock.lock();
708 <        try {
676 >        synchronized (lock) {
677              Object[] elements = getArray();
678              int len = elements.length;
679              if (len != 0) {
# Line 723 | Line 691 | public class CopyOnWriteArrayList<E>
691                  }
692              }
693              return false;
726        } finally {
727            lock.unlock();
694          }
695      }
696  
# Line 743 | Line 709 | public class CopyOnWriteArrayList<E>
709          Object[] cs = c.toArray();
710          if (cs.length == 0)
711              return 0;
712 <        final ReentrantLock lock = this.lock;
747 <        lock.lock();
748 <        try {
712 >        synchronized (lock) {
713              Object[] elements = getArray();
714              int len = elements.length;
715              int added = 0;
# Line 762 | Line 726 | public class CopyOnWriteArrayList<E>
726                  setArray(newElements);
727              }
728              return added;
765        } finally {
766            lock.unlock();
729          }
730      }
731  
# Line 772 | Line 734 | public class CopyOnWriteArrayList<E>
734       * The list will be empty after this call returns.
735       */
736      public void clear() {
737 <        final ReentrantLock lock = this.lock;
776 <        lock.lock();
777 <        try {
737 >        synchronized (lock) {
738              setArray(new Object[0]);
779        } finally {
780            lock.unlock();
739          }
740      }
741  
# Line 796 | Line 754 | public class CopyOnWriteArrayList<E>
754              ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();
755          if (cs.length == 0)
756              return false;
757 <        final ReentrantLock lock = this.lock;
800 <        lock.lock();
801 <        try {
757 >        synchronized (lock) {
758              Object[] elements = getArray();
759              int len = elements.length;
760              if (len == 0 && cs.getClass() == Object[].class)
# Line 809 | Line 765 | public class CopyOnWriteArrayList<E>
765                  setArray(newElements);
766              }
767              return true;
812        } finally {
813            lock.unlock();
768          }
769      }
770  
# Line 832 | Line 786 | public class CopyOnWriteArrayList<E>
786       */
787      public boolean addAll(int index, Collection<? extends E> c) {
788          Object[] cs = c.toArray();
789 <        final ReentrantLock lock = this.lock;
836 <        lock.lock();
837 <        try {
789 >        synchronized (lock) {
790              Object[] elements = getArray();
791              int len = elements.length;
792              if (index > len || index < 0)
# Line 856 | Line 808 | public class CopyOnWriteArrayList<E>
808              System.arraycopy(cs, 0, newElements, index, cs.length);
809              setArray(newElements);
810              return true;
859        } finally {
860            lock.unlock();
811          }
812      }
813  
# Line 873 | Line 823 | public class CopyOnWriteArrayList<E>
823  
824      public boolean removeIf(Predicate<? super E> filter) {
825          if (filter == null) throw new NullPointerException();
826 <        final ReentrantLock lock = this.lock;
877 <        lock.lock();
878 <        try {
826 >        synchronized (lock) {
827              Object[] elements = getArray();
828              int len = elements.length;
829              if (len != 0) {
# Line 892 | Line 840 | public class CopyOnWriteArrayList<E>
840                  }
841              }
842              return false;
895        } finally {
896            lock.unlock();
843          }
844      }
845  
846      public void replaceAll(UnaryOperator<E> operator) {
847          if (operator == null) throw new NullPointerException();
848 <        final ReentrantLock lock = this.lock;
903 <        lock.lock();
904 <        try {
848 >        synchronized (lock) {
849              Object[] elements = getArray();
850              int len = elements.length;
851              Object[] newElements = Arrays.copyOf(elements, len);
# Line 910 | Line 854 | public class CopyOnWriteArrayList<E>
854                  newElements[i] = operator.apply(e);
855              }
856              setArray(newElements);
913        } finally {
914            lock.unlock();
857          }
858      }
859  
860      public void sort(Comparator<? super E> c) {
861 <        final ReentrantLock lock = this.lock;
920 <        lock.lock();
921 <        try {
861 >        synchronized (lock) {
862              Object[] elements = getArray();
863              Object[] newElements = Arrays.copyOf(elements, elements.length);
864              @SuppressWarnings("unchecked") E[] es = (E[])newElements;
865              Arrays.sort(es, c);
866              setArray(newElements);
927        } finally {
928            lock.unlock();
867          }
868      }
869  
# Line 1192 | Line 1130 | public class CopyOnWriteArrayList<E>
1130       * @throws IndexOutOfBoundsException {@inheritDoc}
1131       */
1132      public List<E> subList(int fromIndex, int toIndex) {
1133 <        final ReentrantLock lock = this.lock;
1196 <        lock.lock();
1197 <        try {
1133 >        synchronized (lock) {
1134              Object[] elements = getArray();
1135              int len = elements.length;
1136              if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
1137                  throw new IndexOutOfBoundsException();
1138              return new COWSubList<E>(this, fromIndex, toIndex);
1203        } finally {
1204            lock.unlock();
1139          }
1140      }
1141  
# Line 1232 | Line 1166 | public class CopyOnWriteArrayList<E>
1166          // only call this holding l's lock
1167          COWSubList(CopyOnWriteArrayList<E> list,
1168                     int fromIndex, int toIndex) {
1169 +            // assert Thread.holdsLock(list.lock);
1170              l = list;
1171              expectedArray = l.getArray();
1172              offset = fromIndex;
# Line 1240 | Line 1175 | public class CopyOnWriteArrayList<E>
1175  
1176          // only call this holding l's lock
1177          private void checkForComodification() {
1178 +            // assert Thread.holdsLock(l.lock);
1179              if (l.getArray() != expectedArray)
1180                  throw new ConcurrentModificationException();
1181          }
1182  
1183          // only call this holding l's lock
1184          private void rangeCheck(int index) {
1185 +            // assert Thread.holdsLock(l.lock);
1186              if (index < 0 || index >= size)
1187                  throw new IndexOutOfBoundsException("Index: "+index+
1188                                                      ",Size: "+size);
1189          }
1190  
1191          public E set(int index, E element) {
1192 <            final ReentrantLock lock = l.lock;
1256 <            lock.lock();
1257 <            try {
1192 >            synchronized (l.lock) {
1193                  rangeCheck(index);
1194                  checkForComodification();
1195                  E x = l.set(index+offset, element);
1196                  expectedArray = l.getArray();
1197                  return x;
1263            } finally {
1264                lock.unlock();
1198              }
1199          }
1200  
1201          public E get(int index) {
1202 <            final ReentrantLock lock = l.lock;
1270 <            lock.lock();
1271 <            try {
1202 >            synchronized (l.lock) {
1203                  rangeCheck(index);
1204                  checkForComodification();
1205                  return l.get(index+offset);
1275            } finally {
1276                lock.unlock();
1206              }
1207          }
1208  
1209          public int size() {
1210 <            final ReentrantLock lock = l.lock;
1282 <            lock.lock();
1283 <            try {
1210 >            synchronized (l.lock) {
1211                  checkForComodification();
1212                  return size;
1286            } finally {
1287                lock.unlock();
1213              }
1214          }
1215  
1216          public void add(int index, E element) {
1217 <            final ReentrantLock lock = l.lock;
1293 <            lock.lock();
1294 <            try {
1217 >            synchronized (l.lock) {
1218                  checkForComodification();
1219                  if (index < 0 || index > size)
1220                      throw new IndexOutOfBoundsException();
1221                  l.add(index+offset, element);
1222                  expectedArray = l.getArray();
1223                  size++;
1301            } finally {
1302                lock.unlock();
1224              }
1225          }
1226  
1227          public void clear() {
1228 <            final ReentrantLock lock = l.lock;
1308 <            lock.lock();
1309 <            try {
1228 >            synchronized (l.lock) {
1229                  checkForComodification();
1230                  l.removeRange(offset, offset+size);
1231                  expectedArray = l.getArray();
1232                  size = 0;
1314            } finally {
1315                lock.unlock();
1233              }
1234          }
1235  
1236          public E remove(int index) {
1237 <            final ReentrantLock lock = l.lock;
1321 <            lock.lock();
1322 <            try {
1237 >            synchronized (l.lock) {
1238                  rangeCheck(index);
1239                  checkForComodification();
1240                  E result = l.remove(index+offset);
1241                  expectedArray = l.getArray();
1242                  size--;
1243                  return result;
1329            } finally {
1330                lock.unlock();
1244              }
1245          }
1246  
# Line 1340 | Line 1253 | public class CopyOnWriteArrayList<E>
1253          }
1254  
1255          public Iterator<E> iterator() {
1256 <            final ReentrantLock lock = l.lock;
1344 <            lock.lock();
1345 <            try {
1256 >            synchronized (l.lock) {
1257                  checkForComodification();
1258                  return new COWSubListIterator<E>(l, 0, offset, size);
1348            } finally {
1349                lock.unlock();
1259              }
1260          }
1261  
1262          public ListIterator<E> listIterator(int index) {
1263 <            final ReentrantLock lock = l.lock;
1355 <            lock.lock();
1356 <            try {
1263 >            synchronized (l.lock) {
1264                  checkForComodification();
1265                  if (index < 0 || index > size)
1266                      throw new IndexOutOfBoundsException("Index: "+index+
1267                                                          ", Size: "+size);
1268                  return new COWSubListIterator<E>(l, index, offset, size);
1362            } finally {
1363                lock.unlock();
1269              }
1270          }
1271  
1272          public List<E> subList(int fromIndex, int toIndex) {
1273 <            final ReentrantLock lock = l.lock;
1369 <            lock.lock();
1370 <            try {
1273 >            synchronized (l.lock) {
1274                  checkForComodification();
1275                  if (fromIndex < 0 || toIndex > size || fromIndex > toIndex)
1276                      throw new IndexOutOfBoundsException();
1277                  return new COWSubList<E>(l, fromIndex + offset,
1278                                           toIndex + offset);
1376            } finally {
1377                lock.unlock();
1279              }
1280          }
1281  
# Line 1395 | Line 1296 | public class CopyOnWriteArrayList<E>
1296  
1297          public void replaceAll(UnaryOperator<E> operator) {
1298              if (operator == null) throw new NullPointerException();
1299 <            final ReentrantLock lock = l.lock;
1399 <            lock.lock();
1400 <            try {
1299 >            synchronized (l.lock) {
1300                  int lo = offset;
1301                  int hi = offset + size;
1302                  Object[] elements = expectedArray;
# Line 1412 | Line 1311 | public class CopyOnWriteArrayList<E>
1311                      newElements[i] = operator.apply(e);
1312                  }
1313                  l.setArray(expectedArray = newElements);
1415            } finally {
1416                lock.unlock();
1314              }
1315          }
1316  
1317          public void sort(Comparator<? super E> c) {
1318 <            final ReentrantLock lock = l.lock;
1422 <            lock.lock();
1423 <            try {
1318 >            synchronized (l.lock) {
1319                  int lo = offset;
1320                  int hi = offset + size;
1321                  Object[] elements = expectedArray;
# Line 1433 | Line 1328 | public class CopyOnWriteArrayList<E>
1328                  @SuppressWarnings("unchecked") E[] es = (E[])newElements;
1329                  Arrays.sort(es, lo, hi, c);
1330                  l.setArray(expectedArray = newElements);
1436            } finally {
1437                lock.unlock();
1331              }
1332          }
1333  
1334          public boolean removeAll(Collection<?> c) {
1335              if (c == null) throw new NullPointerException();
1336              boolean removed = false;
1337 <            final ReentrantLock lock = l.lock;
1445 <            lock.lock();
1446 <            try {
1337 >            synchronized (l.lock) {
1338                  int n = size;
1339                  if (n > 0) {
1340                      int lo = offset;
# Line 1472 | Line 1363 | public class CopyOnWriteArrayList<E>
1363                          l.setArray(expectedArray = newElements);
1364                      }
1365                  }
1475            } finally {
1476                lock.unlock();
1366              }
1367              return removed;
1368          }
# Line 1481 | Line 1370 | public class CopyOnWriteArrayList<E>
1370          public boolean retainAll(Collection<?> c) {
1371              if (c == null) throw new NullPointerException();
1372              boolean removed = false;
1373 <            final ReentrantLock lock = l.lock;
1485 <            lock.lock();
1486 <            try {
1373 >            synchronized (l.lock) {
1374                  int n = size;
1375                  if (n > 0) {
1376                      int lo = offset;
# Line 1512 | Line 1399 | public class CopyOnWriteArrayList<E>
1399                          l.setArray(expectedArray = newElements);
1400                      }
1401                  }
1515            } finally {
1516                lock.unlock();
1402              }
1403              return removed;
1404          }
# Line 1521 | Line 1406 | public class CopyOnWriteArrayList<E>
1406          public boolean removeIf(Predicate<? super E> filter) {
1407              if (filter == null) throw new NullPointerException();
1408              boolean removed = false;
1409 <            final ReentrantLock lock = l.lock;
1525 <            lock.lock();
1526 <            try {
1409 >            synchronized (l.lock) {
1410                  int n = size;
1411                  if (n > 0) {
1412                      int lo = offset;
# Line 1552 | Line 1435 | public class CopyOnWriteArrayList<E>
1435                          l.setArray(expectedArray = newElements);
1436                      }
1437                  }
1555            } finally {
1556                lock.unlock();
1438              }
1439              return removed;
1440          }
# Line 1628 | Line 1509 | public class CopyOnWriteArrayList<E>
1509  
1510      // Support for resetting lock while deserializing
1511      private void resetLock() {
1512 <        U.putObjectVolatile(this, LOCK, new ReentrantLock());
1512 >        U.putObjectVolatile(this, LOCK, new Object());
1513      }
1514      private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
1515      private static final long LOCK;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines