Author: scolebourne Date: Sun May 22 12:23:04 2005 New Revision: 171360 URL: http://svn.apache.org/viewcvs?rev=171360&view=rev Log: Simplify code in iterator remove to avoid incorrect ConcurrentModificationException bug 34690, from Guilhem Lavaux at Kaffe
Modified: jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/FastArrayList.java jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/TestFastArrayList.java Modified: jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html?rev=171360&r1=171359&r2=171360&view=diff ============================================================================== --- jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html (original) +++ jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html Sun May 22 12:23:04 2005 @@ -61,6 +61,7 @@ <center><h3>BUG FIXES</h3></center> <ul> <li>FastArrayList - Fix iterators and views to work better in multithreaded environments</li> +<li>FastArrayList - Fix iterator remove where ConcurrentModificationException not as expected [34690]</li> <li>BoundedFifoBuffer/CircularFifoBuffer - Fix serialization to work in case where buffer serialized when full [31433]</li> <li>BoundedFifoBuffer - Fix iterator remove bug causing ArrayIndexOutOfBounds error [33071]</li> <li>MultiHashMap.remove(key, item) - Was returning the item even when nothing was removed [32366]</li> Modified: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/FastArrayList.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/FastArrayList.java?rev=171360&r1=171359&r2=171360&view=diff ============================================================================== --- jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/FastArrayList.java (original) +++ jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/FastArrayList.java Sun May 22 12:23:04 2005 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2004 The Apache Software Foundation + * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1305,7 +1305,7 @@ } get().remove(lastReturnedIndex); expected = list; - iter = get().listIterator(previousIndex()); + iter = get().listIterator(lastReturnedIndex); lastReturnedIndex = -1; } Modified: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/TestFastArrayList.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/TestFastArrayList.java?rev=171360&r1=171359&r2=171360&view=diff ============================================================================== --- jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/TestFastArrayList.java (original) +++ jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/TestFastArrayList.java Sun May 22 12:23:04 2005 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2004 The Apache Software Foundation + * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,9 @@ package org.apache.commons.collections; import java.util.ArrayList; +import java.util.ConcurrentModificationException; import java.util.List; +import java.util.ListIterator; import junit.framework.Test; @@ -50,6 +52,113 @@ FastArrayList fal = new FastArrayList(); fal.setFast(false); return (fal); + } + + public void testConcurrentModification_alwaysFast() { + FastArrayList list = new FastArrayList(); + list.setFast(true); + list.add("a"); + list.add("b"); + list.add("c"); + ListIterator iter = list.listIterator(); + assertEquals("a", iter.next()); + assertEquals("b", iter.next()); + iter.remove(); // checking for no ConcurrentModificationException + assertEquals("c", iter.next()); + assertEquals(false, iter.hasNext()); + assertEquals("c", iter.previous()); + assertEquals("a", iter.previous()); + assertEquals(false, iter.hasPrevious()); + } + + public void testConcurrentModification_alwaysFastModError() { + FastArrayList list = new FastArrayList(); + list.setFast(true); + list.add("a"); + list.add("b"); + list.add("c"); + ListIterator iter = list.listIterator(); + assertEquals("a", iter.next()); + assertEquals("b", iter.next()); + list.remove(1); + try { + iter.remove(); + } catch (ConcurrentModificationException ex) { + // expected + } + // iterator state now invalid + } + + public void testConcurrentModification_delayedFast() { + FastArrayList list = new FastArrayList(); + list.add("a"); + list.add("b"); + list.add("c"); + ListIterator iter = list.listIterator(); + assertEquals("a", iter.next()); + assertEquals("b", iter.next()); + list.setFast(true); + iter.remove(); // checking for no ConcurrentModificationException + assertEquals("c", iter.next()); + assertEquals(false, iter.hasNext()); + assertEquals("c", iter.previous()); + assertEquals("a", iter.previous()); + assertEquals(false, iter.hasPrevious()); + } + + public void testConcurrentModification_delayedFastModError() { + FastArrayList list = new FastArrayList(); + list.add("a"); + list.add("b"); + list.add("c"); + ListIterator iter = list.listIterator(); + assertEquals("a", iter.next()); + assertEquals("b", iter.next()); + list.setFast(true); + list.remove(1); + try { + iter.remove(); + } catch (ConcurrentModificationException ex) { + // expected + } + // iterator state now invalid + } + + public void testConcurrentModification_alwaysFastPrevious() { + FastArrayList list = new FastArrayList(); + list.setFast(true); + list.add("a"); + list.add("b"); + list.add("c"); + ListIterator iter = list.listIterator(); + assertEquals("a", iter.next()); + assertEquals("b", iter.next()); + assertEquals("b", iter.previous()); + iter.remove(); // checking for no ConcurrentModificationException + assertEquals("c", iter.next()); + assertEquals(false, iter.hasNext()); + assertEquals("c", iter.previous()); + assertEquals("a", iter.previous()); + assertEquals(false, iter.hasPrevious()); + } + + public void testConcurrentModification_alwaysFastModErrorPrevious() { + FastArrayList list = new FastArrayList(); + list.setFast(true); + list.add("a"); + list.add("b"); + list.add("c"); + ListIterator iter = list.listIterator(); + assertEquals("a", iter.next()); + assertEquals("b", iter.next()); + assertEquals("b", iter.previous()); + list.remove(1); + try { + iter.remove(); + } catch (ConcurrentModificationException ex) { + // expected + } + // iterator state now invalid } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]