This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY-9631
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit fc931d62b40507e93f03abb33196784d640a7845
Author: Daniel Sun <[email protected]>
AuthorDate: Fri Jul 10 01:25:05 2020 +0800

    GROOVY-9631: Replace legacy data structure with Java collection
---
 .../groovy/reflection/GroovyClassValueFactory.java |   7 +-
 .../reflection/GroovyClassValuePreJava7.java       | 106 -------
 .../metaclass/ThreadManagedMetaBeanProperty.java   |   2 +-
 .../groovy/util/AbstractConcurrentMap.java         | 207 -------------
 .../groovy/util/AbstractConcurrentMapBase.java     | 336 ---------------------
 .../codehaus/groovy/util/ManagedConcurrentMap.java | 148 ++++-----
 .../util/AbstractConcurrentMapSegmentTest.groovy   | 193 ------------
 .../groovy/util/ManagedConcurrentMapTest.groovy    |   2 -
 8 files changed, 80 insertions(+), 921 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/reflection/GroovyClassValueFactory.java 
b/src/main/java/org/codehaus/groovy/reflection/GroovyClassValueFactory.java
index 0565f92..b761895 100644
--- a/src/main/java/org/codehaus/groovy/reflection/GroovyClassValueFactory.java
+++ b/src/main/java/org/codehaus/groovy/reflection/GroovyClassValueFactory.java
@@ -18,7 +18,6 @@
  */
 package org.codehaus.groovy.reflection;
 
-import org.apache.groovy.util.SystemUtil;
 import org.codehaus.groovy.reflection.GroovyClassValue.ComputeValue;
 import org.codehaus.groovy.reflection.v7.GroovyClassValueJava7;
 
@@ -29,11 +28,7 @@ class GroovyClassValueFactory {
         * See https://bugs.openjdk.java.net/browse/JDK-8136353
         * This issue does not exist on IBM Java (J9) so use ClassValue by 
default on that JVM.
         */
-       private static final boolean USE_CLASSVALUE = 
Boolean.parseBoolean(SystemUtil.getSystemPropertySafe("groovy.use.classvalue", 
"true"));
-
        public static <T> GroovyClassValue<T> 
createGroovyClassValue(ComputeValue<T> computeValue) {
-               return (USE_CLASSVALUE)
-                ? new GroovyClassValueJava7<>(computeValue)
-                : new GroovyClassValuePreJava7<>(computeValue);
+               return new GroovyClassValueJava7<>(computeValue);
        }
 }
diff --git 
a/src/main/java/org/codehaus/groovy/reflection/GroovyClassValuePreJava7.java 
b/src/main/java/org/codehaus/groovy/reflection/GroovyClassValuePreJava7.java
deleted file mode 100644
index 02f893c..0000000
--- a/src/main/java/org/codehaus/groovy/reflection/GroovyClassValuePreJava7.java
+++ /dev/null
@@ -1,106 +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.reflection;
-
-import org.codehaus.groovy.util.Finalizable;
-import org.codehaus.groovy.util.ManagedConcurrentMap;
-import org.codehaus.groovy.util.ReferenceBundle;
-
-/** Approximation of Java 7's {@link java.lang.ClassValue} that works on 
earlier versions of Java.
- * Note that this implementation isn't as good at Java 7's; it doesn't allow 
for some GC'ing that Java 7 would allow.
- * But, it's good enough for our use.
- *
- * @param <T>
- */
-class GroovyClassValuePreJava7<T> implements GroovyClassValue<T> {
-       private static final ReferenceBundle weakBundle = 
ReferenceBundle.getWeakBundle();
-
-       private class EntryWithValue extends 
ManagedConcurrentMap.EntryWithValue<Class<?>,T>{
-
-               public EntryWithValue(GroovyClassValuePreJava7Segment segment, 
Class<?> key, int hash) {
-                       super(weakBundle, segment, key, hash, 
computeValue.computeValue(key));
-               }
-
-               @Override
-               public void setValue(T value) {
-                       if(value!=null) super.setValue(value);
-               }
-
-               @Override
-               public void finalizeReference() {
-                       T value = getValue();
-                       if (value instanceof Finalizable) {
-                               ((Finalizable) value).finalizeReference();
-                       }
-                       super.finalizeReference();
-               }
-       }
-
-       private class GroovyClassValuePreJava7Segment extends 
ManagedConcurrentMap.Segment<Class<?>,T> {
-
-        private static final long serialVersionUID = 1289753977947029168L;
-
-        GroovyClassValuePreJava7Segment(ReferenceBundle bundle, int 
initialCapacity) {
-                       super(bundle, initialCapacity);
-               }
-
-               @Override
-               protected EntryWithValue createEntry(Class<?> key, int hash,
-                               T unused) {
-                       return new EntryWithValue(this, key, hash);
-               }
-       }
-
-       private class GroovyClassValuePreJava7Map extends 
ManagedConcurrentMap<Class<?>,T> {
-
-               public GroovyClassValuePreJava7Map() {
-                       super(weakBundle);
-               }
-
-               @Override
-               protected GroovyClassValuePreJava7Segment createSegment(Object 
segmentInfo, int cap) {
-                       ReferenceBundle bundle = (ReferenceBundle) segmentInfo;
-                       if (bundle==null) throw new 
IllegalArgumentException("bundle must not be null ");
-                       return new GroovyClassValuePreJava7Segment(bundle, cap);
-               }
-
-       }
-
-       private final ComputeValue<T> computeValue;
-
-       private final GroovyClassValuePreJava7Map map = new 
GroovyClassValuePreJava7Map();
-
-       public GroovyClassValuePreJava7(ComputeValue<T> computeValue){
-               this.computeValue = computeValue;
-       }
-
-       @Override
-       public T get(Class<?> type) {
-               // the value isn't use in the getOrPut call - see the 
EntryWithValue constructor above
-               T value = ((EntryWithValue)map.getOrPut(type, null)).getValue();
-               //all entries are guaranteed to be EntryWithValue. Value can 
only be null if computeValue returns null
-               return value;
-       }
-
-       @Override
-       public void remove(Class<?> type) {
-               map.remove(type);
-       }
-
-}
diff --git 
a/src/main/java/org/codehaus/groovy/runtime/metaclass/ThreadManagedMetaBeanProperty.java
 
b/src/main/java/org/codehaus/groovy/runtime/metaclass/ThreadManagedMetaBeanProperty.java
index 5074908..b6ac4cf 100644
--- 
a/src/main/java/org/codehaus/groovy/runtime/metaclass/ThreadManagedMetaBeanProperty.java
+++ 
b/src/main/java/org/codehaus/groovy/runtime/metaclass/ThreadManagedMetaBeanProperty.java
@@ -176,7 +176,7 @@ public class ThreadManagedMetaBeanProperty extends 
MetaBeanProperty {
            * @see groovy.lang.MetaMethod#invoke(java.lang.Object, 
java.lang.Object[])
            */
         public Object invoke(Object object, Object[] arguments) {
-            return instance2Prop.getOrPut(object, 
getInitialValue()).getValue();
+            return instance2Prop.computeIfAbsent(object, k -> 
getInitialValue());
         }
     }
 
diff --git a/src/main/java/org/codehaus/groovy/util/AbstractConcurrentMap.java 
b/src/main/java/org/codehaus/groovy/util/AbstractConcurrentMap.java
deleted file mode 100644
index 6168877..0000000
--- a/src/main/java/org/codehaus/groovy/util/AbstractConcurrentMap.java
+++ /dev/null
@@ -1,207 +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.util;
-
-public abstract class AbstractConcurrentMap<K, V> extends 
AbstractConcurrentMapBase {
-
-    public AbstractConcurrentMap(Object segmentInfo) {
-        super(segmentInfo);
-    }
-
-    public Segment segmentFor (int hash) {
-        return (Segment) super.segmentFor(hash);
-    }
-
-    public V get(K key) {
-        int hash = hash(key);
-        return (V) segmentFor(hash).get(key, hash);
-    }
-
-    public Entry<K,V> getOrPut(K key, V value) {
-        int hash = hash(key);
-        return segmentFor(hash).getOrPut(key, hash, value);
-    }
-
-    public void put(K key, V value) {
-        int hash = hash(key);
-        segmentFor(hash).put(key, hash, value);
-    }
-
-    public void remove(K key) {
-        int hash = hash(key);
-        segmentFor(hash).remove(key, hash);
-    }
-
-    public abstract static class Segment<K,V> extends 
AbstractConcurrentMapBase.Segment {
-
-        private static final long serialVersionUID = -2392526467736920612L;
-
-        protected Segment(int initialCapacity) {
-            super(initialCapacity);
-        }
-
-        public final V get(K key, int hash) {
-            Object[] tab = table;
-            Object o = tab[hash & (tab.length - 1)];
-            if (o != null) {
-                if (o instanceof Entry) {
-                    Entry<K,V> e = (Entry) o;
-                    if (e.isEqual(key, hash)) {
-                        return e.getValue();
-                    }
-                }
-                else {
-                    Object[] arr = (Object[]) o;
-                    for (Object value : arr) {
-                        Entry<K, V> e = (Entry<K, V>) value;
-                        if (e != null && e.isEqual(key, hash)) {
-                            return e.getValue();
-                        }
-                    }
-                }
-            }
-            return null;
-        }
-
-        public final Entry<K,V> getOrPut(K key, int hash, V value) {
-            Object[] tab = table;
-            Object o = tab[hash & (tab.length - 1)];
-            if (o != null) {
-                if (o instanceof Entry) {
-                    Entry<K,V> e = (Entry) o;
-                    if (e.isEqual(key, hash)) {
-                        return e;
-                    }
-                }
-                else {
-                    Object[] arr = (Object[]) o;
-                    for (Object item : arr) {
-                        Entry<K, V> e = (Entry<K, V>) item;
-                        if (e != null && e.isEqual(key, hash)) {
-                            return e;
-                        }
-                    }
-                }
-            }
-            return put(key, hash, value);
-        }
-
-        public final Entry put(K key, int hash, V value) {
-            lock();
-            try {
-                rehashIfThresholdExceeded();
-
-                Object[] tab = table;
-                int index = hash & (tab.length - 1);
-                Object o = tab[index];
-                if (o != null) {
-                    if (o instanceof Entry) {
-                        Entry e = (Entry) o;
-                        if (e.isEqual(key, hash)) {
-                            e.setValue(value);
-                            return e;
-                        }
-                        else {
-                            Object[] arr = new Object [2];
-                            final Entry ee = createEntry(key, hash, value);
-                            arr [0] = ee;
-                            arr [1] = e;
-                            tab[index] = arr;
-                            count++;
-                            return ee;
-                        }
-                    }
-                    else {
-                        Object[] arr = (Object[]) o;
-                        for (Object item : arr) {
-                            Entry e = (Entry) item;
-                            if (e != null && e.isEqual(key, hash)) {
-                                e.setValue(value);
-                                return e;
-                            }
-                        }
-
-                        final Entry ee = createEntry(key, hash, value);
-                        for (int i = 0; i < arr.length; i++) {
-                            Entry e = (Entry) arr[i];
-                            if (e == null) {
-                                arr [i] = ee;
-                                count++;
-                                return ee;
-                            }
-                        }
-
-                        Object[] newArr = new Object[arr.length+1];
-                        newArr [0] = ee;
-                        System.arraycopy(arr, 0, newArr, 1, arr.length);
-                        tab [index] = newArr;
-                        count++;
-                        return ee;
-                    }
-                }
-
-                Entry e = createEntry(key, hash, value);
-                tab[index] = e;
-                count++; // write-volatile
-                return e;
-            } finally {
-                unlock();
-            }
-        }
-
-        public void remove(K key, int hash) {
-            lock();
-            try {
-                int c = count-1;
-                final Object[] tab = table;
-                final int index = hash & (tab.length - 1);
-                Object o = tab[index];
-
-                if (o != null) {
-                    if (o instanceof Entry) {
-                        if (((Entry<K,V>)o).isEqual(key, hash)) {
-                          tab[index] = null;
-                          count = c;
-                        }
-                    }
-                    else {
-                        Object[] arr = (Object[]) o;
-                        for (int i = 0; i < arr.length; i++) {
-                            Entry<K,V> e = (Entry<K,V>) arr[i];
-                            if (e != null && e.isEqual(key, hash)) {
-                                arr [i] = null;
-                                count = c;
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-            finally {
-                unlock();
-            }
-        }
-
-        protected abstract Entry<K,V> createEntry(K key, int hash, V value);
-    }
-
-    public interface Entry<K, V> extends AbstractConcurrentMapBase.Entry<V>{
-        boolean isEqual(K key, int hash);
-    }
-}
diff --git 
a/src/main/java/org/codehaus/groovy/util/AbstractConcurrentMapBase.java 
b/src/main/java/org/codehaus/groovy/util/AbstractConcurrentMapBase.java
deleted file mode 100644
index 01f84af..0000000
--- a/src/main/java/org/codehaus/groovy/util/AbstractConcurrentMapBase.java
+++ /dev/null
@@ -1,336 +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.util;
-
-import java.util.Collection;
-import java.util.LinkedList;
-
-public abstract class AbstractConcurrentMapBase {
-    protected static final int MAXIMUM_CAPACITY = 1 << 30;
-    static final int MAX_SEGMENTS = 1 << 16;
-    static final int RETRIES_BEFORE_LOCK = 2;
-    final int segmentMask;
-    final int segmentShift;
-    protected final Segment[] segments;
-
-    public AbstractConcurrentMapBase(Object segmentInfo) {
-        int sshift = 0;
-        int ssize = 1;
-        while (ssize < 16) {
-            ++sshift;
-            ssize <<= 1;
-        }
-        segmentShift = 32 - sshift;
-        segmentMask = ssize - 1;
-        this.segments = new Segment[ssize];
-
-        int c = 512 / ssize;
-        if (c * ssize < 512)
-            ++c;
-        int cap = 1;
-        while (cap < c)
-            cap <<= 1;
-
-        for (int i = 0; i < this.segments.length; ++i)
-            this.segments[i] = createSegment(segmentInfo, cap);
-    }
-
-    protected abstract Segment createSegment(Object segmentInfo, int cap);
-
-    protected static <K> int hash(K key) {
-        int h = System.identityHashCode(key);
-        h += ~(h << 9);
-        h ^=  (h >>> 14);
-        h +=  (h << 4);
-        h ^=  (h >>> 10);
-        return h;
-    }
-
-    public Segment segmentFor(int hash) {
-        return segments[(hash >>> segmentShift) & segmentMask];
-    }
-
-    public int fullSize() {
-        int count = 0;
-        for (Segment segment : segments) {
-            segment.lock();
-            try {
-                for (int j = 0; j < segment.table.length; j++) {
-                    Object o = segment.table[j];
-                    if (o != null) {
-                        if (o instanceof Entry) {
-                            count++;
-                        } else {
-                            Object[] arr = (Object[]) o;
-                            count += arr.length;
-                        }
-                    }
-                }
-            } finally {
-                segment.unlock();
-            }
-        }
-        return count;
-    }
-
-    public int size() {
-        int count = 0;
-        for (Segment segment : segments) {
-            segment.lock();
-            try {
-                for (int j = 0; j < segment.table.length; j++) {
-                    Object o = segment.table[j];
-                    if (o != null) {
-                        if (o instanceof Entry) {
-                            Entry e = (Entry) o;
-                            if (e.isValid())
-                                count++;
-                        } else {
-                            Object[] arr = (Object[]) o;
-                            for (Object value : arr) {
-                                Entry info = (Entry) value;
-                                if (info != null && info.isValid())
-                                    count++;
-                            }
-                        }
-                    }
-                }
-            } finally {
-                segment.unlock();
-            }
-        }
-        return count;
-    }
-
-    public Collection values() {
-        Collection result = new LinkedList();
-        for (Segment segment : segments) {
-            segment.lock();
-            try {
-                for (int j = 0; j < segment.table.length; j++) {
-                    Object o = segment.table[j];
-                    if (o != null) {
-                        if (o instanceof Entry) {
-                            Entry e = (Entry) o;
-                            if (e.isValid())
-                                result.add(e);
-                        } else {
-                            Object[] arr = (Object[]) o;
-                            for (Object value : arr) {
-                                Entry info = (Entry) value;
-                                if (info != null && info.isValid())
-                                    result.add(info);
-                            }
-                        }
-                    }
-                }
-            } finally {
-                segment.unlock();
-            }
-        }
-        return result;
-    }
-
-    public static class Segment extends LockableObject {
-        private static final long serialVersionUID = -4128828550135386431L;
-        volatile int count;
-
-        int threshold;
-
-        protected volatile Object[] table;
-
-        protected Segment(int initialCapacity) {
-            setTable(new Object[initialCapacity]);
-        }
-
-        void setTable(Object[] newTable) {
-            threshold = (int) (newTable.length * 0.75f);
-            table = newTable;
-        }
-
-        void removeEntry (Entry e) {
-            lock ();
-            int newCount = count;
-            try {
-                Object [] tab = table;
-                int index = e.getHash() & (tab.length-1);
-                Object o = tab[index];
-                if (o != null) {
-                    if (o instanceof Entry) {
-                        if (o == e) {
-                            tab [index] = null;
-                            newCount--;
-                        }
-                    }
-                    else {
-                        Object[] arr = (Object[]) o;
-                        Object res = null;
-                        for (Object value : arr) {
-                            Entry info = (Entry) value;
-                            if (info != null) {
-                                if (info != e) {
-                                    if (info.isValid()) {
-                                        res = put(info, res);
-                                    } else {
-                                        newCount--;
-                                    }
-                                } else {
-                                    newCount--;
-                                }
-                            }
-                        }
-                        tab [index] = res;
-                    }
-                    count = newCount;
-                }
-            }
-            finally {
-                unlock();
-            }
-        }
-
-        void rehashIfThresholdExceeded() {
-            if(count > threshold) {
-                rehash();
-            }
-        }
-
-        void rehash() {
-            Object[] oldTable = table;
-            int oldCapacity = oldTable.length;
-            if (oldCapacity >= MAXIMUM_CAPACITY)
-                return;
-
-            int newCount = 0;
-            for (int i = 0; i < oldCapacity ; i++) {
-                Object o = oldTable [i];
-                if (o != null) {
-                    if (o instanceof Entry) {
-                        Entry e = (Entry) o;
-                        if (e.isValid()) {
-                            newCount++;
-                        }
-                        else {
-                            oldTable[i] = null;
-                        }
-                    }
-                    else {
-                        Object[] arr = (Object[]) o;
-                        int localCount = 0;
-                        for (int index = 0; index < arr.length; index++) {
-                            Entry e = (Entry) arr[index];
-                            if (e != null && e.isValid()) {
-                                localCount++;
-                            }
-                            else {
-                                arr [index] = null;
-                            }
-                        }
-                        if (localCount == 0)
-                          oldTable[i] = null;
-                        else
-                          newCount += localCount;
-                    }
-                }
-            }
-
-            Object[] newTable = new Object[newCount+1 < threshold ? 
oldCapacity : oldCapacity << 1];
-            int sizeMask = newTable.length - 1;
-            newCount = 0;
-            for (Object o : oldTable) {
-                if (o != null) {
-                    if (o instanceof Entry) {
-                        Entry e = (Entry) o;
-                        if (e.isValid()) {
-                            int index = e.getHash() & sizeMask;
-                            put(e, index, newTable);
-                            newCount++;
-                        }
-                    } else {
-                        Object[] arr = (Object[]) o;
-                        for (Object value : arr) {
-                            Entry e = (Entry) value;
-                            if (e != null && e.isValid()) {
-                                int index = e.getHash() & sizeMask;
-                                put(e, index, newTable);
-                                newCount++;
-                            }
-                        }
-                    }
-                }
-            }
-
-            threshold = (int)(newTable.length * 0.75f);
-
-            table = newTable;
-            count = newCount;
-        }
-
-        private static void put(Entry ee, int index, Object[] tab) {
-            Object o = tab[index];
-            if (o != null) {
-                if (o instanceof Entry) {
-                    Object[] arr = new Object [2];
-                    arr [0] = ee;
-                    arr [1] = o;
-                    tab[index] = arr;
-                    return;
-                }
-                else {
-                    Object[] arr = (Object[]) o;
-                    Object[] newArr = new Object[arr.length+1];
-                    newArr [0] = ee;
-                    System.arraycopy(arr, 0, newArr, 1, arr.length);
-                    tab [index] = newArr;
-                    return;
-                }
-            }
-            tab[index] = ee;
-        }
-
-        private static Object put(Entry ee, Object o) {
-            if (o != null) {
-                if (o instanceof Entry) {
-                    Object[] arr = new Object [2];
-                    arr [0] = ee;
-                    arr [1] = o;
-                    return arr;
-                }
-                else {
-                    Object[] arr = (Object[]) o;
-                    Object[] newArr = new Object[arr.length+1];
-                    newArr [0] = ee;
-                    System.arraycopy(arr, 0, newArr, 1, arr.length);
-                    return newArr;
-                }
-            }
-            return ee;
-        }
-    }
-
-    public interface Entry<V> {
-        V getValue();
-
-        void setValue(V value);
-
-        int getHash();
-
-        boolean isValid();
-    }
-}
diff --git a/src/main/java/org/codehaus/groovy/util/ManagedConcurrentMap.java 
b/src/main/java/org/codehaus/groovy/util/ManagedConcurrentMap.java
index d1cf760..89e4a21 100644
--- a/src/main/java/org/codehaus/groovy/util/ManagedConcurrentMap.java
+++ b/src/main/java/org/codehaus/groovy/util/ManagedConcurrentMap.java
@@ -18,102 +18,110 @@
  */
 package org.codehaus.groovy.util;
 
-public class ManagedConcurrentMap<K,V> extends AbstractConcurrentMap<K,V> {
-    protected ReferenceBundle bundle;
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class ManagedConcurrentMap<K, V> {
+    private final ConcurrentMap<Key<K>, ManagedReference<V>> internalMap = new 
ConcurrentHashMap<>();
+    private final ReferenceBundle bundle;
+
     public ManagedConcurrentMap(ReferenceBundle bundle) {
-        super(bundle);
+        if (bundle == null) throw new IllegalArgumentException("bundle must 
not be null");
         this.bundle = bundle;
-        if (bundle==null) throw new IllegalArgumentException("bundle must not 
be null");
     }
 
-    protected Segment<K,V> createSegment(Object segmentInfo, int cap) {
-        ReferenceBundle bundle = (ReferenceBundle) segmentInfo;
-        if (bundle==null) throw new IllegalArgumentException("bundle must not 
be null");
-        return new ManagedConcurrentMap.Segment<K,V>(bundle, cap);
+    /**
+     * Returns the value stored for the given key at the point of call.
+     *
+     * @param key a non null key
+     * @return the value stored in the map for the given key
+     */
+    public V get(Object key) {
+        return toValue(internalMap.get(new Key(key)));
     }
 
-    public static class Segment<K,V> extends 
AbstractConcurrentMap.Segment<K,V>{
-        private static final long serialVersionUID = 2742952509311037869L;
-        protected final ReferenceBundle bundle;
-        public Segment(ReferenceBundle bundle, int cap) {
-            super(cap);
-            this.bundle = bundle;
-            if (bundle==null) throw new IllegalArgumentException("bundle must 
not be null");
-
-        }
+    /**
+     * Sets a new value for a given key. an older value is overwritten.
+     *
+     * @param key   a non null key
+     * @param value the new value
+     */
+    public void put(final K key, V value) {
+        final Key<K> k = new Key<K>(key);
+        internalMap.put(k, toManagedReference(k, value));
+    }
 
-        protected AbstractConcurrentMap.Entry<K,V> createEntry(K key, int 
hash, V value) {
-            if (bundle==null) throw new IllegalArgumentException("bundle must 
not be null");
-            return new EntryWithValue<K,V>(bundle, this, key, hash, value);
-        }
+    public V computeIfAbsent(K key, Function<? super K, ? extends V> 
mappingFunction) {
+        return toValue(getOrPut(key, mappingFunction));
     }
 
-    public static class Entry<K,V> extends ManagedReference<K> implements 
AbstractConcurrentMap.Entry<K,V> {
-        private final Segment segment;
-        private final int hash;
+    public ManagedReference<V> getOrPut(K key, V value) {
+        return getOrPut(key, k -> value);
+    }
 
-        public Entry(ReferenceBundle bundle, Segment segment, K key, int hash) 
{
-            super(bundle, key);
-            this.segment = segment;
-            this.hash = hash;
-        }
+    private ManagedReference<V> getOrPut(K key, Function<? super K, ? extends 
V> mappingFunction) {
+        final Key<K> key1 = new Key<K>(key);
+        return internalMap.computeIfAbsent(key1, k -> toManagedReference(key1, 
mappingFunction.apply(k.key)));
+    }
 
-        public boolean isValid() {
-            return get() != null;
-        }
+    public V remove(Object key) {
+        return toValue(internalMap.remove(new Key(key)));
+    }
 
-        public boolean isEqual(K key, int hash) {
-            return this.hash == hash && get() == key;
-        }
+    public Collection<V> values() {
+        return 
internalMap.values().stream().map(this::toValue).collect(Collectors.toList());
+    }
 
-        public V getValue() {
-            return (V)this;
-        }
+    public int size() {
+        return internalMap.size();
+    }
 
-        public void setValue(V value) {
-        }
+    private V toValue(ManagedReference<V> mv) {
+        if (null == mv) return null;
 
-        public int getHash() {
-            return hash;
-        }
+        return mv.get();
+    }
 
-        @Override
-        public void finalizeReference() {
-            segment.removeEntry(this);
-            super.finalizeReference();
-        }
+    private ManagedReference<V> toManagedReference(Key<K> key, V value) {
+        ManagedReference<V> ref = new ManagedReference<V>(bundle, value) {
+            @Override
+            public void finalizeReference() {
+                internalMap.remove(key, this);
+                super.finalizeReference();
+            }
+        };
 
-        /**
-         * @deprecated use finalizeReference
-         */
-        @Deprecated
-        public void finalizeRef() {
-            finalizeReference();
-        }
+        return ref;
     }
 
-    public static class EntryWithValue<K,V> extends Entry<K,V> {
-        private V value;
-
-        public EntryWithValue(ReferenceBundle bundle, Segment segment, K key, 
int hash, V value) {
-            super(bundle, segment, key, hash);
-            setValue(value);
-        }
+    private static class Key<K> {
+        K key;
 
-        @Override
-        public V getValue() {
-            return value;
+        Key(K key) {
+            this.key = key;
         }
 
         @Override
-        public void setValue(V value) {
-            this.value = value;
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Key)) return false;
+            Key<?> other = (Key<?>) o;
+            return key == other.key;
         }
 
         @Override
-        public void finalizeReference() {
-            value = null;
-            super.finalizeReference();
+        public int hashCode() {
+            int hash = System.identityHashCode(key);
+            hash += (hash << 15) ^ 0xffffcd7d;
+            hash ^= (hash >>> 10);
+            hash += (hash << 3);
+            hash ^= (hash >>> 6);
+            hash += (hash << 2) + (hash << 14);
+            hash ^= (hash >>> 16);
+            return hash;
         }
     }
 }
diff --git 
a/src/test/org/codehaus/groovy/util/AbstractConcurrentMapSegmentTest.groovy 
b/src/test/org/codehaus/groovy/util/AbstractConcurrentMapSegmentTest.groovy
deleted file mode 100644
index 4f275f5..0000000
--- a/src/test/org/codehaus/groovy/util/AbstractConcurrentMapSegmentTest.groovy
+++ /dev/null
@@ -1,193 +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.util
-
-import org.junit.Before
-import org.junit.Test
-
-class AbstractConcurrentMapSegmentTest {
-    private static final Integer INITIAL_SEGMENT_SIZE = 100
-    private static final Integer SEGMENT_THRESHOLD = 0.75f * 
INITIAL_SEGMENT_SIZE
-
-    // Incrementing counter used to generate unique key names for TestEntry 
objects
-    // across all test methods in this class
-    private static int keyId
-
-    TestSegment segment
-    List<TestEntry> entries = []
-    int rehashCount = 0
-
-    @Before
-    public void setUp() throws Exception {
-        segment = new TestSegment(INITIAL_SEGMENT_SIZE)
-    }
-
-    @Test
-    public void testSegmentWillNotRehash() {
-        whenIAddElements(50)
-        thenRehashHappenedTimes(0)
-        thenSegmentExpands(false)
-    }
-
-    @Test
-    public void testSegmentWillNotRehashEdgeCase() {
-        whenIAddElements(SEGMENT_THRESHOLD + 1)
-        thenRehashHappenedTimes(0)
-        thenSegmentExpands(false)
-    }
-
-    @Test
-    public void testSegmentWillRehashAndExpand() {
-        whenIAddElements(SEGMENT_THRESHOLD + 2)
-        thenRehashHappenedTimes(1)
-        thenSegmentExpands(true)
-    }
-
-    @Test
-    public void testSegmentWillRehashAndExpandManyTimes() {
-        int elementCount = (SEGMENT_THRESHOLD + 1 ) * 6
-        whenIAddElements(elementCount)
-        //456 elements fit into segment of size 800, which is 100 * 2 * 2 * 2
-        thenSegmentSizeIs(INITIAL_SEGMENT_SIZE * 2 * 2 * 2)
-        thenRehashHappenedTimes(3)
-    }
-
-    @Test
-    public void testSegmentWillRehashWithNoExpansion() {
-        whenIAddElements(SEGMENT_THRESHOLD)
-        whenISetElementsAsInvalid(50)
-        whenIAddElements(50)
-        thenRehashHappenedTimes(1)
-        thenSegmentExpands(false)
-    }
-
-    @Test
-    public void testSegmentWillRehashAndEventuallyExpand() {
-        whenIAddElements(SEGMENT_THRESHOLD)
-
-        // 1-st rehash
-        whenISetElementsAsInvalid(50)
-        whenIAddElements(50)
-        thenSegmentExpands(false)
-
-        // 2-nd rehash
-        whenISetElementsAsInvalid(30)
-        whenIAddElements(30)
-        thenSegmentExpands(false)
-
-        // 3-nd rehash
-        whenISetElementsAsInvalid(20)
-        whenIAddElements(20)
-        thenSegmentExpands(false)
-
-        // 4-th rehash with none invalid => expansion: segment * 2
-        whenIAddElements(SEGMENT_THRESHOLD)
-
-        thenRehashHappenedTimes(4)
-        thenSegmentSizeIs(INITIAL_SEGMENT_SIZE * 2)
-    }
-
-    private void whenIAddElements(int count) {
-        count.times {
-            String key = "k:${++keyId}-${it}"
-            segment.put(key, key.hashCode(), "v${it}")
-        }
-    }
-
-    private void whenISetElementsAsInvalid(int count) {
-        List<TestEntry> validEntires = entries.findAll { it.isValid() }
-        count.times {
-            validEntires.get(it).setValid(false)
-        }
-    }
-
-    private void thenRehashHappenedTimes(int expectedRehashCount) {
-        assert rehashCount == expectedRehashCount
-    }
-
-    private void thenSegmentSizeIs(int expectedSize) {
-        assert segment.table.length == expectedSize
-    }
-
-    private void thenSegmentExpands(boolean truth) {
-        assert segment.table.length > INITIAL_SEGMENT_SIZE == truth
-    }
-
-    class TestSegment extends 
org.codehaus.groovy.util.AbstractConcurrentMap.Segment {
-
-        protected TestSegment(int initialCapacity) {
-            super(initialCapacity)
-        }
-
-        @Override
-        protected org.codehaus.groovy.util.AbstractConcurrentMap.Entry 
createEntry(Object key, int hash, Object value) {
-            TestEntry entry = new TestEntry(key, hash, value)
-            entries.add(entry)
-            return entry
-        }
-
-        @Override
-        void rehash() {
-            rehashCount++
-            super.rehash()
-        }
-    }
-}
-
-class TestEntry implements 
org.codehaus.groovy.util.AbstractConcurrentMap.Entry {
-    Object key
-    Object value
-    int hash
-    boolean valid = true;
-
-    public TestEntry(Object key, int hash, Object value) {
-        this.key = key
-        this.hash = hash
-        this.value = value
-    }
-
-    @Override
-    boolean isEqual(Object key, int hash) {
-        return hash == this.hash && key.equals(this.key)
-    }
-
-    @Override
-    Object getValue() {
-        return value
-    }
-
-    @Override
-    void setValue(Object value) {
-        this.value = value
-    }
-
-    @Override
-    int getHash() {
-        return hash
-    }
-
-    @Override
-    boolean isValid() {
-        return valid
-    }
-
-    public void setValid(boolean valid) {
-        this.valid = valid
-    }
-}
diff --git a/src/test/org/codehaus/groovy/util/ManagedConcurrentMapTest.groovy 
b/src/test/org/codehaus/groovy/util/ManagedConcurrentMapTest.groovy
index d87704f..357e37d 100644
--- a/src/test/org/codehaus/groovy/util/ManagedConcurrentMapTest.groovy
+++ b/src/test/org/codehaus/groovy/util/ManagedConcurrentMapTest.groovy
@@ -32,12 +32,10 @@ class ManagedConcurrentMapTest extends GroovyTestCase {
         }
 
         assert map.size() == 5
-        assert map.fullSize() == 5
 
         entries*.finalizeReference()
 
         assert map.size() == 0
-        assert map.fullSize() == 0
     }
 
 }

Reply via email to