Author: aadamchik Date: Sat Jun 22 19:46:16 2013 New Revision: 1495775 URL: http://svn.apache.org/r1495775 Log: CAY-1789 Lock-free EntityResolver
making class descriptor access non-synchronized Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/ClassDescriptorMap.java Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java?rev=1495775&r1=1495774&r2=1495775&view=diff ============================================================================== --- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java (original) +++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java Sat Jun 22 19:46:16 2013 @@ -64,7 +64,7 @@ public class EntityResolver implements M // must be transient, as resolver may get deserialized in another VM, and // descriptor recompilation will be desired. - protected transient ClassDescriptorMap classDescriptorMap; + protected transient volatile ClassDescriptorMap classDescriptorMap; // callbacks are not serializable protected transient LifecycleCallbackRegistry callbackRegistry; @@ -444,7 +444,7 @@ public class EntityResolver implements M * * @since 1.2 */ - public synchronized ClassDescriptor getClassDescriptor(String entityName) { + public ClassDescriptor getClassDescriptor(String entityName) { if (entityName == null) { throw new IllegalArgumentException("Null entityName"); } @@ -659,22 +659,30 @@ public class EntityResolver implements M */ public ClassDescriptorMap getClassDescriptorMap() { if (classDescriptorMap == null) { - ClassDescriptorMap classDescriptorMap = new ClassDescriptorMap(this); - FaultFactory faultFactory = new SingletonFaultFactory(); - // add factories in reverse of the desired chain order - classDescriptorMap.addFactory(new ValueHolderDescriptorFactory(classDescriptorMap)); - classDescriptorMap.addFactory(new DataObjectDescriptorFactory(classDescriptorMap, faultFactory)); + synchronized (this) { - // since ClassDescriptorMap is not synchronized, we need to prefill - // it with entity proxies here. - for (DataMap map : maps) { - for (String entityName : map.getObjEntityMap().keySet()) { - classDescriptorMap.getDescriptor(entityName); + if (classDescriptorMap == null) { + + ClassDescriptorMap classDescriptorMap = new ClassDescriptorMap(this); + FaultFactory faultFactory = new SingletonFaultFactory(); + + // add factories in reverse of the desired chain order + classDescriptorMap.addFactory(new ValueHolderDescriptorFactory(classDescriptorMap)); + classDescriptorMap.addFactory(new DataObjectDescriptorFactory(classDescriptorMap, faultFactory)); + + // since ClassDescriptorMap is not synchronized, we need to + // prefill + // it with entity proxies here. + for (DataMap map : maps) { + for (String entityName : map.getObjEntityMap().keySet()) { + classDescriptorMap.getDescriptor(entityName); + } + } + + this.classDescriptorMap = classDescriptorMap; } } - - this.classDescriptorMap = classDescriptorMap; } return classDescriptorMap; Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/ClassDescriptorMap.java URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/ClassDescriptorMap.java?rev=1495775&r1=1495774&r2=1495775&view=diff ============================================================================== --- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/ClassDescriptorMap.java (original) +++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/ClassDescriptorMap.java Sat Jun 22 19:46:16 2013 @@ -28,10 +28,11 @@ import org.apache.cayenne.CayenneRuntime import org.apache.cayenne.map.EntityResolver; /** - * An object that holds class descriptors for mapped entities, compiling new descriptors - * on demand using an internal chain of descriptor factories. Note that the object is ot - * synchronized internally, so it has to be prefilled with descriptors by the caller on - * initialization via calling 'getDescriptor' for all mapped entities. + * An object that holds class descriptors for mapped entities, compiling new + * descriptors on demand using an internal chain of descriptor factories. Note + * that the object is not synchronized internally, so it has to be prefilled + * with descriptors by the caller on initialization via calling 'getDescriptor' + * for all mapped entities. * * @since 3.0 */ @@ -83,8 +84,7 @@ public class ClassDescriptorMap { public void addDescriptor(String entityName, ClassDescriptor descriptor) { if (descriptor == null) { removeDescriptor(entityName); - } - else { + } else { descriptors.put(entityName, descriptor); } } @@ -103,9 +103,9 @@ public class ClassDescriptorMap { } /** - * Creates a descriptor wrapper that will compile the underlying descriptor on demand. - * Using proxy indirection is needed to compile relationships of descriptors to other - * descriptors that are not compiled yet. + * Creates a descriptor wrapper that will compile the underlying descriptor + * on demand. Using proxy indirection is needed to compile relationships of + * descriptors to other descriptors that are not compiled yet. */ protected ClassDescriptor createProxyDescriptor(String entityName) { ClassDescriptor descriptor = new LazyClassDescriptorDecorator(this, entityName); @@ -118,11 +118,12 @@ public class ClassDescriptorMap { */ protected ClassDescriptor createDescriptor(String entityName) { - // scan the factory chain until some factory returns a non-null descriptor; - // scanning is done in reverse order so that the factories added last take higher + // scan the factory chain until some factory returns a non-null + // descriptor; + // scanning is done in reverse order so that the factories added last + // take higher // precedence... - ListIterator<ClassDescriptorFactory> it = factories - .listIterator(factories.size()); + ListIterator<ClassDescriptorFactory> it = factories.listIterator(factories.size()); while (it.hasPrevious()) { ClassDescriptorFactory factory = it.previous(); ClassDescriptor descriptor = factory.getDescriptor(entityName); @@ -132,7 +133,6 @@ public class ClassDescriptorMap { } } - throw new CayenneRuntimeException("Failed to create descriptor for entity: " - + entityName); + throw new CayenneRuntimeException("Failed to create descriptor for entity: " + entityName); } }