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



Reply via email to