[jboss-svn-commits] JBL Code SVN: r36534 - labs/jbossrules/soa_branches/BRMS-5.0.2-GA_BRMS-532_BRMS-533/drools-core/src/main/java/org/drools/base.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Jan 14 15:57:24 EST 2011


Author: tsurdilovic
Date: 2011-01-14 15:57:24 -0500 (Fri, 14 Jan 2011)
New Revision: 36534

Modified:
   labs/jbossrules/soa_branches/BRMS-5.0.2-GA_BRMS-532_BRMS-533/drools-core/src/main/java/org/drools/base/ClassFieldAccessorCache.java
Log:
BRMS-535: Fix for BRMS-532 and BRMS-533

Modified: labs/jbossrules/soa_branches/BRMS-5.0.2-GA_BRMS-532_BRMS-533/drools-core/src/main/java/org/drools/base/ClassFieldAccessorCache.java
===================================================================
--- labs/jbossrules/soa_branches/BRMS-5.0.2-GA_BRMS-532_BRMS-533/drools-core/src/main/java/org/drools/base/ClassFieldAccessorCache.java	2011-01-14 20:55:53 UTC (rev 36533)
+++ labs/jbossrules/soa_branches/BRMS-5.0.2-GA_BRMS-532_BRMS-533/drools-core/src/main/java/org/drools/base/ClassFieldAccessorCache.java	2011-01-14 20:57:24 UTC (rev 36534)
@@ -1,3 +1,19 @@
+/**
+ * Copyright 2010 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package org.drools.base;
 
 import java.security.ProtectionDomain;
@@ -4,208 +20,50 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.drools.RuntimeDroolsException;
-import org.drools.util.asm.ClassFieldInspector;
+import org.drools.core.util.asm.ClassFieldInspector;
 
 public class ClassFieldAccessorCache {
-    private static ClassFieldAccessorCache instance;
 
-    private Map<ClassLoader, CacheEntry>   cacheByClassLoader;
+    private Map<ClassLoader, CacheEntry> cacheByClassLoader;
 
-    private ClassLoader                    classLoader;
+    private ClassLoader                  classLoader;
 
-    //    private boolean                        eagerWire;
-
-    //    public static ClassFieldAccessorCache getInstance() {
-    //        if ( instance == null ) {
-    //            ClassLoader cl = Thread.currentThread().getContextClassLoader();
-    //            if ( cl == null ) {
-    //                cl = ClassFieldAccessorCache.class.getClassLoader();
-    //            }
-    //            instance = new ClassFieldAccessorCache( cl );
-    //        }
-    //        
-    //        return instance;
-    //    }
-    //
-    //    public ClassFieldAccessorCache() {
-    //        // we don't set the classloader here, its just for Externalisable
-    //        // any using class will need to set the classloader before using
-    //        this( null );
-    //    }
-
     public ClassFieldAccessorCache(ClassLoader classLoader) {
         //        lookup = new HashMap<AccessorKey, LookupEntry>();
         cacheByClassLoader = new WeakHashMap<ClassLoader, CacheEntry>();
         this.classLoader = classLoader;
     }
 
-    //    public void writeExternal(ObjectOutput out) throws IOException {
-    //        out.writeObject( lookup );
-    //
-    //    }
-    //
-    //    public void readExternal(ObjectInput in) throws IOException,
-    //                                            ClassNotFoundException {
-    //        lookup = ( Map<AccessorKey, LookupEntry> ) in.readObject();
-    //    }
-
-    public void setClassLoader(ClassLoader classLoader) {
-        this.classLoader = classLoader;
-    }
-
     public ClassLoader getClassLoader() {
         return this.classLoader;
     }
 
-    //    public void setEagerWire(boolean eagerWire) {
-    //        this.eagerWire = eagerWire;
-    //    }
-    //
-    //    public ClassFieldWriter getWriter(Class cls,
-    //                                      String fieldName,
-    //                                      ClassLoader classLoader) {
-    //        //        return getReader( cls.getName(),
-    //        //                          fieldName,
-    //        //                          null );
-    //        return null;
-    //    }
-    //
-    //    public ClassFieldReader getReader(Class cls,
-    //                                      String fieldName,
-    //                                      ClassLoader classLoader) {
-    //        return getReader( cls.getName(),
-    //                          fieldName,
-    //                          null );
-    //    }
-    //
-    //    public synchronized ClassFieldReader getReader(final String className,
-    //                                                   final String fieldName,
-    //                                                   final AcceptsReadAccessor target) {
-    //        AccessorKey key = new AccessorKey( className,
-    //                                           fieldName );
-    //        LookupEntry entry = this.lookup.get( key );
-    //        if ( entry == null ) {
-    //            entry = new LookupEntry( new ClassFieldReader( className,
-    //                                                           fieldName ) );
-    //        }
-    //
-    //        if ( target != null ) {
-    //            entry.addReadAccessorTargets( target );
-    //        }
-    //
-    //        if ( this.eagerWire ) {
-    //            wire( entry.getClassFieldReader() );
-    //        }
-    //
-    //        return entry.getClassFieldReader();
-    //    }
-    //
-    //    public synchronized ClassFieldWriter getWriter(final String className,
-    //                                                   final String fieldName,
-    //                                                   final AcceptsWriteAccessor target) {
-    //        AccessorKey key = new AccessorKey( className,
-    //                                           fieldName );
-    //        LookupEntry entry = this.lookup.get( key );
-    //        if ( entry == null ) {
-    //            entry = new LookupEntry( new ClassFieldWriter( className,
-    //                                                           fieldName ) );
-    //            if ( target != null ) {
-    //                //entry.addReadAccessorTargets( target );
-    //            }
-    //        }
-    //
-    //        if ( this.eagerWire ) {
-    //            wire( entry.getClassFieldReader() );
-    //        }
-    //
-    //        return entry.getClassFieldWriter();
-    //    }
-    //
-    //    public void merge(ClassFieldAccessorCache other) {
-    //        for ( Entry<AccessorKey, LookupEntry> entry : other.lookup.entrySet() ) {
-    //            LookupEntry lookupEntry = this.lookup.get( entry.getKey() );
-    //            if ( lookupEntry == null ) {
-    //                // ClassFieldReader does not exist here, so copy in everything.
-    //                this.lookup.put( entry.getKey(),
-    //                                 entry.getValue() );
-    //            } else {
-    //                // iterate through new constraints adding them and wiring them up
-    //                // to the existing ClassFieldReader
-    //                for ( AcceptsReadAccessor target : entry.getValue().getReadAccessorTargets() ) {
-    //                    target.setReadAccessor( lookupEntry.getClassFieldReader() );
-    //                    lookupEntry.addReadAccessorTargets( target );
-    //                }
-    //            }
-    //        }
-    //    }
-    //
-    //    public void wire() {
-    //        for ( Entry<AccessorKey, LookupEntry> entry : lookup.entrySet() ) {
-    //            wire( entry.getValue().getClassFieldReader() );
-    //        }
-    //    }
-    //
-    //    public void wire(ClassFieldReader reader) {
-    //        reader.setReadAccessor( getReadAcessor( reader ) );
-    //    }
-    //
-    //    public void wire(ClassFieldWriter writer) {
-    //        writer.setWriteAccessor( getWriteAcessor( writer ) );
-    //    }
-    //
-    //    public ClassFieldAccessor getAccessor(Class cls,
-    //                                          String fieldName,
-    //                                          ClassLoader classLoader) {
-    //        return getAccessor( cls.getName(),
-    //                            fieldName,
-    //                            null );
-    //    }
-    //
-    //    public ClassFieldAccessor getAccessor(final String className,
-    //                                          final String fieldName,
-    //                                          final AcceptsReadAccessor target) {
-    //        AccessorKey key = new AccessorKey( className,
-    //                                           fieldName );
-    //        LookupEntry entry = this.lookup.get( key );
-    //        if ( entry == null ) {
-    //            entry = new LookupEntry( new ClassFieldReader( className,
-    //                                                           fieldName ),
-    //                                     new ClassFieldWriter( className,
-    //                                                           fieldName ) );
-    //            if ( target != null ) {
-    //                entry.addReadAccessorTargets( target );
-    //            }
-    //        }
-    //
-    //        if ( this.eagerWire ) {
-    //            wire( entry.getClassFieldReader() );
-    //            wire( entry.getClassFieldWriter() );
-    //        }
-    //
-    //        return new ClassFieldAccessor( entry.getClassFieldReader(),
-    //                                       entry.getClassFieldWriter() );
-    //    }
-
     public ClassObjectType getClassObjectType(ClassObjectType objectType) {
         // always lookup the class, as the ClassObjectType might refer to the class from another ClassLoader
         Class cls = getClass( objectType.getClassName() );
         CacheEntry cache = getCacheEntry( cls );
-        return cache.getClassObjectType( cls, objectType );                
+        return cache.getClassObjectType( cls,
+                                         objectType );
     }
-    
+
     public static class ClassObjectTypeKey {
-        private Class cls;
+        private Class   cls;
         private boolean event;
+
         public ClassObjectTypeKey(Class cls,
                                   boolean event) {
             this.cls = cls;
             this.event = event;
         }
+
         public Class getCls() {
             return cls;
         }
+
         public boolean isEvent() {
             return event;
         }
@@ -230,8 +88,6 @@
             return true;
         }
 
-        
-        
     }
 
     public BaseClassFieldReader getReadAcessor(ClassFieldReader reader) {
@@ -251,51 +107,48 @@
     public BaseClassFieldWriter getWriteAcessor(ClassFieldWriter writer) {
         String className = writer.getClassName();
         String fieldName = writer.getFieldName();
-        
+
         Class cls = getClass( className );
         CacheEntry cache = getCacheEntry( cls );
-        
+
         // get the ReaderAccessor for this key
         return cache.getWriteAccessor( new AccessorKey( className,
                                                         fieldName,
                                                         AccessorKey.AccessorType.FieldAccessor ),
                                        cls );
     }
-    
-    public Class getClass(String className) { 
+
+    public Class getClass(String className) {
         try {
             return this.classLoader.loadClass( className );
         } catch ( ClassNotFoundException e ) {
             throw new RuntimeDroolsException( "Unable to resolve class '" + className + "'" );
         }
-    }    
-        
+    }
+
     public CacheEntry getCacheEntry(Class cls) {
         // System classloader classes return null on some JVMs
-        ClassLoader cl = cls.getClassLoader() != null ? 
-        		         cls.getClassLoader() : ( this.classLoader != null ) ? 
-        		        		                  this.classLoader : 
-        		        		                  ClassLoader.getSystemClassLoader();
+        ClassLoader cl = cls.getClassLoader() != null ? cls.getClassLoader() : this.classLoader;
 
         CacheEntry cache = this.cacheByClassLoader.get( cl );
         if ( cache == null ) {
             // setup a cache for this ClassLoader
-            cache = new CacheEntry( cl );
+            cache = new CacheEntry( this.classLoader );
             this.cacheByClassLoader.put( cl,
                                          cache );
         }
-        
+
         return cache;
     }
 
     public static class CacheEntry {
-        private ByteArrayClassLoader                         byteArrayClassLoader;
-        private final Map<AccessorKey, BaseClassFieldReader> readCache   = new HashMap<AccessorKey, BaseClassFieldReader>();
-        private final Map<AccessorKey, BaseClassFieldWriter> writeCache  = new HashMap<AccessorKey, BaseClassFieldWriter>();
+        private ByteArrayClassLoader                                     byteArrayClassLoader;
+        private final ConcurrentMap<AccessorKey, BaseClassFieldReader>   readCache   = new ConcurrentHashMap<AccessorKey, BaseClassFieldReader>();
+        private final ConcurrentMap<AccessorKey, BaseClassFieldWriter>   writeCache  = new ConcurrentHashMap<AccessorKey, BaseClassFieldWriter>();
 
-        private final Map<Class< ? >, ClassFieldInspector>   inspectors  = new HashMap<Class< ? >, ClassFieldInspector>();
+        private final ConcurrentMap<Class< ? >, ClassFieldInspector>     inspectors  = new ConcurrentHashMap<Class< ? >, ClassFieldInspector>();
 
-        private final Map<ClassObjectTypeKey, ClassObjectType>       objectTypes = new HashMap<ClassObjectTypeKey, ClassObjectType>();
+        private final ConcurrentMap<ClassObjectTypeKey, ClassObjectType> objectTypes = new ConcurrentHashMap<ClassObjectTypeKey, ClassObjectType>();
 
         public CacheEntry(ClassLoader parentClassLoader) {
             if ( parentClassLoader == null ) {
@@ -303,7 +156,7 @@
             }
             this.byteArrayClassLoader = new ByteArrayClassLoader( parentClassLoader );
         }
-        
+
         public ByteArrayClassLoader getByteArrayClassLoader() {
             return byteArrayClassLoader;
         }
@@ -315,8 +168,12 @@
                 reader = ClassFieldAccessorFactory.getInstance().getClassFieldReader( cls,
                                                                                       key.getFieldName(),
                                                                                       this );
-                this.readCache.put( key,
-                                    reader );
+                BaseClassFieldReader existingReader = this.readCache.putIfAbsent( key,
+                                                                                  reader );
+                if ( existingReader != null ) {
+                    // Raced, use the (now) existing entry
+                    reader = existingReader;
+                }
             }
 
             return reader;
@@ -324,34 +181,42 @@
 
         public BaseClassFieldWriter getWriteAccessor(AccessorKey key,
                                                      Class cls) {
-            BaseClassFieldWriter reader = this.writeCache.get( key );
-            if ( reader == null ) {
-                reader = ClassFieldAccessorFactory.getInstance().getClassFieldWriter( cls,
+            BaseClassFieldWriter writer = this.writeCache.get( key );
+            if ( writer == null ) {
+                writer = ClassFieldAccessorFactory.getInstance().getClassFieldWriter( cls,
                                                                                       key.getFieldName(),
                                                                                       this );
-                this.writeCache.put( key,
-                                     reader );
+                BaseClassFieldWriter existingWriter = this.writeCache.putIfAbsent( key,
+                                                                                   writer );
+                if ( existingWriter != null ) {
+                    // Raced, use the (now) existing entry
+                    writer = existingWriter;
+                }
             }
 
-            return reader;
+            return writer;
         }
 
         public Map<Class< ? >, ClassFieldInspector> getInspectors() {
             return inspectors;
         }
-        
-        public ClassObjectType getClassObjectType(Class cls, ClassObjectType objectType) {
-            ClassObjectTypeKey key = new ClassObjectTypeKey(cls, objectType.isEvent() );            
+
+        public ClassObjectType getClassObjectType(Class<?> cls,
+                                                  ClassObjectType objectType) {
+            ClassObjectTypeKey key = new ClassObjectTypeKey( cls,
+                                                             objectType.isEvent() );
             ClassObjectType existing = objectTypes.get( key );
-            
-            if ( existing != null ) {
-                objectType = existing;
-            } else {
+
+            if ( existing == null ) {
                 objectType.setClassType( cls ); // most likely set, but set anyway.
-                objectTypes.put(  key, objectType );
+                existing = objectTypes.putIfAbsent( key, objectType );
+                if ( existing == null ) {
+                    // Not raced, use the one we created.
+                    existing = objectType;
+                }
             }
-            
-            return objectType;            
+
+            return existing;
         }
 
     }



More information about the jboss-svn-commits mailing list