Author: schor
Date: Fri Apr 25 20:41:52 2014
New Revision: 1590136

URL: http://svn.apache.org/r1590136
Log:
[UIMA-3774] handle case of table resize while waiting

Modified:
    
uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/jcas/impl/JCasHashMap.java
    
uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/jcas/impl/JCasHashMapTest.java

Modified: 
uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/jcas/impl/JCasHashMap.java
URL: 
http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/jcas/impl/JCasHashMap.java?rev=1590136&r1=1590135&r2=1590136&view=diff
==============================================================================
--- 
uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/jcas/impl/JCasHashMap.java
 (original)
+++ 
uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/jcas/impl/JCasHashMap.java
 Fri Apr 25 20:41:52 2014
@@ -191,49 +191,53 @@ public class JCasHashMap {
      * @param hash - the hash that was already computed from the key
      * @return - the found fs, or null
      */
-    private synchronized FeatureStructureImpl getReserve(int key, int hash) {
+    private synchronized FeatureStructureImpl getReserve(final int key, final 
int hash) {
       int nbrProbes = 1;
-      int probeAddr = hash & bitsMask;
-      int probeDelta = 1;
-      FeatureStructureImpl maybe = table[probeAddr];
-      while ((null != maybe)) {
-        if (maybe.getAddress() == key) {
-          while (((TOP)maybe).jcasType == null) {
-            // we hit a reserve marker - there is another thread in the 
process of creating an instance of this,
-            // so wait for it to finish and then return it
-            try {
-              wait();  // releases the synchronized monitor, otherwise this 
segment blocked for others while waiting
-            } catch (InterruptedException e) {
+      int probeAddr;
+      FeatureStructureImpl maybe;
+      retryAfterWait: do {
+        probeAddr = hash & bitsMask;
+        int probeDelta = 1;
+        maybe = table[probeAddr];
+        while (null != maybe) {
+          if (maybe.getAddress() == key) {
+            while (((TOP) maybe).jcasType == null) {
+              // we hit a reserve marker - there is another thread in the 
process of creating an instance of this,
+              // so wait for it to finish and then return it
+              try {
+                wait();  // releases the synchronized monitor, otherwise this 
segment blocked for others while waiting
+              } catch (InterruptedException e) {
+              }
+              // at this point, the table may have grown
+              // so start over
+              continue retryAfterWait;
             }
-            maybe = table[probeAddr];
+            if (TUNE) {
+              histogram[Math.min(histogram.length - 1, nbrProbes)]++;
+              maxProbe = Math.max(maxProbe, nbrProbes);
+            }
+            return maybe;
           }
+          // is not null, but is wrong key
           if (TUNE) {
-            histogram[Math.min(histogram.length - 1, nbrProbes)]++;
-            maxProbe = Math.max(maxProbe, nbrProbes);
+            nbrProbes++;
           }
-          return maybe;
-        }
-        // is not null, but is wrong key
-        if (TUNE) {
-          nbrProbes++;
+          probeAddr = bitsMask & (probeAddr + (probeDelta++));
+          maybe = table[probeAddr];
         }
-        probeAddr = bitsMask & (probeAddr + (probeDelta++));
-        maybe = table[probeAddr];
-      }
-      
-      // maybe is null
-        // reserve this slot to prevent other "getReserved" calls for this 
same instance from succeeding, 
-        // causing them to wait until this slot gets filled in with a FS value
+        break;
+      } while (true);  // must be true to have label of continue used
+      // "maybe" is null
+      // reserve this slot to prevent other "getReserved" calls for this same 
instance from succeeding,
+      // causing them to wait until this slot gets filled in with a FS value
       table[probeAddr] = new TOP(key, null);  // null indicates its a RESERVE 
marker
-      
-     
+
       if (TUNE) {
         histogram[Math.min(histogram.length - 1, nbrProbes)]++;
         maxProbe = Math.max(maxProbe, nbrProbes);
       }
-      return maybe;    
+      return maybe;
     }
-
     
     private synchronized void put(int key, FeatureStructureImpl value, int 
hash) {
       if (size >= sizeWhichTriggersExpansion) {

Modified: 
uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/jcas/impl/JCasHashMapTest.java
URL: 
http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/jcas/impl/JCasHashMapTest.java?rev=1590136&r1=1590135&r2=1590136&view=diff
==============================================================================
--- 
uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/jcas/impl/JCasHashMapTest.java
 (original)
+++ 
uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/jcas/impl/JCasHashMapTest.java
 Fri Apr 25 20:41:52 2014
@@ -168,6 +168,9 @@ public class JCasHashMapTest extends Tes
     assertEquals(0, numberWaiting);
     System.out.format("JCasHashMapTest collide,  found = %s%n", 
intList(found));
     for (FeatureStructureImpl f : found) {
+      if (f != fs) {
+        System.err.format("JCasHashMapTest miscompare fs = %s,  f = %s%n", fs, 
(f == null) ? "null" : f);
+      }
       assertTrue(f == fs);
     }
   }


Reply via email to