Author: schor Date: Fri Sep 16 21:13:49 2016 New Revision: 1761093 URL: http://svn.apache.org/viewvc?rev=1761093&view=rev Log: [UIMA-5111] add copy on write experiment for avoiding ConcurrentModificationException
Added: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/CopyOnWriteObjHashSet.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/CopyOnWriteOrderedFsSet_array.java Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_bag.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_set_sorted.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_bag.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_bag_pear.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_set_sorted.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/ObjHashSet.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/OrderedFsSet_array.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas/test/IteratorTest.java Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_bag.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_bag.java?rev=1761093&r1=1761092&r2=1761093&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_bag.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_bag.java Fri Sep 16 21:13:49 2016 @@ -19,6 +19,7 @@ package org.apache.uima.cas.impl; +import java.lang.ref.WeakReference; import java.util.Collection; import java.util.List; @@ -26,6 +27,8 @@ import org.apache.uima.cas.FSIterator; import org.apache.uima.cas.FeatureStructure; import org.apache.uima.cas.Type; import org.apache.uima.cas.admin.FSIndexComparator; +import org.apache.uima.internal.util.CopyOnWriteObjHashSet; +import org.apache.uima.internal.util.CopyOnWriteOrderedFsSet_array; import org.apache.uima.internal.util.ObjHashSet; import org.apache.uima.jcas.cas.TOP; @@ -43,6 +46,18 @@ public class FsIndex_bag<T extends Featu // The index final private ObjHashSet<TOP> index; + + /** + * Copy on write, initially null + * Iterator creation initializes (if not null). + * Modification to index: + * call cow.makeCopy(); + * set cow = null + * do the modification + * index clear/flush - set to null; + */ + private WeakReference<CopyOnWriteObjHashSet<TOP>> cow = null; + FsIndex_bag(CASImpl cas, Type type, int initialSize, int indexType, FSIndexComparator comparatorForIndexSpecs) { super(cas, type, indexType, cleanUpComparator(comparatorForIndexSpecs, cas)); this.index = new ObjHashSet<TOP>(initialSize, TOP.class, TOP._singleton); @@ -67,10 +82,12 @@ public class FsIndex_bag<T extends Featu public void flush() { index.clear(); + cow = null; } @Override public final void insert(T fs) { + maybeCopy(); index.add((TOP) fs); } @@ -163,6 +180,7 @@ public class FsIndex_bag<T extends Featu */ @Override public boolean deleteFS(T fs) { + maybeCopy(); return this.index.remove(fs); } @@ -185,6 +203,9 @@ public class FsIndex_bag<T extends Featu */ @Override public FSIterator<T> iterator() { + if (null == cow || null == cow.get()) { + cow = new WeakReference<>(new CopyOnWriteObjHashSet<TOP>(index)); + } return casImpl.inPearContext() ? new FsIterator_bag_pear<>(this, type) : new FsIterator_bag <>(this, type); @@ -192,8 +213,33 @@ public class FsIndex_bag<T extends Featu ObjHashSet<TOP> getObjHashSet() { return index; + } + + private void maybeCopy() { + if (cow != null) { + CopyOnWriteObjHashSet<TOP> v = cow.get(); + if (v != null) { + v.makeCopy(); + } + cow = null; + } } - - + /** + * Called when iterator created, and when a reset concur mod happens + * @return cow to use in iterator + */ + public CopyOnWriteObjHashSet<TOP> getCow() { + if (cow != null) { + CopyOnWriteObjHashSet<TOP> n = cow.get(); + if (n != null) { + return n; + } + } + + // null means index updated since iterator was created, need to make new cow and use it + CopyOnWriteObjHashSet<TOP> n = new CopyOnWriteObjHashSet<TOP>(index); + cow = new WeakReference<>(n); + return n; + } } Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_set_sorted.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_set_sorted.java?rev=1761093&r1=1761092&r2=1761093&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_set_sorted.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIndex_set_sorted.java Fri Sep 16 21:13:49 2016 @@ -19,6 +19,7 @@ package org.apache.uima.cas.impl; +import java.lang.ref.WeakReference; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; @@ -29,6 +30,8 @@ import org.apache.uima.cas.FSIterator; import org.apache.uima.cas.FeatureStructure; import org.apache.uima.cas.Type; import org.apache.uima.cas.admin.FSIndexComparator; +import org.apache.uima.internal.util.CopyOnWriteObjHashSet; +import org.apache.uima.internal.util.CopyOnWriteOrderedFsSet_array; import org.apache.uima.internal.util.OrderedFsSet_array; import org.apache.uima.jcas.cas.TOP; @@ -102,7 +105,21 @@ public class FsIndex_set_sorted<T extend // The index, a NavigableSet. // final private TreeSet<FeatureStructure> indexedFSs; // final private TreeSet<FeatureStructure> indexedFSs; - final private OrderedFsSet_array indexedFSs; + final private OrderedFsSet_array indexedFSs; + + /** + * Copy on write, initially null + * Iterator creation initializes (if not null), and uses. + * Modification to index: + * call cow.makeCopy(); + * set cow = null + * do the modification + * index clear/flush - set to null; + * + * Weak ref so that after iterator is GC'd, and no ref's exist, this becomes null, so that + * future mods no longer need to do extra work. + */ + private WeakReference<CopyOnWriteOrderedFsSet_array> cow = null; final private Comparator<TOP> comparatorWithID; final private Comparator<TOP> comparatorWithoutID; @@ -156,6 +173,7 @@ public class FsIndex_set_sorted<T extend @Override public void flush() { + this.cow = null; this.indexedFSs.clear(); // this.itemsToBeAdded.clear(); // this.largestItemNotYetAdded = null; @@ -204,7 +222,7 @@ public class FsIndex_set_sorted<T extend // } // // past the initial load, or item is not > previous largest item to be added - + maybeCopy(); indexedFSs.add((TOP)fs); // // batch this add // largestItemNotYetAdded = fs; @@ -308,6 +326,7 @@ public class FsIndex_set_sorted<T extend @Override public boolean deleteFS(T fs) { // maybeProcessBulkAdds(); // moved to OrderedFsSet_array class + maybeCopy(); return this.indexedFSs.remove(fs); } @@ -329,10 +348,37 @@ public class FsIndex_set_sorted<T extend @Override public FSIterator<T> iterator() { + if (cow == null || null == cow.get()) { + cow = new WeakReference<>(new CopyOnWriteOrderedFsSet_array(this.indexedFSs)); + } return casImpl.inPearContext() ? new FsIterator_set_sorted_pear<>(this, type, this) : new FsIterator_set_sorted <>(this, type, this); } + + private void maybeCopy() { + if (cow != null) { + CopyOnWriteOrderedFsSet_array v = cow.get(); + if (v != null) { + v.makeCopy(); + } + cow = null; + } + } + + public CopyOnWriteOrderedFsSet_array getCow() { + if (cow != null) { + CopyOnWriteOrderedFsSet_array n = cow.get(); + if (n != null) { + return n; + } + } + + // null means index updated since iterator was created, need to make new cow and use it + CopyOnWriteOrderedFsSet_array n = new CopyOnWriteOrderedFsSet_array(indexedFSs); + cow = new WeakReference<>(n); + return n; + } // synchronized void maybeProcessBulkAdds() { // final int sz = itemsToBeAdded.size(); Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_bag.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_bag.java?rev=1761093&r1=1761092&r2=1761093&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_bag.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_bag.java Fri Sep 16 21:13:49 2016 @@ -22,11 +22,13 @@ package org.apache.uima.cas.impl; import java.util.NoSuchElementException; import org.apache.uima.cas.FeatureStructure; +import org.apache.uima.internal.util.CopyOnWriteObjHashSet; import org.apache.uima.internal.util.ObjHashSet; +import org.apache.uima.jcas.cas.TOP; class FsIterator_bag<T extends FeatureStructure> extends FsIterator_singletype<T> { - private ObjHashSet<T> bag; + private CopyOnWriteObjHashSet<TOP> bag; private int position = -1; @@ -37,8 +39,6 @@ class FsIterator_bag<T extends FeatureSt FsIterator_bag(FsIndex_bag<T> fsBagIndex, TypeImpl ti) { super(ti, null); // null: null comparator for bags this.fsBagIndex = fsBagIndex; // need for copy() - bag = (ObjHashSet<T>) fsBagIndex.getObjHashSet(); - resetConcurrentModification(); moveToFirst(); } @@ -57,14 +57,14 @@ class FsIterator_bag<T extends FeatureSt public T get() { checkConcurrentModification(); if (isValid()) { - return bag.get(position); + return (T) bag.get(position); } throw new NoSuchElementException(); } public T getNvc() { checkConcurrentModification(); - return bag.get(position); + return (T) bag.get(position); } /* (non-Javadoc) @@ -72,6 +72,7 @@ class FsIterator_bag<T extends FeatureSt */ @Override public void moveToFirst() { + bag = fsBagIndex.getCow(); resetConcurrentModification(); isGoingForward = true; position = (bag.size() == 0) ? -1 : bag.moveToNextFilled(0); @@ -83,6 +84,7 @@ class FsIterator_bag<T extends FeatureSt */ @Override public void moveToLast() { + bag = fsBagIndex.getCow(); resetConcurrentModification(); isGoingForward = false; position = (bag.size() == 0) ? -1 : bag.moveToPreviousFilled(bag.getCapacity() -1); @@ -132,6 +134,7 @@ class FsIterator_bag<T extends FeatureSt */ @Override public void moveTo(FeatureStructure fs) { + bag = fsBagIndex.getCow(); resetConcurrentModification(); position = bag.moveTo(fs); } Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_bag_pear.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_bag_pear.java?rev=1761093&r1=1761092&r2=1761093&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_bag_pear.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_bag_pear.java Fri Sep 16 21:13:49 2016 @@ -22,6 +22,11 @@ package org.apache.uima.cas.impl; import org.apache.uima.cas.FeatureStructure; /** + * This version of the FsIterator is used while iterating within a PEAR + * Indexes keep references to the base (possibly non-pear) version of FSs. + * During iteration, within PEARs, if there's a different JCas class for the type, + * the corresponding class instance needs to be found (or created) and returned. + * * @param <T> the type of FSs being returned from the iterator, supplied by the calling context */ class FsIterator_bag_pear<T extends FeatureStructure> extends FsIterator_bag<T> { Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_set_sorted.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_set_sorted.java?rev=1761093&r1=1761092&r2=1761093&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_set_sorted.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FsIterator_set_sorted.java Fri Sep 16 21:13:49 2016 @@ -25,7 +25,7 @@ import java.util.NavigableSet; import java.util.NoSuchElementException; import org.apache.uima.cas.FeatureStructure; -import org.apache.uima.internal.util.OrderedFsSet_array; +import org.apache.uima.internal.util.CopyOnWriteOrderedFsSet_array; import org.apache.uima.jcas.cas.TOP; /** @@ -36,7 +36,7 @@ class FsIterator_set_sorted<T extends Fe // We use TOP instead of T because the // signature of getting a "matching" element limits the type to the declared type, and // in UIMA we can use, say an Annotation instance as a moveTo arg, for a navSet of some subtype of Annotation. - final private NavigableSet<TOP> navSet; // == fsSortIndex.getNavigableSet() + private NavigableSet<TOP> navSet; // == fsSortIndex.getNavigableSet() final protected FsIndex_set_sorted<T> fsSetSortIndex; // only for ll_getIndex, backwards compatibility @@ -59,7 +59,7 @@ class FsIterator_set_sorted<T extends Fe FsIterator_set_sorted(FsIndex_set_sorted<T> fsSetSortIndex, TypeImpl ti, Comparator<FeatureStructure> comp) { super(ti, comp); this.fsSetSortIndex = fsSetSortIndex; - this.navSet = (NavigableSet<TOP>) fsSetSortIndex.getNavigableSet(); // cast to TOP to allow keys outside of range of returned values + this.navSet = (NavigableSet<TOP>) fsSetSortIndex.getCow(); // cast to TOP to allow keys outside of range of returned values iterator = (Iterator<T>) navSet.iterator(); // can't use fsSortIndex.iterator - that recursively calls this resetConcurrentModification(); // follow create of iterator, which, in turn, does any pending batch processing } @@ -70,6 +70,7 @@ class FsIterator_set_sorted<T extends Fe @Override public void moveToFirst() { // fsSetSortIndex.maybeProcessBulkAdds(); + this.navSet = (NavigableSet<TOP>) fsSetSortIndex.getCow(); iterator = (Iterator<T>) navSet.iterator(); // in case iterator was reverse, etc. resetConcurrentModification(); // follow create of iterator, which, in turn, does any pending batch processing isGoingForward = true; @@ -79,6 +80,7 @@ class FsIterator_set_sorted<T extends Fe @Override public void moveToLast() { // fsSetSortIndex.maybeProcessBulkAdds(); + this.navSet = (NavigableSet<TOP>) fsSetSortIndex.getCow(); iterator = (Iterator<T>) navSet.descendingIterator(); resetConcurrentModification(); // follow create of iterator, which, in turn, does any pending batch processing isGoingForward = false; @@ -193,6 +195,7 @@ class FsIterator_set_sorted<T extends Fe isGoingForward = true; isCurrentElementFromLastGet = false; currentElement = null; + this.navSet = (NavigableSet<TOP>) fsSetSortIndex.getCow(); // fsSetSortIndex.maybeProcessBulkAdds(); // not needed, always done due to previous size() call when creating iterator Iterator<T> it = (Iterator<T>) navSet.headSet(fs, false).descendingIterator(); // may have a bunch of equal (using withoutID compare) at end // last element in headSet is 1 before the one LE fs. @@ -215,7 +218,7 @@ class FsIterator_set_sorted<T extends Fe TOP elementBefore = null; boolean comparedEqual = false; // value is ignored, but needed for Java compile while (it.hasNext()) { - comparedEqual = (0 == ((OrderedFsSet_array)navSet).comparatorWithoutID.compare(elementBefore = (TOP)it.next(), fs)); + comparedEqual = (0 == ((CopyOnWriteOrderedFsSet_array)navSet).comparatorWithoutID.compare(elementBefore = (TOP)it.next(), fs)); if (!comparedEqual) { break; } @@ -243,7 +246,7 @@ class FsIterator_set_sorted<T extends Fe @Override protected int getModificationCountFromIndex() { - return ((OrderedFsSet_array)navSet).getModificationCount(); + return ((CopyOnWriteOrderedFsSet_array)navSet).getModificationCount(); } } Added: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/CopyOnWriteObjHashSet.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/CopyOnWriteObjHashSet.java?rev=1761093&view=auto ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/CopyOnWriteObjHashSet.java (added) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/CopyOnWriteObjHashSet.java Fri Sep 16 21:13:49 2016 @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.uima.internal.util; + +import java.util.Iterator; + +import org.apache.uima.cas.FeatureStructure; + +/** + * implements ObjHashSet partially, for iterator use + */ + +public class CopyOnWriteObjHashSet<T> { + + private ObjHashSet<T> ohs; + + + public CopyOnWriteObjHashSet(ObjHashSet<T> original) { + this.ohs = original; + } + + /** + * Called by index when about to make an update + */ + public void makeCopy() { + ohs = new ObjHashSet<>(ohs); + } + + /***************************************************** + * These methods to make this class easily usable by * + * FsIterator_bag * + *****************************************************/ + + /** + * @param obj the object to find in the table (if it is there) + * @return the position of obj in the table, or -1 if not in the table + */ + public int find(T obj) { + return ohs.find(obj); + } + +// @Override +// public int size() { +// +// } + + /** + * For iterator use + * @param index a magic number returned by the internal find + * @return the T at that spot, or null if nothing there + */ + public T get(int index) { + return ohs.get(index); + } + + /** + * advance pos until it points to a non 0 or is 1 past end + * @param pos - + * @return updated pos + */ + public int moveToNextFilled(int pos) { + return ohs.moveToNextFilled(pos); + } + + /** + * decrement pos until it points to a non 0 or is -1 + * @param pos - + * @return updated pos + */ + public int moveToPreviousFilled(int pos) { + return ohs.moveToPreviousFilled(pos); + } + + public Iterator<T> iterator() { + return ohs.iterator(); + } + + /** + * if the fs is in the set, the iterator should return it. + * if not, return -1 (makes iterator invalid) + * @param fs position to this fs + * @return the index if present, otherwise -1; + */ + public int moveTo(FeatureStructure fs) { + return ohs.moveTo(fs); + } + + @Override + public String toString() { + return ohs.toString(); + } + + /** + * @return modification count + * @see org.apache.uima.internal.util.ObjHashSet#getModificationCount() + */ + public int getModificationCount() { + return ohs.getModificationCount(); + } + + /** + * @return + * @see org.apache.uima.internal.util.ObjHashSet#getCapacity() + */ + public int getCapacity() { + return ohs.getCapacity(); + } + + /** + * @return + * @see org.apache.uima.internal.util.ObjHashSet#size() + */ + public int size() { + return ohs.size(); + } + +} Added: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/CopyOnWriteOrderedFsSet_array.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/CopyOnWriteOrderedFsSet_array.java?rev=1761093&view=auto ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/CopyOnWriteOrderedFsSet_array.java (added) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/CopyOnWriteOrderedFsSet_array.java Fri Sep 16 21:13:49 2016 @@ -0,0 +1,433 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.uima.internal.util; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.SortedSet; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.apache.uima.jcas.cas.TOP; + +/** + * implements OrderedFsSet_array partially, for iterator use + * Delegates generated by Eclipse + */ + +public class CopyOnWriteOrderedFsSet_array implements NavigableSet<TOP> { + + private OrderedFsSet_array set; + + final public Comparator<TOP> comparatorWithoutID; + + + public CopyOnWriteOrderedFsSet_array(OrderedFsSet_array original) { + this.set = original; + this.comparatorWithoutID = original.comparatorWithoutID; + } + + /** + * Called by index when about to make an update + */ + public void makeCopy() { + set = new OrderedFsSet_array(set); + } + + /** + * @param action + * @see java.lang.Iterable#forEach(java.util.function.Consumer) + */ + public void forEach(Consumer<? super TOP> action) { + set.forEach(action); + } + + /** + * @return + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return set.hashCode(); + } + + /** + * @param obj + * @return + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + return set.equals(obj); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#comparator() + */ + public Comparator<? super TOP> comparator() { + return set.comparator(); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#first() + */ + public TOP first() { + return set.first(); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#last() + */ + public TOP last() { + return set.last(); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#size() + */ + public int size() { + return set.size(); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#isEmpty() + */ + public boolean isEmpty() { + return set.isEmpty(); + } + + /** + * @param o + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#contains(java.lang.Object) + */ + public boolean contains(Object o) { + return set.contains(o); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#toArray() + */ + public Object[] toArray() { + return set.toArray(); + } + + /** + * @param a1 + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#toArray(java.lang.Object[]) + */ + public <T> T[] toArray(T[] a1) { + return set.toArray(a1); + } + + /** + * @param fs + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#add(org.apache.uima.jcas.cas.TOP) + */ + public boolean add(TOP fs) { + return set.add(fs); + } + + /** + * @return + * @see java.util.SortedSet#spliterator() + */ + public Spliterator<TOP> spliterator() { + return set.spliterator(); + } + + /** + * @param filter + * @return + * @see java.util.Collection#removeIf(java.util.function.Predicate) + */ + public boolean removeIf(Predicate<? super TOP> filter) { + return set.removeIf(filter); + } + + /** + * @return + * @see java.util.Collection#stream() + */ + public Stream<TOP> stream() { + return set.stream(); + } + + /** + * @return + * @see java.util.Collection#parallelStream() + */ + public Stream<TOP> parallelStream() { + return set.parallelStream(); + } + + /** + * @param o + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#remove(java.lang.Object) + */ + public boolean remove(Object o) { + return set.remove(o); + } + + /** + * @param c + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#containsAll(java.util.Collection) + */ + public boolean containsAll(Collection<?> c) { + return set.containsAll(c); + } + + /** + * @param c + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#addAll(java.util.Collection) + */ + public boolean addAll(Collection<? extends TOP> c) { + return set.addAll(c); + } + + /** + * @param c + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#retainAll(java.util.Collection) + */ + public boolean retainAll(Collection<?> c) { + return set.retainAll(c); + } + + /** + * @param c + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#removeAll(java.util.Collection) + */ + public boolean removeAll(Collection<?> c) { + return set.removeAll(c); + } + + /** + * + * @see org.apache.uima.internal.util.OrderedFsSet_array#clear() + */ + public void clear() { + set.clear(); + } + + /** + * @param fs + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#lower(org.apache.uima.jcas.cas.TOP) + */ + public TOP lower(TOP fs) { + return set.lower(fs); + } + + /** + * @param fs + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#lowerPos(org.apache.uima.jcas.cas.TOP) + */ + public int lowerPos(TOP fs) { + return set.lowerPos(fs); + } + + /** + * @param fs + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#floor(org.apache.uima.jcas.cas.TOP) + */ + public TOP floor(TOP fs) { + return set.floor(fs); + } + + /** + * @param fs + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#floorPos(org.apache.uima.jcas.cas.TOP) + */ + public int floorPos(TOP fs) { + return set.floorPos(fs); + } + + /** + * @param fs + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#ceiling(org.apache.uima.jcas.cas.TOP) + */ + public TOP ceiling(TOP fs) { + return set.ceiling(fs); + } + + /** + * @param fs + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#ceilingPos(org.apache.uima.jcas.cas.TOP) + */ + public int ceilingPos(TOP fs) { + return set.ceilingPos(fs); + } + + /** + * @param fs + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#higher(org.apache.uima.jcas.cas.TOP) + */ + public TOP higher(TOP fs) { + return set.higher(fs); + } + + /** + * @param fs + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#higherPos(org.apache.uima.jcas.cas.TOP) + */ + public int higherPos(TOP fs) { + return set.higherPos(fs); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#pollFirst() + */ + public TOP pollFirst() { + return set.pollFirst(); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#pollLast() + */ + public TOP pollLast() { + return set.pollLast(); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#iterator() + */ + public Iterator<TOP> iterator() { + return set.iterator(); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#descendingSet() + */ + public NavigableSet<TOP> descendingSet() { + return set.descendingSet(); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#descendingIterator() + */ + public Iterator<TOP> descendingIterator() { + return set.descendingIterator(); + } + + /** + * @param fromElement + * @param fromInclusive + * @param toElement + * @param toInclusive + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#subSet(org.apache.uima.jcas.cas.TOP, boolean, org.apache.uima.jcas.cas.TOP, boolean) + */ + public NavigableSet<TOP> subSet(TOP fromElement, boolean fromInclusive, TOP toElement, + boolean toInclusive) { + return set.subSet(fromElement, fromInclusive, toElement, toInclusive); + } + + /** + * @param toElement + * @param inclusive + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#headSet(org.apache.uima.jcas.cas.TOP, boolean) + */ + public NavigableSet<TOP> headSet(TOP toElement, boolean inclusive) { + return set.headSet(toElement, inclusive); + } + + /** + * @param fromElement + * @param inclusive + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#tailSet(org.apache.uima.jcas.cas.TOP, boolean) + */ + public NavigableSet<TOP> tailSet(TOP fromElement, boolean inclusive) { + return set.tailSet(fromElement, inclusive); + } + + /** + * @param fromElement + * @param toElement + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#subSet(org.apache.uima.jcas.cas.TOP, org.apache.uima.jcas.cas.TOP) + */ + public SortedSet<TOP> subSet(TOP fromElement, TOP toElement) { + return set.subSet(fromElement, toElement); + } + + /** + * @param toElement + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#headSet(org.apache.uima.jcas.cas.TOP) + */ + public SortedSet<TOP> headSet(TOP toElement) { + return set.headSet(toElement); + } + + /** + * @param fromElement + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#tailSet(org.apache.uima.jcas.cas.TOP) + */ + public SortedSet<TOP> tailSet(TOP fromElement) { + return set.tailSet(fromElement); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#getModificationCount() + */ + public int getModificationCount() { + return set.getModificationCount(); + } + + /** + * @return + * @see org.apache.uima.internal.util.OrderedFsSet_array#toString() + */ + public String toString() { + return set.toString(); + } + + +} Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/ObjHashSet.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/ObjHashSet.java?rev=1761093&r1=1761092&r2=1761093&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/ObjHashSet.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/ObjHashSet.java Fri Sep 16 21:13:49 2016 @@ -40,7 +40,7 @@ import org.apache.uima.cas.FeatureStruct * so find operations continue to work (they can't stop upon finding this object). * */ -public class ObjHashSet<T> implements Set<T>{ +public class ObjHashSet<T> implements Set<T> { public static final float DEFAULT_LOAD_FACTOR = 0.66F; // set to true to collect statistics for tuning @@ -91,6 +91,24 @@ public class ObjHashSet<T> implements Se this.removedMarker = removedMarker; } + /** + * Copy constructor + * @param ohs + */ + public ObjHashSet(ObjHashSet<T> ohs) { + this.removedMarker = ohs.removedMarker; + this.clazz = ohs.clazz; + this.initialCapacity = ohs.initialCapacity; + this.histogram = ohs.histogram; + this.maxProbe = ohs.maxProbe; + this.sizeWhichTriggersExpansion = ohs.sizeWhichTriggersExpansion; + this.size = ohs.size; + this.nbrRemoved = ohs.nbrRemoved; + this.keys = ohs.keys.clone(); + this.secondTimeShrinkable = ohs.secondTimeShrinkable; + this.modificationCount = ohs.modificationCount; + } + private void newTableKeepSize(int capacity) { keys = (T[]) Array.newInstance(clazz, capacity); sizeWhichTriggersExpansion = (int)(capacity * loadFactor); @@ -451,32 +469,32 @@ public class ObjHashSet<T> implements Se return new ObjHashSetIterator(); } - public int moveToFirst() { + private int moveToFirst() { return (size() == 0) ? -1 : moveToNextFilled(0); } - public int moveToLast() { - return (size() == 0) ? -1 : moveToPreviousFilled(getCapacity() -1); - } +// private int moveToLast() { +// return (size() == 0) ? -1 : moveToPreviousFilled(getCapacity() -1); +// } - public int moveToNext(int position) { - if (position < 0) { - return position; - } - final int n = moveToNextFilled(position + 1); - return (n >= getCapacity()) ? -1 : n; - } +// private int moveToNext(int position) { +// if (position < 0) { +// return position; +// } +// final int n = moveToNextFilled(position + 1); +// return (n >= getCapacity()) ? -1 : n; +// } - public int moveToPrevious(int position) { + private int moveToPrevious(int position) { if (position >= getCapacity()) { return -1; } return moveToPreviousFilled(position - 1); } - public boolean isValid(int position) { - return (position >= 0) && (position < getCapacity()); - } +// public boolean isValid(int position) { +// return (position >= 0) && (position < getCapacity()); +// } /** * if the fs is in the set, the iterator should return it. @@ -576,4 +594,5 @@ public class ObjHashSet<T> implements Se public int getModificationCount() { return modificationCount; } + } Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/OrderedFsSet_array.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/OrderedFsSet_array.java?rev=1761093&r1=1761092&r2=1761093&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/OrderedFsSet_array.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/internal/util/OrderedFsSet_array.java Fri Sep 16 21:13:49 2016 @@ -108,10 +108,31 @@ public class OrderedFsSet_array implemen private int lastRemovedPos = -1; private StringBuilder tr = TRACE ? new StringBuilder() : null; + public OrderedFsSet_array(Comparator<TOP> comparatorWithID, Comparator<TOP> comparatorWithoutID) { this.comparatorWithID = comparatorWithID; this.comparatorWithoutID = comparatorWithoutID; } + + /** + * copy constructor + * @param set the original to be copied + */ + public OrderedFsSet_array(OrderedFsSet_array set) { + set.processBatch(); + this.a = set.a.clone(); + this.a_nextFreeslot = set.a_nextFreeslot; + this.a_firstUsedslot = set.a_firstUsedslot; + this.comparatorWithID = set.comparatorWithID; + this.comparatorWithoutID = set.comparatorWithoutID; + this.size = set.size; + this.maxSize = set.maxSize; + this.highest = set.highest; + this.nullBlockStart = set.nullBlockStart; + this.nullBlockEnd = set.nullBlockEnd; + this.modificationCount = set.modificationCount; + this.lastRemovedPos = set.lastRemovedPos; + } @Override public Comparator<? super TOP> comparator() { @@ -1088,9 +1109,7 @@ public class OrderedFsSet_array implemen @Override public boolean hasNext() { - if (batch.size() > 0) { - throw new ConcurrentModificationException(); - } + processBatch(); return pos < a_nextFreeslot; } @@ -1647,4 +1666,5 @@ public class OrderedFsSet_array implemen } } + } Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas/test/IteratorTest.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas/test/IteratorTest.java?rev=1761093&r1=1761092&r2=1761093&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas/test/IteratorTest.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas/test/IteratorTest.java Fri Sep 16 21:13:49 2016 @@ -334,6 +334,8 @@ public class IteratorTest extends TestCa for (int j = 0; j < 2; j++) { assertTrue(it.isValid()); AnnotationFS fs = it.get(); + this.cas.getIndexRepository().addFS(testAnnot); + this.cas.getIndexRepository().removeFS(testAnnot); assertEquals(1, fs.getBegin()); assertEquals(2, fs.getEnd()); it.moveToNext(); @@ -713,6 +715,7 @@ public class IteratorTest extends TestCa private void expectCCE(FeatureStructure a, FSIterator it, boolean isShouldFail) { boolean ok = false; + isShouldFail = false; // after fix try { it.moveToNext(); it.get(); // for set/sorted, the get does the actual "move" operation