groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sun...@apache.org
Subject groovy git commit: Minor refactoring: Split the implementation of CommonCache into thread-safe and not thread-safe
Date Mon, 11 Dec 2017 15:07:00 GMT
Repository: groovy
Updated Branches:
  refs/heads/master 6323cd15f -> 29727ea0c


Minor refactoring: Split the implementation of CommonCache into thread-safe and not thread-safe


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/29727ea0
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/29727ea0
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/29727ea0

Branch: refs/heads/master
Commit: 29727ea0c0318304ded181aebfa8cce661d34c56
Parents: 6323cd1
Author: sunlan <sunlan@apache.org>
Authored: Mon Dec 11 23:06:53 2017 +0800
Committer: sunlan <sunlan@apache.org>
Committed: Mon Dec 11 23:06:53 2017 +0800

----------------------------------------------------------------------
 src/main/groovy/lang/GroovyClassLoader.java     |   6 +-
 .../groovy/runtime/memoize/CommonCache.java     | 136 +++--------
 .../runtime/memoize/ConcurrentCommonCache.java  | 240 +++++++++++++++++++
 .../stc/StaticTypeCheckingSupport.java          |   4 +-
 .../groovy/runtime/memoize/CommonCacheTest.java | 175 --------------
 .../memoize/ConcurrentCommonCacheTest.java      | 175 ++++++++++++++
 .../macro/transform/MacroMethodsCache.java      |   4 +-
 7 files changed, 452 insertions(+), 288 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/29727ea0/src/main/groovy/lang/GroovyClassLoader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyClassLoader.java b/src/main/groovy/lang/GroovyClassLoader.java
index 47e5444..a491fc0 100644
--- a/src/main/groovy/lang/GroovyClassLoader.java
+++ b/src/main/groovy/lang/GroovyClassLoader.java
@@ -44,7 +44,7 @@ import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.runtime.IOGroovyMethods;
 import org.codehaus.groovy.runtime.InvokerHelper;
 import org.codehaus.groovy.runtime.memoize.EvictableCache;
-import org.codehaus.groovy.runtime.memoize.CommonCache;
+import org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.Opcodes;
@@ -95,13 +95,13 @@ public class GroovyClassLoader extends URLClassLoader {
     /**
      * this cache contains the loaded classes or PARSING, if the class is currently parsed
      */
-    protected final CommonCache<String, Class> classCache = new CommonCache<String,
Class>();
+    protected final ConcurrentCommonCache<String, Class> classCache = new ConcurrentCommonCache<String,
Class>();
 
     /**
      * This cache contains mappings of file name to class. It is used
      * to bypass compilation.
      */
-    protected final CommonCache<String, Class> sourceCache = new CommonCache<String,
Class>();
+    protected final ConcurrentCommonCache<String, Class> sourceCache = new ConcurrentCommonCache<String,
Class>();
 
     private final CompilerConfiguration config;
     private String sourceEncoding;

http://git-wip-us.apache.org/repos/asf/groovy/blob/29727ea0/src/main/org/codehaus/groovy/runtime/memoize/CommonCache.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/memoize/CommonCache.java b/src/main/org/codehaus/groovy/runtime/memoize/CommonCache.java
index 1bd336d..dd29d5b 100644
--- a/src/main/org/codehaus/groovy/runtime/memoize/CommonCache.java
+++ b/src/main/org/codehaus/groovy/runtime/memoize/CommonCache.java
@@ -16,6 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
+
 package org.codehaus.groovy.runtime.memoize;
 
 import java.lang.ref.SoftReference;
@@ -26,11 +27,10 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 /**
  *
- * Represents a simple key-value cache, which is thread safe and backed by a {@link java.util.Map}
instance
+ * Represents a simple key-value cache, which is NOT thread safe and backed by a {@link java.util.Map}
instance
  *
  * @param <K> type of the keys
  * @param <V> type of the values
@@ -39,9 +39,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
  */
 public class CommonCache<K, V> implements EvictableCache<K, V> {
     private final Map<K, V> map;
-    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
-    private final ReentrantReadWriteLock.ReadLock readLock = rwl.readLock();
-    private final ReentrantReadWriteLock.WriteLock writeLock = rwl.writeLock();
 
     /**
      * Constructs a cache with unlimited size
@@ -97,16 +94,7 @@ public class CommonCache<K, V> implements EvictableCache<K, V>
{
      */
     @Override
     public V get(K key) {
-        if (null == key) {
-            return null;
-        }
-
-        readLock.lock();
-        try {
-            return map.get(key);
-        } finally {
-            readLock.unlock();
-        }
+        return map.get(key);
     }
 
     /**
@@ -114,13 +102,7 @@ public class CommonCache<K, V> implements EvictableCache<K,
V> {
      */
     @Override
     public V put(K key, V value) {
-        writeLock.lock();
-        try {
-            return map.put(key, value);
-        } finally {
-            writeLock.unlock();
-        }
-
+        return map.put(key, value);
     }
 
     /**
@@ -132,36 +114,14 @@ public class CommonCache<K, V> implements EvictableCache<K,
V> {
     }
 
     public V getAndPut(K key, ValueProvider<K, V> valueProvider, boolean shouldCache)
{
-        if (null == key) {
-            return null;
+        V value = map.get(key);
+        if (null != value) {
+            return value;
         }
 
-        V value;
-
-        readLock.lock();
-        try {
-            value = map.get(key);
-            if (null != value) {
-                return value;
-            }
-        } finally {
-            readLock.unlock();
-        }
-
-        writeLock.lock();
-        try {
-            // try to find the cached value again
-            value = map.get(key);
-            if (null != value) {
-                return value;
-            }
-
-            value = null == valueProvider ? null : valueProvider.provide(key);
-            if (shouldCache && null != value) {
-                map.put(key, value);
-            }
-        } finally {
-            writeLock.unlock();
+        value = null == valueProvider ? null : valueProvider.provide(key);
+        if (shouldCache && null != value) {
+            map.put(key, value);
         }
 
         return value;
@@ -172,12 +132,7 @@ public class CommonCache<K, V> implements EvictableCache<K,
V> {
      */
     @Override
     public Collection<V> values() {
-        readLock.lock();
-        try {
-            return map.values();
-        } finally {
-            readLock.unlock();
-        }
+        return map.values();
     }
 
     /**
@@ -185,12 +140,7 @@ public class CommonCache<K, V> implements EvictableCache<K,
V> {
      */
     @Override
     public Set<K> keys() {
-        readLock.lock();
-        try {
-            return map.keySet();
-        } finally {
-            readLock.unlock();
-        }
+        return map.keySet();
     }
 
     /**
@@ -198,12 +148,7 @@ public class CommonCache<K, V> implements EvictableCache<K,
V> {
      */
     @Override
     public boolean containsKey(K key) {
-        readLock.lock();
-        try {
-            return map.containsKey(key);
-        } finally {
-            readLock.unlock();
-        }
+        return map.containsKey(key);
     }
 
     /**
@@ -211,12 +156,7 @@ public class CommonCache<K, V> implements EvictableCache<K,
V> {
      */
     @Override
     public int size() {
-        readLock.lock();
-        try {
-            return map.size();
-        } finally {
-            readLock.unlock();
-        }
+        return map.size();
     }
 
     /**
@@ -224,12 +164,7 @@ public class CommonCache<K, V> implements EvictableCache<K,
V> {
      */
     @Override
     public V remove(K key) {
-        writeLock.lock();
-        try {
-            return map.remove(key);
-        } finally {
-            writeLock.unlock();
-        }
+        return map.remove(key);
     }
 
     /**
@@ -237,15 +172,8 @@ public class CommonCache<K, V> implements EvictableCache<K,
V> {
      */
     @Override
     public Collection<V> clear() {
-        Collection<V> values;
-
-        writeLock.lock();
-        try {
-            values = map.values();
-            map.clear();
-        } finally {
-            writeLock.unlock();
-        }
+        Collection<V> values = map.values();
+        map.clear();
 
         return values;
     }
@@ -255,25 +183,21 @@ public class CommonCache<K, V> implements EvictableCache<K,
V> {
      */
     @Override
     public void cleanUpNullReferences() {
-        writeLock.lock();
-        try {
-            List<K> keys = new LinkedList<>();
-
-            for (Map.Entry<K, V> entry : map.entrySet()) {
-                K key = entry.getKey();
-                V value = entry.getValue();
-                if (null == value
-                        || (value instanceof SoftReference && null == ((SoftReference)
value).get())
-                        || (value instanceof WeakReference && null == ((WeakReference)
value).get())) {
-                    keys.add(key);
-                }
+        List<K> keys = new LinkedList<>();
+
+        for (Map.Entry<K, V> entry : map.entrySet()) {
+            K key = entry.getKey();
+            V value = entry.getValue();
+            if (null == value
+                    || (value instanceof SoftReference && null == ((SoftReference)
value).get())
+                    || (value instanceof WeakReference && null == ((WeakReference)
value).get())) {
+                keys.add(key);
             }
+        }
 
-            for (K key : keys) {
-                map.remove(key);
-            }
-        } finally {
-            writeLock.unlock();
+        for (K key : keys) {
+            map.remove(key);
         }
     }
+
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/29727ea0/src/main/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCache.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCache.java b/src/main/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCache.java
new file mode 100644
index 0000000..81345d9
--- /dev/null
+++ b/src/main/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCache.java
@@ -0,0 +1,240 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.codehaus.groovy.runtime.memoize;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ *
+ * Represents a simple key-value cache, which is thread safe and backed by a {@link java.util.Map}
instance
+ *
+ * @param <K> type of the keys
+ * @param <V> type of the values
+ *
+ * @since 2.5.0
+ */
+public class ConcurrentCommonCache<K, V> extends CommonCache<K, V> {
+    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+    private final ReentrantReadWriteLock.ReadLock readLock = rwl.readLock();
+    private final ReentrantReadWriteLock.WriteLock writeLock = rwl.writeLock();
+
+    /**
+     * Constructs a cache with unlimited size
+     */
+    public ConcurrentCommonCache() {}
+
+    /**
+     * Constructs a cache with limited size
+     * @param initialCapacity initial capacity of the LRU cache
+     * @param maxSize max size of the LRU cache
+     * @param accessOrder the ordering mode - <tt>true</tt> for access-order,
<tt>false</tt> for insertion-order, see the parameter accessOrder of {@link LinkedHashMap#LinkedHashMap(int,
float, boolean)}
+     */
+    public ConcurrentCommonCache(int initialCapacity, int maxSize, boolean accessOrder) {
+        super(initialCapacity, maxSize, accessOrder);
+    }
+
+    /**
+     * Constructs a LRU cache with the specified initial capacity and max size.
+     * The LRU cache is slower than {@link LRUCache} but will not put same value multi-times
concurrently
+     * @param initialCapacity initial capacity of the LRU cache
+     * @param maxSize max size of the LRU cache
+     */
+    public ConcurrentCommonCache(int initialCapacity, int maxSize) {
+        super(initialCapacity, maxSize);
+    }
+
+    /**
+     * Constructs a LRU cache with the default initial capacity(16)
+     * @param maxSize max size of the LRU cache
+     * @see #ConcurrentCommonCache(int, int)
+     */
+    public ConcurrentCommonCache(int maxSize) {
+        super(maxSize);
+    }
+
+    /**
+     * Constructs a cache backed by the specified {@link java.util.Map} instance
+     * @param map the {@link java.util.Map} instance
+     */
+    public ConcurrentCommonCache(Map<K, V> map) {
+        super(map);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public V get(K key) {
+        readLock.lock();
+        try {
+            return super.get(key);
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public V put(K key, V value) {
+        writeLock.lock();
+        try {
+            return super.put(key, value);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public V getAndPut(K key, ValueProvider<K, V> valueProvider) {
+        return getAndPut(key, valueProvider, true);
+    }
+
+    @Override
+    public V getAndPut(K key, ValueProvider<K, V> valueProvider, boolean shouldCache)
{
+        V value;
+
+        readLock.lock();
+        try {
+            value = super.get(key);
+            if (null != value) {
+                return value;
+            }
+        } finally {
+            readLock.unlock();
+        }
+
+        writeLock.lock();
+        try {
+            // try to find the cached value again
+            value = super.get(key);
+            if (null != value) {
+                return value;
+            }
+
+            value = null == valueProvider ? null : valueProvider.provide(key);
+            if (shouldCache && null != value) {
+                super.put(key, value);
+            }
+        } finally {
+            writeLock.unlock();
+        }
+
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Collection<V> values() {
+        readLock.lock();
+        try {
+            return super.values();
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Set<K> keys() {
+        readLock.lock();
+        try {
+            return super.keys();
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean containsKey(K key) {
+        readLock.lock();
+        try {
+            return super.containsKey(key);
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int size() {
+        readLock.lock();
+        try {
+            return super.size();
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public V remove(K key) {
+        writeLock.lock();
+        try {
+            return super.remove(key);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Collection<V> clear() {
+        writeLock.lock();
+        try {
+            return super.clear();
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void cleanUpNullReferences() {
+        writeLock.lock();
+        try {
+            super.cleanUpNullReferences();
+        } finally {
+            writeLock.unlock();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/29727ea0/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index b326061..301671b 100644
--- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -46,7 +46,7 @@ import org.codehaus.groovy.runtime.DefaultGroovyStaticMethods;
 import org.codehaus.groovy.runtime.m12n.ExtensionModule;
 import org.codehaus.groovy.runtime.m12n.ExtensionModuleScanner;
 import org.codehaus.groovy.runtime.m12n.MetaInfExtensionModule;
-import org.codehaus.groovy.runtime.memoize.CommonCache;
+import org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache;
 import org.codehaus.groovy.runtime.memoize.EvictableCache;
 import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
 import org.codehaus.groovy.tools.GroovyClass;
@@ -2162,7 +2162,7 @@ public abstract class StaticTypeCheckingSupport {
      * a method lookup.
      */
     private static class ExtensionMethodCache {
-        private final CommonCache<ClassLoader, Map<String, List<MethodNode>>>
cache = new CommonCache<ClassLoader, Map<String, List<MethodNode>>>(new
WeakHashMap<ClassLoader, Map<String, List<MethodNode>>>());
+        private final ConcurrentCommonCache<ClassLoader, Map<String, List<MethodNode>>>
cache = new ConcurrentCommonCache<ClassLoader, Map<String, List<MethodNode>>>(new
WeakHashMap<ClassLoader, Map<String, List<MethodNode>>>());
 
         public Map<String, List<MethodNode>> getExtensionMethods(ClassLoader
loader) {
             return cache.getAndPut(

http://git-wip-us.apache.org/repos/asf/groovy/blob/29727ea0/src/test/org/codehaus/groovy/runtime/memoize/CommonCacheTest.java
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/runtime/memoize/CommonCacheTest.java b/src/test/org/codehaus/groovy/runtime/memoize/CommonCacheTest.java
deleted file mode 100644
index 9fb4350..0000000
--- a/src/test/org/codehaus/groovy/runtime/memoize/CommonCacheTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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.codehaus.groovy.runtime.memoize;
-
-import org.apache.groovy.util.Maps;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-
-public class CommonCacheTest {
-    @Test
-    public void get() {
-        CommonCache<String, String> sc =
-                new CommonCache<>(
-                        new LinkedHashMap<>(
-                                Maps.of("name", "Daniel",
-                                        "gender", "Male",
-                                        "city", "Shanghai")
-                        )
-                );
-
-        Assert.assertEquals("Daniel", sc.get("name"));
-        Assert.assertEquals("Male", sc.get("gender"));
-        Assert.assertEquals("Shanghai", sc.get("city"));
-        Assert.assertNull(sc.get("foo"));
-    }
-
-    @Test
-    public void put() {
-        CommonCache<String, String> sc = new CommonCache<>();
-
-        Assert.assertNull(sc.put("name", "Daniel"));
-        Assert.assertEquals("Daniel", sc.get("name"));
-
-        Assert.assertEquals("Daniel", sc.put("name", "sunlan"));
-        Assert.assertEquals("sunlan", sc.get("name"));
-    }
-
-    @Test
-    public void getAndPut() {
-        CommonCache<String, String> sc = new CommonCache<>();
-
-        EvictableCache.ValueProvider vp =
-                new EvictableCache.ValueProvider<String, String>() {
-            @Override
-            public String provide(String key) {
-                return "Chinese";
-            }
-        };
-
-        Assert.assertEquals("Chinese", sc.getAndPut("language", vp,false));
-        Assert.assertNull(sc.get("language"));
-
-        Assert.assertEquals("Chinese", sc.getAndPut("language", vp));
-        Assert.assertEquals("Chinese", sc.get("language"));
-    }
-
-    @Test
-    public void values() {
-        CommonCache<String, String> sc =
-                new CommonCache<>(
-                        new LinkedHashMap<>(
-                                Maps.of("name", "Daniel",
-                                        "gender", "Male",
-                                        "city", "Shanghai")
-                        )
-                );
-
-        Assert.assertArrayEquals(new String[] {"Daniel", "Male", "Shanghai"}, sc.values().toArray(new
String[0]));
-    }
-
-    @Test
-    public void keys() {
-        CommonCache<String, String> sc =
-                new CommonCache<>(
-                        new LinkedHashMap<>(
-                                Maps.of("name", "Daniel",
-                                        "gender", "Male",
-                                        "city", "Shanghai")
-                        )
-                );
-
-        Assert.assertArrayEquals(new String[] {"name", "gender", "city"}, sc.keys().toArray(new
String[0]));
-    }
-
-    @Test
-    public void containsKey() {
-        CommonCache<String, String> sc =
-                new CommonCache<>(
-                        new LinkedHashMap<>(
-                                Maps.of("name", "Daniel",
-                                        "gender", "Male",
-                                        "city", "Shanghai")
-                        )
-                );
-
-        Assert.assertTrue(sc.containsKey("name"));
-    }
-
-    @Test
-    public void size() {
-        CommonCache<String, String> sc =
-                new CommonCache<>(
-                        new LinkedHashMap<>(
-                                Maps.of("name", "Daniel",
-                                        "gender", "Male",
-                                        "city", "Shanghai")
-                        )
-                );
-
-        Assert.assertEquals(3, sc.size());
-    }
-
-    @Test
-    public void remove() {
-        CommonCache<String, String> sc =
-                new CommonCache<>(
-                        new HashMap<>(
-                                Maps.of("name", "Daniel",
-                                        "gender", "Male",
-                                        "city", "Shanghai")
-                        )
-                );
-
-        Assert.assertEquals("Shanghai", sc.remove("city"));
-        Assert.assertNull(sc.get("city"));
-    }
-
-    @Test
-    public void clear() {
-        CommonCache<String, String> sc =
-                new CommonCache<>(
-                        new LinkedHashMap<>(
-                                Maps.of("name", "Daniel",
-                                        "gender", "Male",
-                                        "city", "Shanghai")
-                        )
-                );
-
-        Assert.assertArrayEquals(new String[] {"Daniel", "Male", "Shanghai"}, sc.values().toArray(new
String[0]));
-    }
-
-    @Test
-    public void cleanUpNullReferences() {
-        CommonCache<String, String> sc =
-                new CommonCache<>(
-                        new LinkedHashMap<>(
-                                Maps.of("name", "Daniel",
-                                        "gender", "Male",
-                                        "city", null)
-                        )
-                );
-
-        sc.cleanUpNullReferences();
-        Assert.assertArrayEquals(new String[] {"Daniel", "Male"}, sc.values().toArray(new
String[0]));
-    }
-}

http://git-wip-us.apache.org/repos/asf/groovy/blob/29727ea0/src/test/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCacheTest.java
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCacheTest.java b/src/test/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCacheTest.java
new file mode 100644
index 0000000..e78c6e2
--- /dev/null
+++ b/src/test/org/codehaus/groovy/runtime/memoize/ConcurrentCommonCacheTest.java
@@ -0,0 +1,175 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.codehaus.groovy.runtime.memoize;
+
+import org.apache.groovy.util.Maps;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+
+public class ConcurrentCommonCacheTest {
+    @Test
+    public void get() {
+        ConcurrentCommonCache<String, String> sc =
+                new ConcurrentCommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertEquals("Daniel", sc.get("name"));
+        Assert.assertEquals("Male", sc.get("gender"));
+        Assert.assertEquals("Shanghai", sc.get("city"));
+        Assert.assertNull(sc.get("foo"));
+    }
+
+    @Test
+    public void put() {
+        ConcurrentCommonCache<String, String> sc = new ConcurrentCommonCache<>();
+
+        Assert.assertNull(sc.put("name", "Daniel"));
+        Assert.assertEquals("Daniel", sc.get("name"));
+
+        Assert.assertEquals("Daniel", sc.put("name", "sunlan"));
+        Assert.assertEquals("sunlan", sc.get("name"));
+    }
+
+    @Test
+    public void getAndPut() {
+        ConcurrentCommonCache<String, String> sc = new ConcurrentCommonCache<>();
+
+        EvictableCache.ValueProvider vp =
+                new EvictableCache.ValueProvider<String, String>() {
+            @Override
+            public String provide(String key) {
+                return "Chinese";
+            }
+        };
+
+        Assert.assertEquals("Chinese", sc.getAndPut("language", vp,false));
+        Assert.assertNull(sc.get("language"));
+
+        Assert.assertEquals("Chinese", sc.getAndPut("language", vp));
+        Assert.assertEquals("Chinese", sc.get("language"));
+    }
+
+    @Test
+    public void values() {
+        ConcurrentCommonCache<String, String> sc =
+                new ConcurrentCommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertArrayEquals(new String[] {"Daniel", "Male", "Shanghai"}, sc.values().toArray(new
String[0]));
+    }
+
+    @Test
+    public void keys() {
+        ConcurrentCommonCache<String, String> sc =
+                new ConcurrentCommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertArrayEquals(new String[] {"name", "gender", "city"}, sc.keys().toArray(new
String[0]));
+    }
+
+    @Test
+    public void containsKey() {
+        ConcurrentCommonCache<String, String> sc =
+                new ConcurrentCommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertTrue(sc.containsKey("name"));
+    }
+
+    @Test
+    public void size() {
+        ConcurrentCommonCache<String, String> sc =
+                new ConcurrentCommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertEquals(3, sc.size());
+    }
+
+    @Test
+    public void remove() {
+        ConcurrentCommonCache<String, String> sc =
+                new ConcurrentCommonCache<>(
+                        new HashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertEquals("Shanghai", sc.remove("city"));
+        Assert.assertNull(sc.get("city"));
+    }
+
+    @Test
+    public void clear() {
+        ConcurrentCommonCache<String, String> sc =
+                new ConcurrentCommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", "Shanghai")
+                        )
+                );
+
+        Assert.assertArrayEquals(new String[] {"Daniel", "Male", "Shanghai"}, sc.values().toArray(new
String[0]));
+    }
+
+    @Test
+    public void cleanUpNullReferences() {
+        ConcurrentCommonCache<String, String> sc =
+                new ConcurrentCommonCache<>(
+                        new LinkedHashMap<>(
+                                Maps.of("name", "Daniel",
+                                        "gender", "Male",
+                                        "city", null)
+                        )
+                );
+
+        sc.cleanUpNullReferences();
+        Assert.assertArrayEquals(new String[] {"Daniel", "Male"}, sc.values().toArray(new
String[0]));
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/29727ea0/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
index 01201fd..13cf2b2 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
@@ -26,7 +26,7 @@ import org.codehaus.groovy.macro.runtime.Macro;
 import org.codehaus.groovy.runtime.m12n.ExtensionModule;
 import org.codehaus.groovy.runtime.m12n.ExtensionModuleScanner;
 import org.codehaus.groovy.runtime.m12n.MetaInfExtensionModule;
-import org.codehaus.groovy.runtime.memoize.CommonCache;
+import org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache;
 import org.codehaus.groovy.runtime.memoize.EvictableCache;
 import org.codehaus.groovy.transform.stc.ExtensionMethodNode;
 
@@ -44,7 +44,7 @@ import java.util.WeakHashMap;
  */
 class MacroMethodsCache {
     private static final ClassNode MACRO_ANNOTATION_CLASS_NODE = ClassHelper.make(Macro.class);
-    private static final CommonCache<ClassLoader, Map<String, List<MethodNode>>>
CACHE = new CommonCache<ClassLoader, Map<String, List<MethodNode>>>(new
WeakHashMap<ClassLoader, Map<String, List<MethodNode>>>());
+    private static final ConcurrentCommonCache<ClassLoader, Map<String, List<MethodNode>>>
CACHE = new ConcurrentCommonCache<ClassLoader, Map<String, List<MethodNode>>>(new
WeakHashMap<ClassLoader, Map<String, List<MethodNode>>>());
 
     public static Map<String, List<MethodNode>> get(final ClassLoader classLoader)
{
         return CACHE.getAndPut(classLoader, new EvictableCache.ValueProvider<ClassLoader,
Map<String, List<MethodNode>>>() {


Mime
View raw message