You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sc...@apache.org on 2004/06/23 23:41:49 UTC

cvs commit: jakarta-commons/collections/src/test/org/apache/commons/collections TestFastArrayList1.java

scolebourne    2004/06/23 14:41:49

  Modified:    collections/src/java/org/apache/commons/collections
                        FastArrayList.java
               collections/src/test/org/apache/commons/collections
                        TestFastArrayList1.java
  Log:
  Fix FastArrayList iterator to work in thread-safe environments
  
  Revision  Changes    Path
  1.16      +46 -17    jakarta-commons/collections/src/java/org/apache/commons/collections/FastArrayList.java
  
  Index: FastArrayList.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/FastArrayList.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- FastArrayList.java	18 Feb 2004 01:15:42 -0000	1.15
  +++ FastArrayList.java	23 Jun 2004 21:41:49 -0000	1.16
  @@ -60,6 +60,7 @@
    * @version $Revision$ $Date$
    * 
    * @author Craig R. McClanahan
  + * @author Stephen Colebourne
    */
   public class FastArrayList extends ArrayList {
   
  @@ -486,12 +487,20 @@
   
       /**
        * Return an iterator over the elements in this list in proper sequence.
  -     * <br><br>
  -     * <strong>IMPLEMENTATION NOTE</strong> - If the list is operating in fast
  -     * mode, an Iterator is returned, and a structural modification to the
  -     * list is made, then the Iterator will continue over the previous contents
  -     * of the list (at the time that the Iterator was created), rather than
  -     * failing due to concurrent modifications.
  +     * <p>
  +     * <b>Thread safety</b><br />
  +     * The iterator returned is thread-safe ONLY in FAST mode.
  +     * In slow mode there is no way to synchronize, or make the iterator thread-safe.
  +     * <p>
  +     * In fast mode iteration and modification may occur in parallel on different threads,
  +     * however there is a restriction. Modification must be EITHER via the Iterator
  +     * interface methods OR the List interface. If a mixture of modification
  +     * methods is used a ConcurrentModificationException is thrown from the iterator
  +     * modification method. If the List modification methods are used the changes are
  +     * NOT visible in the iterator (it shows the list contents at the time the iterator
  +     * was created).
  +     * 
  +     * @return the iterator
        */
       public Iterator iterator() {
           if (fast) {
  @@ -524,7 +533,20 @@
   
       /**
        * Return an iterator of the elements of this list, in proper sequence.
  -     * See the implementation note on <code>iterator()</code>.
  +     * <p>
  +     * <b>Thread safety</b><br />
  +     * The iterator returned is thread-safe ONLY in FAST mode.
  +     * In slow mode there is no way to synchronize, or make the iterator thread-safe.
  +     * <p>
  +     * In fast mode iteration and modification may occur in parallel on different threads,
  +     * however there is a restriction. Modification must be EITHER via the Iterator
  +     * interface methods OR the List interface. If a mixture of modification
  +     * methods is used a ConcurrentModificationException is thrown from the iterator
  +     * modification method. If the List modification methods are used the changes are
  +     * NOT visible in the iterator (it shows the list contents at the time the iterator
  +     * was created).
  +     * 
  +     * @return the list iterator
        */
       public ListIterator listIterator() {
           if (fast) {
  @@ -538,10 +560,21 @@
       /**
        * Return an iterator of the elements of this list, in proper sequence,
        * starting at the specified position.
  -     * See the implementation note on <code>iterator()</code>.
  +     * <p>
  +     * <b>Thread safety</b><br />
  +     * The iterator returned is thread-safe ONLY in FAST mode.
  +     * In slow mode there is no way to synchronize, or make the iterator thread-safe.
  +     * <p>
  +     * In fast mode iteration and modification may occur in parallel on different threads,
  +     * however there is a restriction. Modification must be EITHER via the Iterator
  +     * interface methods OR the List interface. If a mixture of modification
  +     * methods is used a ConcurrentModificationException is thrown from the iterator
  +     * modification method. If the List modification methods are used the changes are
  +     * NOT visible in the iterator (it shows the list contents at the time the iterator
  +     * was created).
        *
        * @param index The starting position of the iterator to return
  -     *
  +     * @return the list iterator
        * @exception IndexOutOfBoundsException if the index is out of range
        */
       public ListIterator listIterator(int index) {
  @@ -1205,8 +1238,9 @@
               int i = nextIndex();
               get().add(i, o);
               last++;
  +            expected = list;
               iter = get().listIterator(i + 1);
  -            lastReturnedIndex = 1;
  +            lastReturnedIndex = -1;
           }
   
      }
  @@ -1239,34 +1273,28 @@
           }
   
           public boolean hasNext() {
  -            checkMod();
               return iter.hasNext();     
           }
   
           public Object next() {
  -            checkMod();
               lastReturnedIndex = iter.nextIndex();
               return iter.next();
           }
   
           public boolean hasPrevious() {
  -            checkMod();
               return iter.hasPrevious();
           }
   
           public Object previous() {
  -            checkMod();
               lastReturnedIndex = iter.previousIndex();
               return iter.previous();
           }
   
           public int previousIndex() {
  -            checkMod();
               return iter.previousIndex();
           }
   
           public int nextIndex() {
  -            checkMod();
               return iter.nextIndex();
           }
   
  @@ -1295,6 +1323,7 @@
               checkMod();
               int i = nextIndex();
               get().add(i, o);
  +            expected = list;
               iter = get().listIterator(i + 1);
               lastReturnedIndex = -1;
           }
  
  
  
  1.10      +50 -8     jakarta-commons/collections/src/test/org/apache/commons/collections/TestFastArrayList1.java
  
  Index: TestFastArrayList1.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/TestFastArrayList1.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- TestFastArrayList1.java	18 Feb 2004 01:20:35 -0000	1.9
  +++ TestFastArrayList1.java	23 Jun 2004 21:41:49 -0000	1.10
  @@ -16,7 +16,10 @@
   package org.apache.commons.collections;
   
   import java.util.ArrayList;
  +import java.util.ConcurrentModificationException;
  +import java.util.Iterator;
   import java.util.List;
  +import java.util.ListIterator;
   
   import junit.framework.Test;
   
  @@ -51,13 +54,52 @@
           fal.setFast(true);
           return (fal);
       }
  -    
  -    public String[] ignoredTests() {
  -        // subList impl result in...
  -        return new String[] {
  -            "TestFastArrayList1.bulkTestSubList.bulkTestListIterator.testAddThenSet",
  -            "TestFastArrayList1.bulkTestSubList.bulkTestListIterator.testAddThenRemove",
  -        };
  +
  +    public void testIterateModify1() {
  +        List list = makeEmptyList();
  +        list.add("A");
  +        list.add("B");
  +        list.add("C");
  +        assertEquals(3, list.size());
  +        
  +        Iterator it = list.iterator();
  +        assertEquals("A", it.next());
  +        assertEquals(3, list.size());
  +        list.add(1, "Z");
  +        assertEquals(4, list.size());
  +        assertEquals("B", it.next());
  +        assertEquals("C", it.next());
  +        assertEquals(false, it.hasNext());
  +    }
  +
  +    public void testIterateModify2() {
  +        List list = makeEmptyList();
  +        list.add("A");
  +        list.add("B");
  +        list.add("C");
  +        assertEquals(3, list.size());
  +        
  +        ListIterator it = list.listIterator();
  +        assertEquals("A", it.next());
  +        it.add("M");  // change via Iterator interface
  +        assertEquals(4, list.size());
  +        list.add(2, "Z");  // change via List interface
  +        assertEquals(5, list.size());
  +        assertEquals("B", it.next());
  +        try {
  +            it.set("N"); // fails as previously changed via List interface
  +            fail();
  +        } catch (ConcurrentModificationException ex) {}
  +        try {
  +            it.remove();
  +            fail();
  +        } catch (ConcurrentModificationException ex) {}
  +        try {
  +            it.add("N");
  +            fail();
  +        } catch (ConcurrentModificationException ex) {}
  +        assertEquals("C", it.next());
  +        assertEquals(false, it.hasNext());
       }
   
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org