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