Author: schor Date: Tue Apr 15 20:25:30 2014 New Revision: 1587714 URL: http://svn.apache.org/r1587714 Log: [UIMA-1249] [UIMA-1598] fixes supporting multiple initialize calls on multiple threads. Make fields either final or volatile, per JCIP (Java Concurrency in Practice)
Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/impl/CasManager_impl.java Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/impl/CasManager_impl.java URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/impl/CasManager_impl.java?rev=1587714&r1=1587713&r2=1587714&view=diff ============================================================================== --- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/impl/CasManager_impl.java (original) +++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/impl/CasManager_impl.java Tue Apr 15 20:25:30 2014 @@ -48,27 +48,37 @@ import org.apache.uima.util.impl.CasPool /** * Simple CAS Manager Implementation used in the AnalysisEngine framework. Maintains a pool of 1 CAS * for each requestor. + * + * The ResourceManager points to one instantiation of this class. + * + * An instance of this class might be accessed in parallel on different threads. */ public class CasManager_impl implements CasManager { private ResourceManager mResourceManager; - private List<ProcessingResourceMetaData> mMetaDataList = new ArrayList<ProcessingResourceMetaData>(); + /** + * accumulates the metadata needed for shared CASes for this resource manager + * Starts out "empty" when this is created; is added to (but never removed) + * Duplicates may be in the list. + */ + private final List<ProcessingResourceMetaData> mMetaDataList = Collections.synchronizedList(new ArrayList<ProcessingResourceMetaData>()); - private Map<String, CasPool> mRequestorToCasPoolMap = Collections.synchronizedMap(new HashMap<String, CasPool>()); + private final Map<String, CasPool> mRequestorToCasPoolMap = Collections.synchronizedMap(new HashMap<String, CasPool>()); - private Map<CAS, CasPool> mCasToCasPoolMap = Collections.synchronizedMap(new HashMap<CAS, CasPool>()); + private final Map<CAS, CasPool> mCasToCasPoolMap = Collections.synchronizedMap(new HashMap<CAS, CasPool>()); - private Map<CAS, UimaContext> mCasToUimaContextMap = Collections.synchronizedMap(new HashMap<CAS, UimaContext>()); + private final Map<CAS, UimaContext> mCasToUimaContextMap = Collections.synchronizedMap(new HashMap<CAS, UimaContext>()); - private CasDefinition mCasDefinition = null; + private volatile CasDefinition mCasDefinition = null; // once goes non-null, stays - private TypeSystem mCurrentTypeSystem = null; + private volatile TypeSystem mCurrentTypeSystem = null; // once set, same identical typesystem object used for subseq. CASes - private Object mMBeanServer; + private volatile Object mMBeanServer; - private String mMBeanNamePrefix; + private volatile String mMBeanNamePrefix; - private List<CasPoolManagementImpl> casPoolMBeans = new ArrayList<CasPoolManagementImpl>(); + private final List<CasPoolManagementImpl> casPoolMBeans = + Collections.synchronizedList(new ArrayList<CasPoolManagementImpl>()); public CasManager_impl(ResourceManager aResourceManager) { mResourceManager = aResourceManager; @@ -79,10 +89,13 @@ public class CasManager_impl implements * * @see org.apache.uima.resource.CasManager#addMetaData(org.apache.uima.resource.metadata.ProcessingResourceMetaData) */ - public void addMetaData(ProcessingResourceMetaData aMetaData) { + public synchronized void addMetaData(ProcessingResourceMetaData aMetaData) { + if (mCasDefinition != null) { + throw new UIMARuntimeException(); // internal error UIMA-1249 + } mMetaDataList.add(aMetaData); - mCasDefinition = null; // mark this stale - mCurrentTypeSystem = null; //this too +// mCasDefinition = null; // mark this stale +// mCurrentTypeSystem = null; //this too } /* @@ -90,7 +103,7 @@ public class CasManager_impl implements * * @see org.apache.uima.resource.CasManager#getCasDefinition() */ - public CasDefinition getCasDefinition() throws ResourceInitializationException { + public synchronized CasDefinition getCasDefinition() throws ResourceInitializationException { if (mCasDefinition == null) { mCasDefinition = new CasDefinition(mMetaDataList, mResourceManager); } @@ -190,15 +203,20 @@ public class CasManager_impl implements * @see org.apache.uima.resource.CasManager#createNewCas(java.util.Properties) */ public CAS createNewCas(Properties aPerformanceTuningSettings) throws ResourceInitializationException { - CAS cas; + if (mCurrentTypeSystem != null) { - cas = CasCreationUtils.createCas(getCasDefinition(), aPerformanceTuningSettings, mCurrentTypeSystem); - } else - { - cas = CasCreationUtils.createCas(getCasDefinition(), aPerformanceTuningSettings); - mCurrentTypeSystem = cas.getTypeSystem(); + return CasCreationUtils.createCas(getCasDefinition(), aPerformanceTuningSettings, mCurrentTypeSystem); + } else { + synchronized(this) { + if (mCurrentTypeSystem != null) { // double check idiom + return CasCreationUtils.createCas(getCasDefinition(), aPerformanceTuningSettings, mCurrentTypeSystem); + } else { + CAS cas = CasCreationUtils.createCas(getCasDefinition(), aPerformanceTuningSettings); + mCurrentTypeSystem = cas.getTypeSystem(); + return cas; + } + } } - return cas; } /** @@ -292,6 +310,9 @@ public class CasManager_impl implements /** * Registers an MBean for the given CasPool. + * + * Never called unless pool is new + * * @param aRequestorContextName context name that identifies this CasPool * @param pool the CasPool */