Merge pull request #610 from dangerousben/init-race-condition
Fix FhirContext initialisation race condition.
This commit is contained in:
commit
9201692c70
|
@ -82,7 +82,6 @@ public class FhirContext {
|
|||
private Map<String, Class<? extends IBaseResource>> myDefaultTypeForProfile = new HashMap<String, Class<? extends IBaseResource>>();
|
||||
private volatile Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = Collections.emptyMap();
|
||||
private boolean myInitialized;
|
||||
private boolean myInitializing;
|
||||
private HapiLocalizer myLocalizer = new HapiLocalizer();
|
||||
private volatile Map<String, BaseRuntimeElementDefinition<?>> myNameToElementDefinition = Collections.emptyMap();
|
||||
private volatile Map<String, RuntimeResourceDefinition> myNameToResourceDefinition = Collections.emptyMap();
|
||||
|
@ -644,8 +643,6 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
private synchronized Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> scanResourceTypes(Collection<Class<? extends IElement>> theResourceTypes) {
|
||||
myInitializing = true;
|
||||
|
||||
List<Class<? extends IBase>> typesToScan = new ArrayList<Class<? extends IBase>>();
|
||||
if (theResourceTypes != null) {
|
||||
typesToScan.addAll(theResourceTypes);
|
||||
|
@ -844,8 +841,8 @@ public class FhirContext {
|
|||
return resTypes;
|
||||
}
|
||||
|
||||
private void validateInitialized() {
|
||||
if (!myInitialized && !myInitializing) {
|
||||
private synchronized void validateInitialized() {
|
||||
if (!myInitialized) {
|
||||
scanResourceTypes(toElementList(myResourceTypesToScan));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.dstu3.model.Reference;
|
||||
|
@ -81,4 +87,41 @@ public class FhirContextDstu3Test {
|
|||
assertEquals(null, genderChild.getBoundEnumType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitialisationThreadSafety() {
|
||||
final FhirContext ctx = FhirContext.forDstu3();
|
||||
|
||||
final int numThreads = 4;
|
||||
final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>());
|
||||
final ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
|
||||
try {
|
||||
final CountDownLatch threadsReady = new CountDownLatch(numThreads);
|
||||
final CountDownLatch threadsFinished = new CountDownLatch(numThreads);
|
||||
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
threadPool.submit(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
threadsReady.countDown();
|
||||
try {
|
||||
threadsReady.await();
|
||||
ctx.getResourceDefinition("patient");
|
||||
} catch(final Exception e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
threadsFinished.countDown();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
threadsFinished.await();
|
||||
} catch(final InterruptedException e) {
|
||||
exceptions.add(e);
|
||||
} finally {
|
||||
threadPool.shutdownNow();
|
||||
}
|
||||
|
||||
assertTrue("failed with exception(s): " + exceptions, exceptions.isEmpty());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue