You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/07/09 14:21:12 UTC
[groovy] branch GROOVY-9631 updated: GROOVY-9631: Replace legacy
data structure with Java collection
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
The following commit(s) were added to refs/heads/GROOVY-9631 by this push:
new ec57d3e GROOVY-9631: Replace legacy data structure with Java collection
ec57d3e is described below
commit ec57d3ee9046223d4d0017dfbb41b72d474043ac
Author: Daniel Sun <su...@apache.org>
AuthorDate: Thu Jul 9 22:20:06 2020 +0800
GROOVY-9631: Replace legacy data structure with Java collection
---
.../metaclass/ThreadManagedMetaBeanProperty.java | 2 +-
.../groovy/util/AbstractConcurrentMap.java | 184 +-----------
.../groovy/util/AbstractConcurrentMapBase.java | 330 +++------------------
.../codehaus/groovy/util/ManagedConcurrentMap.java | 97 +-----
.../util/AbstractConcurrentMapSegmentTest.groovy | 193 ------------
.../groovy/util/ManagedConcurrentMapTest.groovy | 4 +-
6 files changed, 56 insertions(+), 754 deletions(-)
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
index 66ccc34..1554bce 100644
--- a/src/main/java/org/codehaus/groovy/util/AbstractConcurrentMap.java
+++ b/src/main/java/org/codehaus/groovy/util/AbstractConcurrentMap.java
@@ -18,190 +18,8 @@
*/
package org.codehaus.groovy.util;
-public abstract class AbstractConcurrentMap<K, V> extends AbstractConcurrentMapBase {
-
+public abstract class AbstractConcurrentMap<K, V> extends AbstractConcurrentMapBase<K, V> {
public AbstractConcurrentMap(ReferenceBundle 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
index ba66374..8735e61 100644
--- a/src/main/java/org/codehaus/groovy/util/AbstractConcurrentMapBase.java
+++ b/src/main/java/org/codehaus/groovy/util/AbstractConcurrentMapBase.java
@@ -19,313 +19,81 @@
package org.codehaus.groovy.util;
import java.util.Collection;
-import java.util.LinkedList;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
public abstract class AbstractConcurrentMapBase<K, V> {
- protected static final int MAXIMUM_CAPACITY = 1 << 30;
- final int segmentMask;
- final int segmentShift;
- protected final Segment[] segments;
+ private final ConcurrentHashMap<K, ManagedReference<V>> internalMap = new ConcurrentHashMap<>();
+ private ReferenceBundle bundle;
- public AbstractConcurrentMapBase(ReferenceBundle 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);
+ public AbstractConcurrentMapBase(ReferenceBundle bundle) {
+ this.bundle = bundle;
}
- protected abstract Segment createSegment(ReferenceBundle 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;
+ /**
+ * 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) {
+ ManagedReference<V> ref = internalMap.get(key);
+ if (ref != null) return ref.get();
+ return null;
}
- public Segment segmentFor(int hash) {
- return segments[(hash >>> segmentShift) & segmentMask];
+ /**
+ * 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) {
+ internalMap.put(key, toManagedReference(key, value));
}
- 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 V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+ return toValue(getOrPut(key, mappingFunction));
}
- 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 ManagedReference<V> getOrPut(K key, Function<? super K, ? extends V> mappingFunction) {
+ return internalMap.computeIfAbsent(key, k -> toManagedReference(k, mappingFunction.apply(k)));
}
- 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 V remove(Object key) {
+ return toValue(internalMap.remove(key));
}
- 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;
- }
- }
- }
+ public Collection<ManagedReference<V>> values() {
+ return internalMap.values();
+ }
- 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++;
- }
- }
- }
- }
- }
+ public int size() {
+ return internalMap.size();
+ }
- threshold = (int)(newTable.length * 0.75f);
+ private V toValue(ManagedReference<V> mv) {
+ if (null == mv) return null;
- table = newTable;
- count = newCount;
- }
+ return mv.get();
+ }
- 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;
- }
+ private ManagedReference<V> toManagedReference(K key, V value) {
+ ManagedReference<V> ref = new ManagedReference<V>(bundle, value) {
+ @Override
+ public void finalizeReference() {
+ internalMap.remove(key, this);
+ super.finalizeReference();
}
- 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;
- }
+ return ref;
}
public interface Entry<V> {
V getValue();
- void setValue(V value);
+ void setValue(V var1);
int getHash();
diff --git a/src/main/java/org/codehaus/groovy/util/ManagedConcurrentMap.java b/src/main/java/org/codehaus/groovy/util/ManagedConcurrentMap.java
index fb2bb11..c36f055 100644
--- a/src/main/java/org/codehaus/groovy/util/ManagedConcurrentMap.java
+++ b/src/main/java/org/codehaus/groovy/util/ManagedConcurrentMap.java
@@ -18,102 +18,13 @@
*/
package org.codehaus.groovy.util;
-public class ManagedConcurrentMap<K,V> extends AbstractConcurrentMap<K,V> {
+public class ManagedConcurrentMap<K, V> extends AbstractConcurrentMap<K, V> {
protected ReferenceBundle bundle;
+
public ManagedConcurrentMap(ReferenceBundle bundle) {
super(bundle);
- this.bundle = bundle;
- if (bundle==null) throw new IllegalArgumentException("bundle must not be null");
- }
-
- protected Segment<K,V> createSegment(ReferenceBundle 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);
- }
-
- 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");
-
- }
-
- 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 static class Entry<K,V> extends ManagedReference<K> implements AbstractConcurrentMap.Entry<K,V> {
- private final Segment segment;
- private final int hash;
-
- public Entry(ReferenceBundle bundle, Segment segment, K key, int hash) {
- super(bundle, key);
- this.segment = segment;
- this.hash = hash;
- }
-
- public boolean isValid() {
- return get() != null;
- }
- public boolean isEqual(K key, int hash) {
- return this.hash == hash && get() == key;
- }
-
- public V getValue() {
- return (V)this;
- }
-
- public void setValue(V value) {
- }
-
- public int getHash() {
- return hash;
- }
-
- @Override
- public void finalizeReference() {
- segment.removeEntry(this);
- super.finalizeReference();
- }
-
- /**
- * @deprecated use finalizeReference
- */
- @Deprecated
- public void finalizeRef() {
- finalizeReference();
- }
- }
-
- 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);
- }
-
- @Override
- public V getValue() {
- return value;
- }
-
- @Override
- public void setValue(V value) {
- this.value = value;
- }
-
- @Override
- public void finalizeReference() {
- value = null;
- super.finalizeReference();
- }
+ if (bundle == null) throw new IllegalArgumentException("bundle must not be null");
+ this.bundle = bundle;
}
}
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..e1e0b87 100644
--- a/src/test/org/codehaus/groovy/util/ManagedConcurrentMapTest.groovy
+++ b/src/test/org/codehaus/groovy/util/ManagedConcurrentMapTest.groovy
@@ -28,16 +28,14 @@ class ManagedConcurrentMapTest extends GroovyTestCase {
void testEntriesRemoveSelfFromMapWhenFinalized() {
List<ManagedReference<Object>> entries = []
for (int i = 0; i < 5; i++) {
- entries << map.getOrPut(new Object(), "Object ${i}")
+ entries << map.getOrPut(new Object(), k -> "Object ${i}")
}
assert map.size() == 5
- assert map.fullSize() == 5
entries*.finalizeReference()
assert map.size() == 0
- assert map.fullSize() == 0
}
}