You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2013/06/22 21:46:16 UTC

svn commit: r1495775 - in /cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne: map/EntityResolver.java reflect/ClassDescriptorMap.java

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