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); } }