From fd91368197b64003e586716e3ef2c5361fc57e95 Mon Sep 17 00:00:00 2001 From: Rob Austin Date: Thu, 24 Jul 2014 11:07:36 +0100 Subject: [PATCH] HCOLL-119 Add Lamda support to SHM --- .../openhft/chronicle/map/ChronicleMap.java | 325 +++++++++ .../chronicle/map/ChronicleMapBuilder.java | 30 + .../collections/ChronicleMapBuilder0.java | 150 +++++ .../ChronicleReplicatedHashMap.java | 35 + .../collections/ConcurrentHashMap2.java | 25 + .../collections/ConcurrentHashMap3.java | 159 +++++ .../java/net/openhft/collections/VSHM.java | 36 + .../chronicle/map/ConcurrentHashMap8Test.java | 279 +++++--- .../map/others/ConcurrentAssociateTest.java | 163 ----- .../map/others/ConcurrentContainsKeyTest.java | 153 ----- .../map/others/DistinctEntrySetElements.java | 73 -- .../chronicle/map/others/LoopHelpers.java | 146 ---- .../chronicle/map/others/MapCheck.java | 635 ------------------ .../chronicle/map/others/MapLoops.java | 254 ------- .../openhft/chronicle/map/others/ToArray.java | 105 --- 15 files changed, 959 insertions(+), 1609 deletions(-) create mode 100644 src/main/java/net/openhft/chronicle/map/ChronicleMap.java create mode 100644 src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java create mode 100644 src/main/java/net/openhft/collections/ChronicleMapBuilder0.java create mode 100644 src/main/java/net/openhft/collections/ChronicleReplicatedHashMap.java create mode 100644 src/main/java/net/openhft/collections/ConcurrentHashMap2.java create mode 100644 src/main/java/net/openhft/collections/ConcurrentHashMap3.java create mode 100644 src/main/java/net/openhft/collections/VSHM.java delete mode 100644 src/test/java/net/openhft/chronicle/map/others/ConcurrentAssociateTest.java delete mode 100644 src/test/java/net/openhft/chronicle/map/others/ConcurrentContainsKeyTest.java delete mode 100644 src/test/java/net/openhft/chronicle/map/others/DistinctEntrySetElements.java delete mode 100644 src/test/java/net/openhft/chronicle/map/others/LoopHelpers.java delete mode 100644 src/test/java/net/openhft/chronicle/map/others/MapCheck.java delete mode 100644 src/test/java/net/openhft/chronicle/map/others/MapLoops.java delete mode 100644 src/test/java/net/openhft/chronicle/map/others/ToArray.java diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ChronicleMap.java new file mode 100644 index 000000000..fe1c0c5a9 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMap.java @@ -0,0 +1,325 @@ +/* + * Copyright 2014 Higher Frequency Trading + *

+ * http://www.higherfrequencytrading.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map; + +import net.openhft.collections.SharedHashMap; + +import java.util.Map; +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * @author Rob Austin. + */ +public interface ChronicleMap extends SharedHashMap { // }, ConcurrentHashMap3 { + + + + /** + * {@inheritDoc} + * + * @throws ClassCastException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @implNote This implementation assumes that the ConcurrentMap cannot contain null values and {@code + * get()} returning null unambiguously means the key is absent. Implementations which support null values + * must override this default implementation. + * @since 1.8 + */ + default V getOrDefault(Object key, V defaultValue) { + V v; + return ((v = get(key)) != null) ? v : defaultValue; + } + + /** + * {@inheritDoc} + * + * @throws NullPointerException {@inheritDoc} + * @implSpec The default implementation is equivalent to, for this {@code map}: + *

 {@code
+     * for ((Map.Entry entry : map.entrySet())
+     *     action.accept(entry.getKey(), entry.getValue());
+     * }
+ * @implNote The default implementation assumes that {@code IllegalStateException} thrown by {@code + * getKey()} or {@code getValue()} indicates that the entry has been removed and cannot be processed. + * Operation continues for subsequent entries. + * @since 1.8 + */ + default void forEach(BiConsumer action) { + Objects.requireNonNull(action); + for (Map.Entry entry : entrySet()) { + K k; + V v; + try { + k = entry.getKey(); + v = entry.getValue(); + } catch (IllegalStateException ise) { + // this usually means the entry is no longer in the map. + continue; + } + action.accept(k, v); + } + } + + + /** + * {@inheritDoc} + * + * @throws UnsupportedOperationException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @throws ClassCastException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} + * @implSpec

The default implementation is equivalent to, for this {@code map}: + *

 {@code
+     * for ((Map.Entry entry : map.entrySet())
+     *     do {
+     *        K k = entry.getKey();
+     *        V v = entry.getValue();
+     *     } while(!replace(k, v, function.apply(k, v)));
+     * }
+ * + * The default implementation may retry these steps when multiple threads attempt updates including + * potentially calling the function repeatedly for a given key. + * + *

This implementation assumes that the ConcurrentMap cannot contain null values and {@code get()} + * returning null unambiguously means the key is absent. Implementations which support null values + * must override this default implementation. + * @since 1.8 + */ + default void replaceAll(BiFunction function) { + Objects.requireNonNull(function); + forEach((k, v) -> { + while (!replace(k, v, function.apply(k, v))) { + // v changed or k is gone + if ((v = get(k)) == null) { + // k is no longer in the map. + break; + } + } + }); + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedOperationException {@inheritDoc} + * @throws ClassCastException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @implSpec The default implementation is equivalent to the following steps for this {@code map}, then + * returning the current value or {@code null} if now absent: + * + *

 {@code
+     * if (map.get(key) == null) {
+     *     V newValue = mappingFunction.apply(key);
+     *     if (newValue != null)
+     *         return map.putIfAbsent(key, newValue);
+     * }
+     * }
+ * + * The default implementation may retry these steps when multiple threads attempt updates including + * potentially calling the mapping function multiple times. + * + *

This implementation assumes that the ConcurrentMap cannot contain null values and {@code get()} + * returning null unambiguously means the key is absent. Implementations which support null values + * must override this default implementation. + * @since 1.8 + */ + + default V computeIfAbsent(K key, + Function mappingFunction) { + Objects.requireNonNull(mappingFunction); + V v, newValue; + return ((v = get(key)) == null && + (newValue = mappingFunction.apply(key)) != null && + (v = putIfAbsent(key, newValue)) == null) ? newValue : v; + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedOperationException {@inheritDoc} + * @throws ClassCastException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @implSpec The default implementation is equivalent to performing the following steps for this {@code + * map}, then returning the current value or {@code null} if now absent. : + * + *

 {@code
+     * if (map.get(key) != null) {
+     *     V oldValue = map.get(key);
+     *     V newValue = remappingFunction.apply(key, oldValue);
+     *     if (newValue != null)
+     *         map.replace(key, oldValue, newValue);
+     *     else
+     *         map.remove(key, oldValue);
+     * }
+     * }
+ * + * The default implementation may retry these steps when multiple threads attempt updates including + * potentially calling the remapping function multiple times. + * + *

This implementation assumes that the ConcurrentMap cannot contain null values and {@code get()} + * returning null unambiguously means the key is absent. Implementations which support null values + * must override this default implementation. + * @since 1.8 + */ + default V computeIfPresent(K key, + BiFunction remappingFunction) { + Objects.requireNonNull(remappingFunction); + V oldValue; + while ((oldValue = get(key)) != null) { + V newValue = remappingFunction.apply(key, oldValue); + if (newValue != null) { + if (replace(key, oldValue, newValue)) + return newValue; + } else if (remove(key, oldValue)) + return null; + } + return oldValue; + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedOperationException {@inheritDoc} + * @throws ClassCastException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @implSpec The default implementation is equivalent to performing the following steps for this {@code + * map}, then returning the current value or {@code null} if absent: + * + *

 {@code
+     * V oldValue = map.get(key);
+     * V newValue = remappingFunction.apply(key, oldValue);
+     * if (oldValue != null ) {
+     *    if (newValue != null)
+     *       map.replace(key, oldValue, newValue);
+     *    else
+     *       map.remove(key, oldValue);
+     * } else {
+     *    if (newValue != null)
+     *       map.putIfAbsent(key, newValue);
+     *    else
+     *       return null;
+     * }
+     * }
+ * + * The default implementation may retry these steps when multiple threads attempt updates including + * potentially calling the remapping function multiple times. + * + *

This implementation assumes that the ConcurrentMap cannot contain null values and {@code get()} + * returning null unambiguously means the key is absent. Implementations which support null values + * must override this default implementation. + * @since 1.8 + */ + default V compute(K key, + BiFunction remappingFunction) { + Objects.requireNonNull(remappingFunction); + V oldValue = get(key); + for (; ; ) { + V newValue = remappingFunction.apply(key, oldValue); + if (newValue == null) { + // delete mapping + if (oldValue != null || containsKey(key)) { + // something to remove + if (remove(key, oldValue)) { + // removed the old value as expected + return null; + } + + // some other value replaced old value. try again. + oldValue = get(key); + } else { + // nothing to do. Leave things as they were. + return null; + } + } else { + // add or replace old mapping + if (oldValue != null) { + // replace + if (replace(key, oldValue, newValue)) { + // replaced as expected. + return newValue; + } + + // some other value replaced old value. try again. + oldValue = get(key); + } else { + // add (replace if oldValue was null) + if ((oldValue = putIfAbsent(key, newValue)) == null) { + // replaced + return newValue; + } + + // some other value replaced old value. try again. + } + } + } + } + + + /** + * {@inheritDoc} + * + * @throws UnsupportedOperationException {@inheritDoc} + * @throws ClassCastException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @implSpec The default implementation is equivalent to performing the following steps for this {@code + * map}, then returning the current value or {@code null} if absent: + * + *

 {@code
+     * V oldValue = map.get(key);
+     * V newValue = (oldValue == null) ? value :
+     *              remappingFunction.apply(oldValue, value);
+     * if (newValue == null)
+     *     map.remove(key);
+     * else
+     *     map.put(key, newValue);
+     * }
+ * + *

The default implementation may retry these steps when multiple threads attempt updates including + * potentially calling the remapping function multiple times. + * + *

This implementation assumes that the ConcurrentMap cannot contain null values and {@code get()} + * returning null unambiguously means the key is absent. Implementations which support null values + * must override this default implementation. + * @since 1.8 + */ + default V merge(K key, V value, + BiFunction remappingFunction) { + Objects.requireNonNull(remappingFunction); + Objects.requireNonNull(value); + V oldValue = get(key); + for (; ; ) { + if (oldValue != null) { + V newValue = remappingFunction.apply(oldValue, value); + if (newValue != null) { + if (replace(key, oldValue, newValue)) + return newValue; + } else if (remove(key, oldValue)) { + return null; + } + oldValue = get(key); + } else { + if ((oldValue = putIfAbsent(key, value)) == null) { + return value; + } + } + } + } +} diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java new file mode 100644 index 000000000..a70b77439 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java @@ -0,0 +1,30 @@ +/* + * Copyright 2014 Higher Frequency Trading + *

+ * http://www.higherfrequencytrading.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map; + +import net.openhft.collections.ChronicleMapBuilder0; + +/** + * @author Rob Austin. + */ +public class ChronicleMapBuilder extends ChronicleMapBuilder0 { + public ChronicleMapBuilder(Class aClass, Class aClass2) { + super(aClass, aClass2); + } +} diff --git a/src/main/java/net/openhft/collections/ChronicleMapBuilder0.java b/src/main/java/net/openhft/collections/ChronicleMapBuilder0.java new file mode 100644 index 000000000..c94499931 --- /dev/null +++ b/src/main/java/net/openhft/collections/ChronicleMapBuilder0.java @@ -0,0 +1,150 @@ +/* + * Copyright 2014 Higher Frequency Trading + *

+ * http://www.higherfrequencytrading.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.collections; + +import net.openhft.chronicle.map.ChronicleMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * @author Rob Austin. + */ +public class ChronicleMapBuilder0 extends SharedHashMapBuilder implements Cloneable { + + private static final Logger LOG = LoggerFactory.getLogger(ChronicleMapBuilder0.class.getName()); + + public ChronicleMapBuilder0(Class kClass, Class vClass) { + super(kClass, vClass); + } + + public static ChronicleMapBuilder0 of(Class kClass, Class vClass) { + return new ChronicleMapBuilder0(kClass, vClass); + } + + + /** + * Not supported yet. + * + * @param transactional if the built map should be transactional + * @return this {@code SharedHashMapBuilder} back + */ + public ChronicleMapBuilder0 transactional(boolean transactional) { + this.transactional = transactional; + return this; + } + + public boolean transactional() { + return transactional; + } + + + public ChronicleMapBuilder0 kClass(Class kClass) { + this.kClass = kClass; + return this; + } + + public ChronicleMapBuilder0 vClass(Class vClass) { + this.vClass = vClass; + return this; + } + + public ChronicleMapBuilder0 file(File file) { + this.file = file; + return this; + } + + + public ChronicleMap create() throws IOException { + super.create(); + + if (kClass == null) + throw new IllegalArgumentException("missing mandatory parameter kClass"); + + if (vClass == null) + throw new IllegalArgumentException("missing mandatory parameter vClass"); + + if (file == null) + throw new IllegalArgumentException("missing mandatory parameter file"); + + + ChronicleMapBuilder0 builder = toBuilder(); + + if (!canReplicate()) + return new ChronicleMap0(builder, file, kClass, vClass); + + if (identifier <= 0) + throw new IllegalArgumentException("Identifier must be positive, " + identifier + " given"); + + final ChronicleReplicatedHashMap result = + new ChronicleReplicatedHashMap(builder, kClass, vClass); + + if (externalReplicatorBuilder != null) + externalReplicator = applyExternalReplicator(result, externalReplicatorBuilder, kClass, vClass); + + if (tcpReplicatorBuilder != null) + applyTcpReplication(result, tcpReplicatorBuilder); + + if (udpReplicatorBuilder != null) { + if (tcpReplicatorBuilder == null) + LOG.warn("MISSING TCP REPLICATION : The UdpReplicator only attempts to read data (" + + "it does not enforce or guarantee delivery), you should use the UdpReplicator if " + + "you have a large number of nodes, and you wish to receive the data before it " + + "becomes available on TCP/IP. Since data delivery is not guaranteed, it is " + + "recommended that you only use the UDP" + + " " + + "Replicator " + + "in conjunction with a TCP Replicator"); + applyUdpReplication(result, udpReplicatorBuilder); + } + return result; + } + + ChronicleMapBuilder0 toBuilder() throws IOException { + ChronicleMapBuilder0 builder = clone(); + + for (int i = 0; i < 10; i++) { + if (file.exists() && file.length() > 0) { + readFile(file, builder); + break; + } + if (file.createNewFile() || file.length() == 0) { + newFile(file); + break; + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { + throw new IOException(e); + } + } + if (builder == null || !file.exists()) + throw new FileNotFoundException("Unable to create " + file); + return builder; + } + + @Override + public ChronicleMapBuilder0 clone() { + return (ChronicleMapBuilder0) super.clone(); + } + +} diff --git a/src/main/java/net/openhft/collections/ChronicleReplicatedHashMap.java b/src/main/java/net/openhft/collections/ChronicleReplicatedHashMap.java new file mode 100644 index 000000000..e1eb5b152 --- /dev/null +++ b/src/main/java/net/openhft/collections/ChronicleReplicatedHashMap.java @@ -0,0 +1,35 @@ +/* + * Copyright 2014 Higher Frequency Trading + *

+ * http://www.higherfrequencytrading.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.collections; + +import net.openhft.chronicle.map.ChronicleMap; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; + +/** + * @author Rob Austin. + */ +public class ChronicleReplicatedHashMap extends VanillaSharedReplicatedHashMap implements ChronicleMap { + + public ChronicleReplicatedHashMap(@NotNull SharedHashMapBuilder builder, @NotNull Class aClass, @NotNull Class aClass2) throws IOException { + super(builder, aClass, aClass2); + } + +} diff --git a/src/main/java/net/openhft/collections/ConcurrentHashMap2.java b/src/main/java/net/openhft/collections/ConcurrentHashMap2.java new file mode 100644 index 000000000..07611ecac --- /dev/null +++ b/src/main/java/net/openhft/collections/ConcurrentHashMap2.java @@ -0,0 +1,25 @@ +/* + * Copyright 2014 Higher Frequency Trading + *

+ * http://www.higherfrequencytrading.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.collections; + +/** + * @author Rob Austin. + */ +public interface ConcurrentHashMap2 { +} diff --git a/src/main/java/net/openhft/collections/ConcurrentHashMap3.java b/src/main/java/net/openhft/collections/ConcurrentHashMap3.java new file mode 100644 index 000000000..cb4052002 --- /dev/null +++ b/src/main/java/net/openhft/collections/ConcurrentHashMap3.java @@ -0,0 +1,159 @@ +/* + * Copyright 2014 Higher Frequency Trading + *

+ * http://www.higherfrequencytrading.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.collections; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.*; + +/** + * @author Rob Austin. + */ +public interface ConcurrentHashMap3 { + + + long mappingCount(); + + ConcurrentHashMap.KeySetView keySet(V mappedValue); + + void forEach(long parallelismThreshold, + BiConsumer action); + + void forEach(long parallelismThreshold, + BiFunction transformer, + Consumer action); + + U search(long parallelismThreshold, + BiFunction searchFunction); + + U reduce(long parallelismThreshold, + BiFunction transformer, + BiFunction reducer); + + double reduceToDouble(long parallelismThreshold, + ToDoubleBiFunction transformer, + double basis, + DoubleBinaryOperator reducer); + + long reduceToLong(long parallelismThreshold, + ToLongBiFunction transformer, + long basis, + LongBinaryOperator reducer); + + int reduceToInt(long parallelismThreshold, + ToIntBiFunction transformer, + int basis, + IntBinaryOperator reducer); + + void forEachKey(long parallelismThreshold, + Consumer action); + + void forEachKey(long parallelismThreshold, + Function transformer, + Consumer action); + + U searchKeys(long parallelismThreshold, + Function searchFunction); + + K reduceKeys(long parallelismThreshold, + BiFunction reducer); + + U reduceKeys(long parallelismThreshold, + Function transformer, + BiFunction reducer); + + double reduceKeysToDouble(long parallelismThreshold, + ToDoubleFunction transformer, + double basis, + DoubleBinaryOperator reducer); + + long reduceKeysToLong(long parallelismThreshold, + ToLongFunction transformer, + long basis, + LongBinaryOperator reducer); + + int reduceKeysToInt(long parallelismThreshold, + ToIntFunction transformer, + int basis, + IntBinaryOperator reducer); + + void forEachValue(long parallelismThreshold, + Consumer action); + + void forEachValue(long parallelismThreshold, + Function transformer, + Consumer action); + + U searchValues(long parallelismThreshold, + Function searchFunction); + + V reduceValues(long parallelismThreshold, + BiFunction reducer); + + U reduceValues(long parallelismThreshold, + Function transformer, + BiFunction reducer); + + double reduceValuesToDouble(long parallelismThreshold, + ToDoubleFunction transformer, + double basis, + DoubleBinaryOperator reducer); + + long reduceValuesToLong(long parallelismThreshold, + ToLongFunction transformer, + long basis, + LongBinaryOperator reducer); + + int reduceValuesToInt(long parallelismThreshold, + ToIntFunction transformer, + int basis, + IntBinaryOperator reducer); + + void forEachEntry(long parallelismThreshold, + Consumer> action); + + void forEachEntry(long parallelismThreshold, + Function, ? extends U> transformer, + Consumer action); + + U searchEntries(long parallelismThreshold, + Function, ? extends U> searchFunction); + + Map.Entry reduceEntries(long parallelismThreshold, + BiFunction, Map.Entry, ? extends Map.Entry> reducer); + + U reduceEntries(long parallelismThreshold, + Function, ? extends U> transformer, + BiFunction reducer); + + double reduceEntriesToDouble(long parallelismThreshold, + ToDoubleFunction> transformer, + double basis, + DoubleBinaryOperator reducer); + + long reduceEntriesToLong(long parallelismThreshold, + ToLongFunction> transformer, + long basis, + LongBinaryOperator reducer); + + int reduceEntriesToInt(long parallelismThreshold, + ToIntFunction> transformer, + int basis, + IntBinaryOperator reducer); +} diff --git a/src/main/java/net/openhft/collections/VSHM.java b/src/main/java/net/openhft/collections/VSHM.java new file mode 100644 index 000000000..e55d80c56 --- /dev/null +++ b/src/main/java/net/openhft/collections/VSHM.java @@ -0,0 +1,36 @@ +/* + * Copyright 2014 Higher Frequency Trading + *

+ * http://www.higherfrequencytrading.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.collections; + +import net.openhft.chronicle.map.ChronicleMap; + +import java.io.File; +import java.io.IOException; + +/** + * @author Rob Austin. + */ +class ChronicleMap0 extends VanillaSharedHashMap implements ChronicleMap { + public ChronicleMap0(ChronicleMapBuilder0 builder, File file, Class kClass, Class vClass) + throws IOException { + super(builder, file, kClass, vClass); + } + + +} diff --git a/src/test/java/net/openhft/chronicle/map/ConcurrentHashMap8Test.java b/src/test/java/net/openhft/chronicle/map/ConcurrentHashMap8Test.java index 969de12f4..c1a2f39aa 100644 --- a/src/test/java/net/openhft/chronicle/map/ConcurrentHashMap8Test.java +++ b/src/test/java/net/openhft/chronicle/map/ConcurrentHashMap8Test.java @@ -30,9 +30,8 @@ import org.junit.Test; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentHashMap.KeySetView; import java.util.concurrent.atomic.LongAdder; -import java.util.function.BiFunction; +import java.util.function.*; import static java.util.Spliterator.*; import static org.junit.Assert.*; @@ -42,11 +41,56 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { private static final double EPSILON = 1E-5; + private static ConcurrentHashMap newLongMap() { + //First create (or access if already created) the shared map + +/* final ConcurrentHashMapBuilder0 builder = ConcurrentHashMapBuilder0.of(Long.class, Long.class); + + + //// don't include this, just to check it is as expected. + assertEquals(8, builder.minSegments()); + //// end of test + + String shmPath = System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + "SHMTest" + System.nanoTime(); + try { + return builder.file(new File(shmPath)).create(); + } catch (IOException e) { + throw new IllegalStateException(e); + }*/ + + + return new ConcurrentHashMap(5); + + } + + private static ConcurrentHashMap newIntegerStringMap() { + + +/* final ConcurrentHashMapBuilder0 builder = ConcurrentHashMapBuilder0.of(Long.class, String.class); + + + //// don't include this, just to check it is as expected. + assertEquals(8, builder.minSegments()); + //// end of test + + String shmPath = System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + + "SHMTest" + System.nanoTime(); + try { + return builder.file(new File(shmPath)).create(); + } catch (IOException e) { + throw new IllegalStateException(e); + }*/ + + + return new ConcurrentHashMap(5); + + } + /** * Returns a new map from Integers 1-5 to Strings "A"-"E". */ private static ConcurrentHashMap map5() { - ConcurrentHashMap map = new ConcurrentHashMap(5); + ConcurrentHashMap map = newIntegerStringMap(); assertTrue(map.isEmpty()); map.put(one, "A"); map.put(two, "B"); @@ -58,6 +102,7 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { return map; } + /** * getOrDefault returns value if present, else default */ @@ -236,8 +281,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { Set set1 = map.keySet(); Set set2 = map.keySet(true); set2.add(six); - assertTrue(((KeySetView) set2).getMap() == map); - assertTrue(((KeySetView) set1).getMap() == map); + assertTrue(((ConcurrentHashMap.KeySetView) set2).getMap() == map); + assertTrue(((ConcurrentHashMap.KeySetView) set1).getMap() == map); assertEquals(set2.size(), map.size()); assertEquals(set1.size(), map.size()); assertTrue((Boolean) map.get(six)); @@ -336,7 +381,7 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { shouldThrow(); } catch (NullPointerException e) { } - KeySetView set = map.keySet(one); + final ConcurrentHashMap.KeySetView set = map.keySet(one); set.add(one); set.add(six); set.add(seven); @@ -608,13 +653,15 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { static ConcurrentHashMap longMap() { if (longMap == null) { - longMap = new ConcurrentHashMap(SIZE); + longMap = newLongMap(); for (int i = 0; i < SIZE; ++i) longMap.put(Long.valueOf(i), Long.valueOf(2 * i)); } + return longMap; } + // explicit function class to avoid type inference problems static class AddKeys implements BiFunction, Map.Entry, Map.Entry> { public Map.Entry apply(Map.Entry x, Map.Entry y) { @@ -631,7 +678,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testForEachKeySequentially() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachKey(Long.MAX_VALUE, (Long x) -> adder.add(x.longValue())); + final Consumer consumer = (Long x) -> adder.add(x.longValue()); + m.forEachKey(Long.MAX_VALUE, consumer); assertEquals(adder.sum(), SIZE * (SIZE - 1) / 2); } @@ -641,8 +689,9 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testForEachValueSequentially() { LongAdder adder = new LongAdder(); - ConcurrentHashMap m = longMap(); - m.forEachValue(Long.MAX_VALUE, (Long x) -> adder.add(x.longValue())); + ConcurrentHashMap m = (ConcurrentHashMap) longMap(); + final Consumer action = (Long x) -> adder.add(x.longValue()); + m.forEachValue(Long.MAX_VALUE, action); assertEquals(adder.sum(), SIZE * (SIZE - 1)); } @@ -653,7 +702,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testForEachSequentially() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEach(Long.MAX_VALUE, (Long x, Long y) -> adder.add(x.longValue() + y.longValue())); + final BiConsumer action = (Long x, Long y) -> adder.add(x.longValue() + y.longValue()); + m.forEach(Long.MAX_VALUE, action); assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); } @@ -664,7 +714,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testForEachEntrySequentially() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachEntry(Long.MAX_VALUE, (Map.Entry e) -> adder.add(e.getKey().longValue() + e.getValue().longValue())); + final Consumer> action = (Map.Entry e) -> adder.add(e.getKey().longValue() + e.getValue().longValue()); + m.forEachEntry(Long.MAX_VALUE, action); assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); } @@ -675,7 +726,9 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testForEachKeyInParallel() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachKey(1L, (Long x) -> adder.add(x.longValue())); + final Consumer action = (Long x) -> adder.add(x.longValue()); + + m.forEachKey(1L, action); assertEquals(adder.sum(), SIZE * (SIZE - 1) / 2); } @@ -686,7 +739,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testForEachValueInParallel() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachValue(1L, (Long x) -> adder.add(x.longValue())); + final Consumer action = (Long x) -> adder.add(x.longValue()); + m.forEachValue(1L, action); assertEquals(adder.sum(), SIZE * (SIZE - 1)); } @@ -697,7 +751,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testForEachInParallel() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEach(1L, (Long x, Long y) -> adder.add(x.longValue() + y.longValue())); + final BiConsumer action = (Long x, Long y) -> adder.add(x.longValue() + y.longValue()); + m.forEach(1L, action); assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); } @@ -708,7 +763,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testForEachEntryInParallel() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachEntry(1L, (Map.Entry e) -> adder.add(e.getKey().longValue() + e.getValue().longValue())); + final Consumer> action = (Map.Entry e) -> adder.add(e.getKey().longValue() + e.getValue().longValue()); + m.forEachEntry(1L, action); assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); } @@ -719,8 +775,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testMappedForEachKeySequentially() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachKey(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()), - (Long x) -> adder.add(x.longValue())); + final Function transformer = (Long x) -> Long.valueOf(4 * x.longValue()); + final Consumer action = (Long x) -> adder.add(x.longValue()); + m.forEachKey(Long.MAX_VALUE, transformer, + action); assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1) / 2); } @@ -731,8 +789,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testMappedForEachValueSequentially() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachValue(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()), - (Long x) -> adder.add(x.longValue())); + final Function transformer = (Long x) -> Long.valueOf(4 * x.longValue()); + final Consumer action = (Long x) -> adder.add(x.longValue()); + m.forEachValue(Long.MAX_VALUE, transformer, + action); assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1)); } @@ -743,8 +803,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testMappedForEachSequentially() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEach(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()), - (Long x) -> adder.add(x.longValue())); + final BiFunction transformer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + final Consumer action = (Long x) -> adder.add(x.longValue()); + m.forEach(Long.MAX_VALUE, transformer, + action); assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); } @@ -755,8 +817,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testMappedForEachEntrySequentially() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachEntry(Long.MAX_VALUE, (Map.Entry e) -> Long.valueOf(e.getKey().longValue() + e.getValue().longValue()), - (Long x) -> adder.add(x.longValue())); + final Function, Long> transformer = (Map.Entry e) -> Long.valueOf(e.getKey().longValue() + e.getValue().longValue()); + final Consumer action = (Long x) -> adder.add(x.longValue()); + m.forEachEntry(Long.MAX_VALUE, transformer, + action); assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); } @@ -767,8 +831,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testMappedForEachKeyInParallel() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachKey(1L, (Long x) -> Long.valueOf(4 * x.longValue()), - (Long x) -> adder.add(x.longValue())); + final Function transformer = (Long x) -> Long.valueOf(4 * x.longValue()); + final Consumer action = (Long x) -> adder.add(x.longValue()); + m.forEachKey(1L, transformer, + action); assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1) / 2); } @@ -779,8 +845,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testMappedForEachValueInParallel() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachValue(1L, (Long x) -> Long.valueOf(4 * x.longValue()), - (Long x) -> adder.add(x.longValue())); + final Function transformer = (Long x) -> Long.valueOf(4 * x.longValue()); + final Consumer action = (Long x) -> adder.add(x.longValue()); + m.forEachValue(1L, transformer, + action); assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1)); } @@ -791,8 +859,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testMappedForEachInParallel() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEach(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()), - (Long x) -> adder.add(x.longValue())); + final BiFunction transformer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + final Consumer action = (Long x) -> adder.add(x.longValue()); + m.forEach(1L, transformer, + action); assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); } @@ -803,8 +873,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testMappedForEachEntryInParallel() { LongAdder adder = new LongAdder(); ConcurrentHashMap m = longMap(); - m.forEachEntry(1L, (Map.Entry e) -> Long.valueOf(e.getKey().longValue() + e.getValue().longValue()), - (Long x) -> adder.add(x.longValue())); + final Function, Long> transformer = (Map.Entry e) -> Long.valueOf(e.getKey().longValue() + e.getValue().longValue()); + final Consumer action = (Long x) -> adder.add(x.longValue()); + m.forEachEntry(1L, transformer, + action); assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); } @@ -815,7 +887,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testReduceKeysSequentially() { ConcurrentHashMap m = longMap(); Long r; - r = m.reduceKeys(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + final BiFunction reducer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + r = m.reduceKeys(Long.MAX_VALUE, reducer); assertEquals((long) r, (long) SIZE * (SIZE - 1) / 2); } @@ -826,7 +899,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testReduceValuesSequentially() { ConcurrentHashMap m = longMap(); Long r; - r = m.reduceKeys(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + final BiFunction reducer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + r = m.reduceKeys(Long.MAX_VALUE, reducer); assertEquals((long) r, (long) SIZE * (SIZE - 1) / 2); } @@ -837,7 +911,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testReduceEntriesSequentially() { ConcurrentHashMap m = longMap(); Map.Entry r; - r = m.reduceEntries(Long.MAX_VALUE, new AddKeys()); + final AddKeys reducer = new AddKeys(); + r = m.reduceEntries(Long.MAX_VALUE, reducer); assertEquals(r.getKey().longValue(), (long) SIZE * (SIZE - 1) / 2); } @@ -848,7 +923,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testReduceKeysInParallel() { ConcurrentHashMap m = longMap(); Long r; - r = m.reduceKeys(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + final BiFunction reducer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + r = m.reduceKeys(1L, reducer); assertEquals((long) r, (long) SIZE * (SIZE - 1) / 2); } @@ -859,7 +935,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testReduceValuesInParallel() { ConcurrentHashMap m = longMap(); Long r; - r = m.reduceValues(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + final BiFunction reducer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + r = m.reduceValues(1L, reducer); assertEquals((long) r, (long) SIZE * (SIZE - 1)); } @@ -880,8 +957,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testMapReduceKeysSequentially() { ConcurrentHashMap m = longMap(); - Long r = m.reduceKeys(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()), - (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + final Function transformer = (Long x) -> Long.valueOf(4 * x.longValue()); + final BiFunction reducer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + Long r = m.reduceKeys(Long.MAX_VALUE, transformer, + reducer); assertEquals((long) r, (long) 4 * SIZE * (SIZE - 1) / 2); } @@ -891,8 +970,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testMapReduceValuesSequentially() { ConcurrentHashMap m = longMap(); - Long r = m.reduceValues(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()), - (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + final Function transformer = (Long x) -> Long.valueOf(4 * x.longValue()); + final BiFunction reducer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + Long r = m.reduceValues(Long.MAX_VALUE, transformer, + reducer); assertEquals((long) r, (long) 4 * SIZE * (SIZE - 1)); } @@ -902,8 +983,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testMappedReduceSequentially() { ConcurrentHashMap m = longMap(); - Long r = m.reduce(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()), - (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + final BiFunction transformer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + final BiFunction reducer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + Long r = m.reduce(Long.MAX_VALUE, transformer, + reducer); assertEquals((long) r, (long) 3 * SIZE * (SIZE - 1) / 2); } @@ -914,8 +997,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testMapReduceKeysInParallel() { ConcurrentHashMap m = longMap(); - Long r = m.reduceKeys(1L, (Long x) -> Long.valueOf(4 * x.longValue()), - (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + final Function transformer = (Long x) -> Long.valueOf(4 * x.longValue()); + final BiFunction reducer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + Long r = m.reduceKeys(1L, transformer, + reducer); assertEquals((long) r, (long) 4 * SIZE * (SIZE - 1) / 2); } @@ -925,8 +1010,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testMapReduceValuesInParallel() { ConcurrentHashMap m = longMap(); - Long r = m.reduceValues(1L, (Long x) -> Long.valueOf(4 * x.longValue()), - (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + final Function transformer = (Long x) -> Long.valueOf(4 * x.longValue()); + final BiFunction reducer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + Long r = m.reduceValues(1L, transformer, + reducer); assertEquals((long) r, (long) 4 * SIZE * (SIZE - 1)); } @@ -937,8 +1024,10 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testMappedReduceInParallel() { ConcurrentHashMap m = longMap(); Long r; - r = m.reduce(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()), - (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + final BiFunction transformer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + final BiFunction reducer = (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()); + r = m.reduce(1L, transformer, + reducer); assertEquals((long) r, (long) 3 * SIZE * (SIZE - 1) / 2); } @@ -948,7 +1037,9 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceKeysToLongSequentially() { ConcurrentHashMap m = longMap(); - long lr = m.reduceKeysToLong(Long.MAX_VALUE, (Long x) -> x.longValue(), 0L, Long::sum); + final ToLongFunction transformer = (Long x) -> x.longValue(); + final LongBinaryOperator sum = Long::sum; + long lr = m.reduceKeysToLong(Long.MAX_VALUE, transformer, 0L, sum); assertEquals(lr, (long) SIZE * (SIZE - 1) / 2); } @@ -958,7 +1049,9 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceKeysToIntSequentially() { ConcurrentHashMap m = longMap(); - int ir = m.reduceKeysToInt(Long.MAX_VALUE, (Long x) -> x.intValue(), 0, Integer::sum); + final ToIntFunction transformer = (Long x) -> x.intValue(); + final IntBinaryOperator sum = Integer::sum; + int ir = m.reduceKeysToInt(Long.MAX_VALUE, transformer, 0, sum); assertEquals(ir, SIZE * (SIZE - 1) / 2); } @@ -968,8 +1061,9 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceKeysToDoubleSequentially() { ConcurrentHashMap m = longMap(); - double dr = m.reduceKeysToDouble(Long.MAX_VALUE, (Long x) -> x.doubleValue(), 0.0, Double::sum); - assertEquals(dr, (double) SIZE * (SIZE - 1) / 2,EPSILON); + final ToDoubleFunction transformer = (Long x) -> x.doubleValue(); + double dr = m.reduceKeysToDouble(Long.MAX_VALUE, transformer, 0.0, Double::sum); + assertEquals(dr, (double) SIZE * (SIZE - 1) / 2, EPSILON); } /** @@ -978,7 +1072,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceValuesToLongSequentially() { ConcurrentHashMap m = longMap(); - long lr = m.reduceValuesToLong(Long.MAX_VALUE, (Long x) -> x.longValue(), 0L, Long::sum); + final ToLongFunction transformer = (Long x) -> x.longValue(); + long lr = m.reduceValuesToLong(Long.MAX_VALUE, transformer, 0L, Long::sum); assertEquals(lr, (long) SIZE * (SIZE - 1)); } @@ -988,7 +1083,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceValuesToIntSequentially() { ConcurrentHashMap m = longMap(); - int ir = m.reduceValuesToInt(Long.MAX_VALUE, (Long x) -> x.intValue(), 0, Integer::sum); + final ToIntFunction transformer = (Long x) -> x.intValue(); + int ir = m.reduceValuesToInt(Long.MAX_VALUE, transformer, 0, Integer::sum); assertEquals(ir, SIZE * (SIZE - 1)); } @@ -998,8 +1094,9 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceValuesToDoubleSequentially() { ConcurrentHashMap m = longMap(); - double dr = m.reduceValuesToDouble(Long.MAX_VALUE, (Long x) -> x.doubleValue(), 0.0, Double::sum); - assertEquals(dr, (double) SIZE * (SIZE - 1),EPSILON); + final ToDoubleFunction transformer = (Long x) -> x.doubleValue(); + double dr = m.reduceValuesToDouble(Long.MAX_VALUE, transformer, 0.0, Double::sum); + assertEquals(dr, (double) SIZE * (SIZE - 1), EPSILON); } /** @@ -1008,7 +1105,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceKeysToLongInParallel() { ConcurrentHashMap m = longMap(); - long lr = m.reduceKeysToLong(1L, (Long x) -> x.longValue(), 0L, Long::sum); + final ToLongFunction transformer = (Long x) -> x.longValue(); + long lr = m.reduceKeysToLong(1L, transformer, 0L, Long::sum); assertEquals(lr, (long) SIZE * (SIZE - 1) / 2); } @@ -1018,7 +1116,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceKeysToIntInParallel() { ConcurrentHashMap m = longMap(); - int ir = m.reduceKeysToInt(1L, (Long x) -> x.intValue(), 0, Integer::sum); + final ToIntFunction transformer = (Long x) -> x.intValue(); + int ir = m.reduceKeysToInt(1L, transformer, 0, Integer::sum); assertEquals(ir, SIZE * (SIZE - 1) / 2); } @@ -1028,7 +1127,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceKeysToDoubleInParallel() { ConcurrentHashMap m = longMap(); - double dr = m.reduceKeysToDouble(1L, (Long x) -> x.doubleValue(), 0.0, Double::sum); + final ToDoubleFunction transformer = (Long x) -> x.doubleValue(); + double dr = m.reduceKeysToDouble(1L, transformer, 0.0, Double::sum); assertEquals(dr, (double) SIZE * (SIZE - 1) / 2, 0.01); } @@ -1038,7 +1138,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceValuesToLongInParallel() { ConcurrentHashMap m = longMap(); - long lr = m.reduceValuesToLong(1L, (Long x) -> x.longValue(), 0L, Long::sum); + final ToLongFunction transformer = (Long x) -> x.longValue(); + long lr = m.reduceValuesToLong(1L, transformer, 0L, Long::sum); assertEquals(lr, (long) SIZE * (SIZE - 1)); } @@ -1048,7 +1149,8 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceValuesToIntInParallel() { ConcurrentHashMap m = longMap(); - int ir = m.reduceValuesToInt(1L, (Long x) -> x.intValue(), 0, Integer::sum); + final ToIntFunction transformer = (Long x) -> x.intValue(); + int ir = m.reduceValuesToInt(1L, transformer, 0, Integer::sum); assertEquals(ir, SIZE * (SIZE - 1)); } @@ -1058,8 +1160,9 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { @Test public void testReduceValuesToDoubleInParallel() { ConcurrentHashMap m = longMap(); - double dr = m.reduceValuesToDouble(1L, (Long x) -> x.doubleValue(), 0.0, Double::sum); - assertEquals(dr, (double) SIZE * (SIZE - 1),EPSILON); + final ToDoubleFunction transformer = (Long x) -> x.doubleValue(); + double dr = m.reduceValuesToDouble(1L, transformer, 0.0, Double::sum); + assertEquals(dr, (double) SIZE * (SIZE - 1), EPSILON); } /** @@ -1069,9 +1172,11 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testSearchKeysSequentially() { ConcurrentHashMap m = longMap(); Long r; - r = m.searchKeys(Long.MAX_VALUE, (Long x) -> x.longValue() == (long) (SIZE / 2) ? x : null); + final Function searchFunction = (Long x) -> x.longValue() == (long) (SIZE / 2) ? x : null; + r = m.searchKeys(Long.MAX_VALUE, searchFunction); assertEquals((long) r, (long) (SIZE / 2)); - r = m.searchKeys(Long.MAX_VALUE, (Long x) -> x.longValue() < 0L ? x : null); + final Function searchFunction1 = (Long x) -> x.longValue() < 0L ? x : null; + r = m.searchKeys(Long.MAX_VALUE, searchFunction1); assertNull(r); } @@ -1082,9 +1187,11 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testSearchValuesSequentially() { ConcurrentHashMap m = longMap(); Long r; - r = m.searchValues(Long.MAX_VALUE, (Long x) -> x.longValue() == (long) (SIZE / 2) ? x : null); + final Function searchFunction = (Long x) -> x.longValue() == (long) (SIZE / 2) ? x : null; + r = m.searchValues(Long.MAX_VALUE, searchFunction); assertEquals((long) r, (long) (SIZE / 2)); - r = m.searchValues(Long.MAX_VALUE, (Long x) -> x.longValue() < 0L ? x : null); + final Function searchFunction1 = (Long x) -> x.longValue() < 0L ? x : null; + r = m.searchValues(Long.MAX_VALUE, searchFunction1); assertNull(r); } @@ -1095,9 +1202,11 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testSearchSequentially() { ConcurrentHashMap m = longMap(); Long r; - r = m.search(Long.MAX_VALUE, (Long x, Long y) -> x.longValue() == (long) (SIZE / 2) ? x : null); + final BiFunction searchFunction = (Long x, Long y) -> x.longValue() == (long) (SIZE / 2) ? x : null; + r = m.search(Long.MAX_VALUE, searchFunction); assertEquals((long) r, (long) (SIZE / 2)); - r = m.search(Long.MAX_VALUE, (Long x, Long y) -> x.longValue() < 0L ? x : null); + final BiFunction searchFunction1 = (Long x, Long y) -> x.longValue() < 0L ? x : null; + r = m.search(Long.MAX_VALUE, searchFunction1); assertNull(r); } @@ -1108,9 +1217,11 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testSearchEntriesSequentially() { ConcurrentHashMap m = longMap(); Long r; - r = m.searchEntries(Long.MAX_VALUE, (Map.Entry e) -> e.getKey().longValue() == (long) (SIZE / 2) ? e.getKey() : null); + final Function, Long> searchFunction = (Map.Entry e) -> e.getKey().longValue() == (long) (SIZE / 2) ? e.getKey() : null; + r = m.searchEntries(Long.MAX_VALUE, searchFunction); assertEquals((long) r, (long) (SIZE / 2)); - r = m.searchEntries(Long.MAX_VALUE, (Map.Entry e) -> e.getKey().longValue() < 0L ? e.getKey() : null); + final Function, Long> searchFunction1 = (Map.Entry e) -> e.getKey().longValue() < 0L ? e.getKey() : null; + r = m.searchEntries(Long.MAX_VALUE, searchFunction1); assertNull(r); } @@ -1121,9 +1232,11 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testSearchKeysInParallel() { ConcurrentHashMap m = longMap(); Long r; - r = m.searchKeys(1L, (Long x) -> x.longValue() == (long) (SIZE / 2) ? x : null); + final Function searchFunction = (Long x) -> x.longValue() == (long) (SIZE / 2) ? x : null; + r = m.searchKeys(1L, searchFunction); assertEquals((long) r, (long) (SIZE / 2)); - r = m.searchKeys(1L, (Long x) -> x.longValue() < 0L ? x : null); + final Function searchFunction1 = (Long x) -> x.longValue() < 0L ? x : null; + r = m.searchKeys(1L, searchFunction1); assertNull(r); } @@ -1134,9 +1247,11 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testSearchValuesInParallel() { ConcurrentHashMap m = longMap(); Long r; - r = m.searchValues(1L, (Long x) -> x.longValue() == (long) (SIZE / 2) ? x : null); + final Function searchFunction = (Long x) -> x.longValue() == (long) (SIZE / 2) ? x : null; + r = m.searchValues(1L, searchFunction); assertEquals((long) r, (long) (SIZE / 2)); - r = m.searchValues(1L, (Long x) -> x.longValue() < 0L ? x : null); + final Function searchFunction1 = (Long x) -> x.longValue() < 0L ? x : null; + r = m.searchValues(1L, searchFunction1); assertNull(r); } @@ -1147,9 +1262,11 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testSearchInParallel() { ConcurrentHashMap m = longMap(); Long r; - r = m.search(1L, (Long x, Long y) -> x.longValue() == (long) (SIZE / 2) ? x : null); + final BiFunction searchFunction = (Long x, Long y) -> x.longValue() == (long) (SIZE / 2) ? x : null; + r = m.search(1L, searchFunction); assertEquals((long) r, (long) (SIZE / 2)); - r = m.search(1L, (Long x, Long y) -> x.longValue() < 0L ? x : null); + final BiFunction searchFunction1 = (Long x, Long y) -> x.longValue() < 0L ? x : null; + r = m.search(1L, searchFunction1); assertNull(r); } @@ -1160,9 +1277,11 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { public void testSearchEntriesInParallel() { ConcurrentHashMap m = longMap(); Long r; - r = m.searchEntries(1L, (Map.Entry e) -> e.getKey().longValue() == (long) (SIZE / 2) ? e.getKey() : null); + final Function, Long> searchFunction = (Map.Entry e) -> e.getKey().longValue() == (long) (SIZE / 2) ? e.getKey() : null; + r = m.searchEntries(1L, searchFunction); assertEquals((long) r, (long) (SIZE / 2)); - r = m.searchEntries(1L, (Map.Entry e) -> e.getKey().longValue() < 0L ? e.getKey() : null); + final Function, Long> searchFunction1 = (Map.Entry e) -> e.getKey().longValue() < 0L ? e.getKey() : null; + r = m.searchEntries(1L, searchFunction1); assertNull(r); } diff --git a/src/test/java/net/openhft/chronicle/map/others/ConcurrentAssociateTest.java b/src/test/java/net/openhft/chronicle/map/others/ConcurrentAssociateTest.java deleted file mode 100644 index dc881cc7c..000000000 --- a/src/test/java/net/openhft/chronicle/map/others/ConcurrentAssociateTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2014 Higher Frequency Trading - *

- * http://www.higherfrequencytrading.com - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.openhft.chronicle.map.others;/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.testng.annotations.Test; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ThreadLocalRandom; -import java.util.function.BiConsumer; -import java.util.function.Supplier; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -/** - * @test - * @bug 8028564 - * @run testng ConcurrentAssociateTest - * @summary Test that association operations, such as put and compute, - * place entries in the map - */ -@Test -public class ConcurrentAssociateTest { - - // The number of entries for each thread to place in a map - private static final int N = Integer.getInteger("n", 128); - // The number of iterations of the test - private static final int I = Integer.getInteger("i", 256); - - // Object to be placed in the concurrent map - static class X { - // Limit the hash code to trigger collisions - int hc = ThreadLocalRandom.current().nextInt(1, 9); - - public int hashCode() { return hc; } - } - - @Test - public void testPut() { - test("CHM.put", (m, o) -> m.put(o, o)); - } - - @Test - public void testCompute() { - test("CHM.compute", (m, o) -> m.compute(o, (k, v) -> o)); - } - - @Test - public void testComputeIfAbsent() { - test("CHM.computeIfAbsent", (m, o) -> m.computeIfAbsent(o, (k) -> o)); - } - - @Test - public void testMerge() { - test("CHM.merge", (m, o) -> m.merge(o, o, (v1, v2) -> v1)); - } - - @Test - public void testPutAll() { - test("CHM.putAll", (m, o) -> { - Map hm = new HashMap<>(); - hm.put(o, o); - m.putAll(hm); - }); - } - - private static void test(String desc, BiConsumer, Object> associator) { - for (int i = 0; i < I; i++) { - testOnce(desc, associator); - } - } - - static class AssociationFailure extends RuntimeException { - AssociationFailure(String message) { - super(message); - } - } - - private static void testOnce(String desc, BiConsumer, Object> associator) { - ConcurrentHashMap m = new ConcurrentHashMap<>(); - CountDownLatch s = new CountDownLatch(1); - - Supplier sr = () -> () -> { - try { - s.await(); - } - catch (InterruptedException e) { - } - - for (int i = 0; i < N; i++) { - Object o = new X(); - associator.accept(m, o); - if (!m.containsKey(o)) { - throw new AssociationFailure(desc + " failed: entry does not exist"); - } - } - }; - - int ps = Runtime.getRuntime().availableProcessors(); - Stream runners = IntStream.range(0, ps) - .mapToObj(i -> sr.get()) - .map(CompletableFuture::runAsync); - - CompletableFuture all = CompletableFuture.allOf( - runners.toArray(CompletableFuture[]::new)); - - // Trigger the runners to start associating - s.countDown(); - try { - all.join(); - } catch (CompletionException e) { - Throwable t = e.getCause(); - if (t instanceof AssociationFailure) { - throw (AssociationFailure) t; - } - else { - throw e; - } - } - } -} diff --git a/src/test/java/net/openhft/chronicle/map/others/ConcurrentContainsKeyTest.java b/src/test/java/net/openhft/chronicle/map/others/ConcurrentContainsKeyTest.java deleted file mode 100644 index 8fd4f23a5..000000000 --- a/src/test/java/net/openhft/chronicle/map/others/ConcurrentContainsKeyTest.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2014 Higher Frequency Trading - *

- * http://www.higherfrequencytrading.com - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.openhft.chronicle.map.others;/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import org.testng.annotations.Test; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.function.Supplier; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -/** - * @test - * @bug 8028564 - * @run testng ConcurrentContainsKeyTest - * @summary Test that entries are always present in the map, when entries are held within one bin that is a - * tree - */ -@Test -public class ConcurrentContainsKeyTest { - - // The number of entries for each thread to place in a map - // Should be > net.openhft.chronicle.map.ConcurrentHashMap.TREEIFY_THRESHOLD but small - // enough to allow for enough iteration overlap by multiple threads - private static final int N = Integer.getInteger("n", 16); - // The number of rounds each thread performs per entry - private static final int R = Integer.getInteger("r", 32); - // The number of iterations of the test - private static final int I = Integer.getInteger("i", 256); - - // Object to be placed in the concurrent map - static class X implements Comparable { - - private final int a; - - X(int a) { - this.a = a; - } - - public int compareTo(X o) { - return this.a - o.a; - } - - public int hashCode() { - // Return the same hash code to guarantee collisions - return 0; - } - } - - @Test - public void testContainsKey() { - X[] content = IntStream.range(0, N).mapToObj(i -> new X(i)).toArray((java.util.function - .IntFunction) (value) -> new X[value]); - // Create map with an initial size >= net.openhft.chronicle.map.ConcurrentHashMap.TREEIFY_THRESHOLD - // ensuring tree'ification will occur for a small number of entries - // with the same hash code - ConcurrentHashMap m = new ConcurrentHashMap<>(64); - Stream.of(content).forEach(x -> m.put(x, x)); - test(content, m); - } - - - private static void test(X[] content, ConcurrentHashMap m) { - for (int i = 0; i < I; i++) { - testOnce(content, m); - } - } - - static class AssociationFailure extends RuntimeException { - AssociationFailure(String message) { - super(message); - } - } - - private static void testOnce(Object[] content, ConcurrentHashMap m) { - CountDownLatch s = new CountDownLatch(1); - - Supplier sr = () -> () -> { - try { - s.await(); - } catch (InterruptedException e) { - } - - for (int i = 0; i < R * N; i++) { - Object o = content[i % content.length]; - if (!m.containsKey(o)) { - throw new AssociationFailure("CHM.containsKey failed: entry does not exist"); - } - } - }; - - int ps = Runtime.getRuntime().availableProcessors(); - Stream runners = IntStream.range(0, ps) - .mapToObj(i -> sr.get()) - .map(CompletableFuture::runAsync); - - CompletableFuture all = CompletableFuture.allOf( - runners.toArray(CompletableFuture[]::new)); - - // Trigger the runners to start checking key membership - s.countDown(); - try { - all.join(); - } catch (CompletionException e) { - Throwable t = e.getCause(); - if (t instanceof AssociationFailure) { - throw (AssociationFailure) t; - } else { - throw e; - } - } - } -} diff --git a/src/test/java/net/openhft/chronicle/map/others/DistinctEntrySetElements.java b/src/test/java/net/openhft/chronicle/map/others/DistinctEntrySetElements.java deleted file mode 100644 index 9a54ecb3c..000000000 --- a/src/test/java/net/openhft/chronicle/map/others/DistinctEntrySetElements.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2014 Higher Frequency Trading - *

- * http://www.higherfrequencytrading.com - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.openhft.chronicle.map.others;/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 6312706 - * @summary Sets from Map.entrySet() return distinct objects for each Entry - * @author Neil Richards , - */ - -import java.util.concurrent.ConcurrentHashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -public class DistinctEntrySetElements { - public static void main(String[] args) throws Exception { - final ConcurrentHashMap concurrentHashMap = - new ConcurrentHashMap<>(); - - concurrentHashMap.put("One", "Un"); - concurrentHashMap.put("Two", "Deux"); - concurrentHashMap.put("Three", "Trois"); - - Set> entrySet = concurrentHashMap.entrySet(); - HashSet> hashSet = new HashSet<>(entrySet); - - if (false == hashSet.equals(entrySet)) { - throw new RuntimeException("Test FAILED: Sets are not equal."); - } - if (hashSet.hashCode() != entrySet.hashCode()) { - throw new RuntimeException("Test FAILED: Set's hashcodes are not equal."); - } - } -} diff --git a/src/test/java/net/openhft/chronicle/map/others/LoopHelpers.java b/src/test/java/net/openhft/chronicle/map/others/LoopHelpers.java deleted file mode 100644 index aa8627ac4..000000000 --- a/src/test/java/net/openhft/chronicle/map/others/LoopHelpers.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2014 Higher Frequency Trading - *

- * http://www.higherfrequencytrading.com - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.openhft.chronicle.map.others;/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -/** - * Misc utilities in JSR166 performance tests - */ - -import java.util.concurrent.atomic.AtomicLong; - -class LoopHelpers { - - // Some mindless computation to do between synchronizations... - - /** - * generates 32 bit pseudo-random numbers. - * Adapted from http://www.snippets.org - */ - public static int compute1(int x) { - int lo = 16807 * (x & 0xFFFF); - int hi = 16807 * (x >>> 16); - lo += (hi & 0x7FFF) << 16; - if ((lo & 0x80000000) != 0) { - lo &= 0x7fffffff; - ++lo; - } - lo += hi >>> 15; - if (lo == 0 || (lo & 0x80000000) != 0) { - lo &= 0x7fffffff; - ++lo; - } - return lo; - } - - /** - * Computes a linear congruential random number a random number - * of times. - */ - public static int compute2(int x) { - int loops = (x >>> 4) & 7; - while (loops-- > 0) { - x = (x * 2147483647) % 16807; - } - return x; - } - - /** - * An actually useful random number generator, but unsynchronized. - * Basically same as java.util.Random. - */ - public static class SimpleRandom { - private static final long multiplier = 0x5DEECE66DL; - private static final long addend = 0xBL; - private static final long mask = (1L << 48) - 1; - static final AtomicLong seq = new AtomicLong(1); - private long seed = System.nanoTime() + seq.getAndIncrement(); - - public void setSeed(long s) { - seed = s; - } - - public int next() { - long nextseed = (seed * multiplier + addend) & mask; - seed = nextseed; - return ((int)(nextseed >>> 17)) & 0x7FFFFFFF; - } - } - - public static class BarrierTimer implements Runnable { - public volatile long startTime; - public volatile long endTime; - public void run() { - long t = System.nanoTime(); - if (startTime == 0) - startTime = t; - else - endTime = t; - } - public void clear() { - startTime = 0; - endTime = 0; - } - public long getTime() { - return endTime - startTime; - } - } - - public static String rightJustify(long n) { - // There's probably a better way to do this... - String field = " "; - String num = Long.toString(n); - if (num.length() >= field.length()) - return num; - StringBuffer b = new StringBuffer(field); - b.replace(b.length()-num.length(), b.length(), num); - return b.toString(); - } - -} diff --git a/src/test/java/net/openhft/chronicle/map/others/MapCheck.java b/src/test/java/net/openhft/chronicle/map/others/MapCheck.java deleted file mode 100644 index 265306b4f..000000000 --- a/src/test/java/net/openhft/chronicle/map/others/MapCheck.java +++ /dev/null @@ -1,635 +0,0 @@ -/* - * Copyright 2014 Higher Frequency Trading - *

- * http://www.higherfrequencytrading.com - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.openhft.chronicle.map.others;/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -/* - * @test - * @bug 4486658 - * @compile -source 1.5 MapCheck.java - * @run main/timeout=240 MapCheck - * @summary Times and checks basic map operations - */ - -import java.util.*; -import java.io.*; - -public class MapCheck { - - static final int absentSize = 1 << 17; - static final int absentMask = absentSize - 1; - static Object[] absent = new Object[absentSize]; - - static final Object MISSING = new Object(); - - static TestTimer timer = new TestTimer(); - - static void reallyAssert(boolean b) { - if (!b) throw new Error("Failed Assertion"); - } - - public static void main(String[] args) throws Exception { - Class mapClass = java.util.concurrent.ConcurrentHashMap.class; - int numTests = 8; - int size = 50000; - - if (args.length > 0) { - try { - mapClass = Class.forName(args[0]); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Class " + args[0] + " not found."); - } - } - - - if (args.length > 1) - numTests = Integer.parseInt(args[1]); - - if (args.length > 2) - size = Integer.parseInt(args[2]); - - boolean doSerializeTest = args.length > 3; - - System.out.println("Testing " + mapClass.getName() + " trials: " + numTests + " size: " + size); - - for (int i = 0; i < absentSize; ++i) absent[i] = new Object(); - - Object[] key = new Object[size]; - for (int i = 0; i < size; ++i) key[i] = new Object(); - - forceMem(size * 8); - - for (int rep = 0; rep < numTests; ++rep) { - runTest(newMap(mapClass), key); - } - - TestTimer.printStats(); - - - if (doSerializeTest) - stest(newMap(mapClass), size); - } - - static Map newMap(Class cl) { - try { - Map m = (Map)cl.newInstance(); - return m; - } catch (Exception e) { - throw new RuntimeException("Can't instantiate " + cl + ": " + e); - } - } - - - static void runTest(Map s, Object[] key) { - shuffle(key); - int size = key.length; - long startTime = System.currentTimeMillis(); - test(s, key); - long time = System.currentTimeMillis() - startTime; - } - - static void forceMem(int n) { - // force enough memory - Long[] junk = new Long[n]; - for (int i = 0; i < junk.length; ++i) junk[i] = new Long(i); - int sum = 0; - for (int i = 0; i < junk.length; ++i) - sum += (int)(junk[i].longValue() + i); - if (sum == 0) System.out.println("Useless number = " + sum); - junk = null; - // System.gc(); - } - - - static void t1(String nm, int n, Map s, Object[] key, int expect) { - int sum = 0; - int iters = 4; - timer.start(nm, n * iters); - for (int j = 0; j < iters; ++j) { - for (int i = 0; i < n; i++) { - if (s.get(key[i]) != null) ++sum; - } - } - timer.finish(); - reallyAssert(sum == expect * iters); - } - - static void t2(String nm, int n, Map s, Object[] key, int expect) { - int sum = 0; - timer.start(nm, n); - for (int i = 0; i < n; i++) { - if (s.remove(key[i]) != null) ++sum; - } - timer.finish(); - reallyAssert(sum == expect); - } - - static void t3(String nm, int n, Map s, Object[] key, int expect) { - int sum = 0; - timer.start(nm, n); - for (int i = 0; i < n; i++) { - if (s.put(key[i], absent[i & absentMask]) == null) ++sum; - } - timer.finish(); - reallyAssert(sum == expect); - } - - static void t4(String nm, int n, Map s, Object[] key, int expect) { - int sum = 0; - timer.start(nm, n); - for (int i = 0; i < n; i++) { - if (s.containsKey(key[i])) ++sum; - } - timer.finish(); - reallyAssert(sum == expect); - } - - static void t5(String nm, int n, Map s, Object[] key, int expect) { - int sum = 0; - timer.start(nm, n/2); - for (int i = n-2; i >= 0; i-=2) { - if (s.remove(key[i]) != null) ++sum; - } - timer.finish(); - reallyAssert(sum == expect); - } - - static void t6(String nm, int n, Map s, Object[] k1, Object[] k2) { - int sum = 0; - timer.start(nm, n * 2); - for (int i = 0; i < n; i++) { - if (s.get(k1[i]) != null) ++sum; - if (s.get(k2[i & absentMask]) != null) ++sum; - } - timer.finish(); - reallyAssert(sum == n); - } - - static void t7(String nm, int n, Map s, Object[] k1, Object[] k2) { - int sum = 0; - timer.start(nm, n * 2); - for (int i = 0; i < n; i++) { - if (s.containsKey(k1[i])) ++sum; - if (s.containsKey(k2[i & absentMask])) ++sum; - } - timer.finish(); - reallyAssert(sum == n); - } - - static void t8(String nm, int n, Map s, Object[] key, int expect) { - int sum = 0; - timer.start(nm, n); - for (int i = 0; i < n; i++) { - if (s.get(key[i]) != null) ++sum; - } - timer.finish(); - reallyAssert(sum == expect); - } - - - static void t9(Map s) { - int sum = 0; - int iters = 20; - timer.start("ContainsValue (/n) ", iters * s.size()); - int step = absentSize / iters; - for (int i = 0; i < absentSize; i += step) - if (s.containsValue(absent[i])) ++sum; - timer.finish(); - reallyAssert(sum != 0); - } - - - static void ktest(Map s, int size, Object[] key) { - timer.start("ContainsKey ", size); - Set ks = s.keySet(); - int sum = 0; - for (int i = 0; i < size; i++) { - if (ks.contains(key[i])) ++sum; - } - timer.finish(); - reallyAssert(sum == size); - } - - - static void ittest1(Map s, int size) { - int sum = 0; - timer.start("Iter Key ", size); - for (Iterator it = s.keySet().iterator(); it.hasNext(); ) { - if (it.next() != MISSING) - ++sum; - } - timer.finish(); - reallyAssert(sum == size); - } - - static void ittest2(Map s, int size) { - int sum = 0; - timer.start("Iter Value ", size); - for (Iterator it = s.values().iterator(); it.hasNext(); ) { - if (it.next() != MISSING) - ++sum; - } - timer.finish(); - reallyAssert(sum == size); - } - static void ittest3(Map s, int size) { - int sum = 0; - timer.start("Iter Entry ", size); - for (Iterator it = s.entrySet().iterator(); it.hasNext(); ) { - if (it.next() != MISSING) - ++sum; - } - timer.finish(); - reallyAssert(sum == size); - } - - static void ittest4(Map s, int size, int pos) { - IdentityHashMap seen = new IdentityHashMap(size); - reallyAssert(s.size() == size); - int sum = 0; - timer.start("Iter XEntry ", size); - Iterator it = s.entrySet().iterator(); - Object k = null; - Object v = null; - for (int i = 0; i < size-pos; ++i) { - Map.Entry x = (Map.Entry)(it.next()); - k = x.getKey(); - v = x.getValue(); - seen.put(k, k); - if (x != MISSING) - ++sum; - } - reallyAssert(s.containsKey(k)); - it.remove(); - reallyAssert(!s.containsKey(k)); - while (it.hasNext()) { - Map.Entry x = (Map.Entry)(it.next()); - Object k2 = x.getKey(); - seen.put(k2, k2); - if (x != MISSING) - ++sum; - } - - reallyAssert(s.size() == size-1); - s.put(k, v); - reallyAssert(seen.size() == size); - timer.finish(); - reallyAssert(sum == size); - reallyAssert(s.size() == size); - } - - - static void ittest(Map s, int size) { - ittest1(s, size); - ittest2(s, size); - ittest3(s, size); - // for (int i = 0; i < size-1; ++i) - // ittest4(s, size, i); - } - - static void entest1(Hashtable ht, int size) { - int sum = 0; - - timer.start("Iter Enumeration Key ", size); - for (Enumeration en = ht.keys(); en.hasMoreElements(); ) { - if (en.nextElement() != MISSING) - ++sum; - } - timer.finish(); - reallyAssert(sum == size); - } - - static void entest2(Hashtable ht, int size) { - int sum = 0; - timer.start("Iter Enumeration Value ", size); - for (Enumeration en = ht.elements(); en.hasMoreElements(); ) { - if (en.nextElement() != MISSING) - ++sum; - } - timer.finish(); - reallyAssert(sum == size); - } - - - static void entest3(Hashtable ht, int size) { - int sum = 0; - - timer.start("Iterf Enumeration Key ", size); - Enumeration en = ht.keys(); - for (int i = 0; i < size; ++i) { - if (en.nextElement() != MISSING) - ++sum; - } - timer.finish(); - reallyAssert(sum == size); - } - - static void entest4(Hashtable ht, int size) { - int sum = 0; - timer.start("Iterf Enumeration Value", size); - Enumeration en = ht.elements(); - for (int i = 0; i < size; ++i) { - if (en.nextElement() != MISSING) - ++sum; - } - timer.finish(); - reallyAssert(sum == size); - } - - static void entest(Map s, int size) { - if (s instanceof Hashtable) { - Hashtable ht = (Hashtable)s; - // entest3(ht, size); - // entest4(ht, size); - entest1(ht, size); - entest2(ht, size); - entest1(ht, size); - entest2(ht, size); - entest1(ht, size); - entest2(ht, size); - } - } - - static void rtest(Map s, int size) { - timer.start("Remove (iterator) ", size); - for (Iterator it = s.keySet().iterator(); it.hasNext(); ) { - it.next(); - it.remove(); - } - timer.finish(); - } - - static void rvtest(Map s, int size) { - timer.start("Remove (iterator) ", size); - for (Iterator it = s.values().iterator(); it.hasNext(); ) { - it.next(); - it.remove(); - } - timer.finish(); - } - - - static void dtest(Map s, int size, Object[] key) { - timer.start("Put (putAll) ", size * 2); - Map s2 = null; - try { - s2 = (Map) (s.getClass().newInstance()); - s2.putAll(s); - } - catch (Exception e) { e.printStackTrace(); return; } - timer.finish(); - - timer.start("Iter Equals ", size * 2); - boolean eqt = s2.equals(s) && s.equals(s2); - reallyAssert(eqt); - timer.finish(); - - timer.start("Iter HashCode ", size * 2); - int shc = s.hashCode(); - int s2hc = s2.hashCode(); - reallyAssert(shc == s2hc); - timer.finish(); - - timer.start("Put (present) ", size); - s2.putAll(s); - timer.finish(); - - timer.start("Iter EntrySet contains ", size * 2); - Set es2 = s2.entrySet(); - int sum = 0; - for (Iterator i1 = s.entrySet().iterator(); i1.hasNext(); ) { - Object entry = i1.next(); - if (es2.contains(entry)) ++sum; - } - timer.finish(); - reallyAssert(sum == size); - - t6("Get ", size, s2, key, absent); - - Object hold = s2.get(key[size-1]); - s2.put(key[size-1], absent[0]); - timer.start("Iter Equals ", size * 2); - eqt = s2.equals(s) && s.equals(s2); - reallyAssert(!eqt); - timer.finish(); - - timer.start("Iter HashCode ", size * 2); - int s1h = s.hashCode(); - int s2h = s2.hashCode(); - reallyAssert(s1h != s2h); - timer.finish(); - - s2.put(key[size-1], hold); - timer.start("Remove (iterator) ", size * 2); - Iterator s2i = s2.entrySet().iterator(); - Set es = s.entrySet(); - while (s2i.hasNext()) - es.remove(s2i.next()); - timer.finish(); - - reallyAssert(s.isEmpty()); - - timer.start("Clear ", size); - s2.clear(); - timer.finish(); - reallyAssert(s2.isEmpty() && s.isEmpty()); - } - - static void stest(Map s, int size) throws Exception { - if (!(s instanceof Serializable)) - return; - System.out.print("Serialize : "); - - for (int i = 0; i < size; i++) { - s.put(new Integer(i), Boolean.TRUE); - } - - long startTime = System.currentTimeMillis(); - - FileOutputStream fs = new FileOutputStream("MapCheck.dat"); - ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(fs)); - out.writeObject(s); - out.close(); - - FileInputStream is = new FileInputStream("MapCheck.dat"); - ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(is)); - Map m = (Map)in.readObject(); - - long endTime = System.currentTimeMillis(); - long time = endTime - startTime; - - System.out.print(time + "ms"); - - if (s instanceof IdentityHashMap) return; - reallyAssert(s.equals(m)); - } - - - static void test(Map s, Object[] key) { - int size = key.length; - - t3("Put (absent) ", size, s, key, size); - t3("Put (present) ", size, s, key, 0); - t7("ContainsKey ", size, s, key, absent); - t4("ContainsKey ", size, s, key, size); - ktest(s, size, key); - t4("ContainsKey ", absentSize, s, absent, 0); - t6("Get ", size, s, key, absent); - t1("Get (present) ", size, s, key, size); - t1("Get (absent) ", absentSize, s, absent, 0); - t2("Remove (absent) ", absentSize, s, absent, 0); - t5("Remove (present) ", size, s, key, size / 2); - t3("Put (half present) ", size, s, key, size / 2); - - ittest(s, size); - entest(s, size); - t9(s); - rtest(s, size); - - t4("ContainsKey ", size, s, key, 0); - t2("Remove (absent) ", size, s, key, 0); - t3("Put (presized) ", size, s, key, size); - dtest(s, size, key); - } - - static class TestTimer { - private String name; - private long numOps; - private long startTime; - private String cname; - - static final java.util.TreeMap accum = new java.util.TreeMap(); - - static void printStats() { - for (Iterator it = accum.entrySet().iterator(); it.hasNext(); ) { - Map.Entry e = (Map.Entry)(it.next()); - Stats stats = ((Stats)(e.getValue())); - int n = stats.number; - double t; - if (n > 0) - t = stats.sum / n; - else - t = stats.least; - long nano = Math.round(1000000.0 * t); - System.out.println(e.getKey() + ": " + nano); - } - } - - void start(String name, long numOps) { - this.name = name; - this.cname = classify(); - this.numOps = numOps; - startTime = System.currentTimeMillis(); - } - - - String classify() { - if (name.startsWith("Get")) - return "Get "; - else if (name.startsWith("Put")) - return "Put "; - else if (name.startsWith("Remove")) - return "Remove "; - else if (name.startsWith("Iter")) - return "Iter "; - else - return null; - } - - void finish() { - long endTime = System.currentTimeMillis(); - long time = endTime - startTime; - double timePerOp = ((double)time)/numOps; - - Object st = accum.get(name); - if (st == null) - accum.put(name, new Stats(timePerOp)); - else { - Stats stats = (Stats) st; - stats.sum += timePerOp; - stats.number++; - if (timePerOp < stats.least) stats.least = timePerOp; - } - - if (cname != null) { - st = accum.get(cname); - if (st == null) - accum.put(cname, new Stats(timePerOp)); - else { - Stats stats = (Stats) st; - stats.sum += timePerOp; - stats.number++; - if (timePerOp < stats.least) stats.least = timePerOp; - } - } - - } - - } - - static class Stats { - double sum = 0; - double least; - int number = 0; - Stats(double t) { least = t; } - } - - static Random rng = new Random(); - - static void shuffle(Object[] keys) { - int size = keys.length; - for (int i=size; i>1; i--) { - int r = rng.nextInt(i); - Object t = keys[i-1]; - keys[i-1] = keys[r]; - keys[r] = t; - } - } - -} diff --git a/src/test/java/net/openhft/chronicle/map/others/MapLoops.java b/src/test/java/net/openhft/chronicle/map/others/MapLoops.java deleted file mode 100644 index a5b1d56fe..000000000 --- a/src/test/java/net/openhft/chronicle/map/others/MapLoops.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright 2014 Higher Frequency Trading - *

- * http://www.higherfrequencytrading.com - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.openhft.chronicle.map.others;/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -/* - * @test - * @bug 4486658 - * @compile -source 1.5 MapLoops.java - * @run main/timeout=1600 MapLoops - * @summary Exercise multithreaded maps, by default net.openhft.chronicle.map.ConcurrentHashMap. - * Multithreaded hash table test. Each thread does a random walk - * though elements of "key" array. On each iteration, it checks if - * table includes key. If absent, with probability pinsert it - * inserts it, and if present, with probability premove it removes - * it. (pinsert and premove are expressed as percentages to simplify - * parsing from command line.) - */ - -import java.util.*; -import java.util.concurrent.*; - -public class MapLoops { - static int nkeys = 10000; - static int pinsert = 60; - static int premove = 2; - static int maxThreads = 100; - static int nops = 100000; - static int removesPerMaxRandom; - static int insertsPerMaxRandom; - - static final ExecutorService pool = Executors.newCachedThreadPool(); - - static final List throwables - = new CopyOnWriteArrayList(); - - public static void main(String[] args) throws Exception { - - Class mapClass = null; - if (args.length > 0) { - try { - mapClass = Class.forName(args[0]); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Class " + args[0] + " not found."); - } - } - else - mapClass = java.util.concurrent.ConcurrentHashMap.class; - - if (args.length > 1) - maxThreads = Integer.parseInt(args[1]); - - if (args.length > 2) - nkeys = Integer.parseInt(args[2]); - - if (args.length > 3) - pinsert = Integer.parseInt(args[3]); - - if (args.length > 4) - premove = Integer.parseInt(args[4]); - - if (args.length > 5) - nops = Integer.parseInt(args[5]); - - // normalize probabilities wrt random number generator - removesPerMaxRandom = (int)(((double)premove/100.0 * 0x7FFFFFFFL)); - insertsPerMaxRandom = (int)(((double)pinsert/100.0 * 0x7FFFFFFFL)); - - System.out.print("Class: " + mapClass.getName()); - System.out.print(" threads: " + maxThreads); - System.out.print(" size: " + nkeys); - System.out.print(" ins: " + pinsert); - System.out.print(" rem: " + premove); - System.out.print(" ops: " + nops); - System.out.println(); - - int k = 1; - int warmups = 2; - for (int i = 1; i <= maxThreads;) { - Thread.sleep(100); - test(i, nkeys, mapClass); - if (warmups > 0) - --warmups; - else if (i == k) { - k = i << 1; - i = i + (i >>> 1); - } - else if (i == 1 && k == 2) { - i = k; - warmups = 1; - } - else - i = k; - } - pool.shutdown(); - if (! pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) - throw new Error(); - - if (! throwables.isEmpty()) - throw new Error - (throwables.size() + " thread(s) terminated abruptly."); - } - - static Integer[] makeKeys(int n) { - LoopHelpers.SimpleRandom rng = new LoopHelpers.SimpleRandom(); - Integer[] key = new Integer[n]; - for (int i = 0; i < key.length; ++i) - key[i] = new Integer(rng.next()); - return key; - } - - static void shuffleKeys(Integer[] key) { - Random rng = new Random(); - for (int i = key.length; i > 1; --i) { - int j = rng.nextInt(i); - Integer tmp = key[j]; - key[j] = key[i-1]; - key[i-1] = tmp; - } - } - - static void test(int i, int nkeys, Class mapClass) throws Exception { - System.out.print("Threads: " + i + "\t:"); - Map map = (Map)mapClass.newInstance(); - Integer[] key = makeKeys(nkeys); - // Uncomment to start with a non-empty table - // for (int j = 0; j < nkeys; j += 4) // start 1/4 occupied - // map.put(key[j], key[j]); - LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer(); - CyclicBarrier barrier = new CyclicBarrier(i+1, timer); - for (int t = 0; t < i; ++t) - pool.execute(new Runner(map, key, barrier)); - barrier.await(); - barrier.await(); - long time = timer.getTime(); - long tpo = time / (i * (long)nops); - System.out.print(LoopHelpers.rightJustify(tpo) + " ns per op"); - double secs = (double)(time) / 1000000000.0; - System.out.println("\t " + secs + "s run time"); - map.clear(); - } - - static class Runner implements Runnable { - final Map map; - final Integer[] key; - final LoopHelpers.SimpleRandom rng = new LoopHelpers.SimpleRandom(); - final CyclicBarrier barrier; - int position; - int total; - - Runner(Map map, Integer[] key, CyclicBarrier barrier) { - this.map = map; - this.key = key; - this.barrier = barrier; - position = key.length / 2; - } - - int step() { - // random-walk around key positions, bunching accesses - int r = rng.next(); - position += (r & 7) - 3; - while (position >= key.length) position -= key.length; - while (position < 0) position += key.length; - - Integer k = key[position]; - Integer x = map.get(k); - - if (x != null) { - if (x.intValue() != k.intValue()) - throw new Error("bad mapping: " + x + " to " + k); - - if (r < removesPerMaxRandom) { - if (map.remove(k) != null) { - position = total % key.length; // move from position - return 2; - } - } - } - else if (r < insertsPerMaxRandom) { - ++position; - map.put(k, k); - return 2; - } - - // Uncomment to add a little computation between accesses - // total += LoopHelpers.compute1(k.intValue()); - total += r; - return 1; - } - - public void run() { - try { - barrier.await(); - int ops = nops; - while (ops > 0) - ops -= step(); - barrier.await(); - } - catch (Throwable throwable) { - synchronized (System.err) { - System.err.println("--------------------------------"); - throwable.printStackTrace(); - } - throwables.add(throwable); - } - } - } -} diff --git a/src/test/java/net/openhft/chronicle/map/others/ToArray.java b/src/test/java/net/openhft/chronicle/map/others/ToArray.java deleted file mode 100644 index 7833a580e..000000000 --- a/src/test/java/net/openhft/chronicle/map/others/ToArray.java +++ /dev/null @@ -1,105 +0,0 @@ -package net.openhft.chronicle.map.others;/* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4486658 8010293 - * @summary thread safety of toArray methods of subCollections - * @author Martin Buchholz - */ - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.IntStream; - -public class ToArray { - - public static void main(String[] args) throws Throwable { - // Execute a number of times to increase the probability of - // failure if there is an issue - for (int i = 0; i < 16; i++) { - executeTest(); - } - } - - static void executeTest() throws Throwable { - final Throwable throwable[] = new Throwable[1]; - final ConcurrentHashMap m = new ConcurrentHashMap<>(); - - // Number of workers equal to the number of processors - // Each worker will put globally unique keys into the map - final int nWorkers = Runtime.getRuntime().availableProcessors(); - final int sizePerWorker = 1024; - final int maxSize = nWorkers * sizePerWorker; - - // The foreman keeps checking that the size of the arrays - // obtained from the key and value sets is never less than the - // previously observed size and is never greater than the maximum size - // NOTE: these size constraints are not specific to toArray and are - // applicable to any form of traversal of the collection views - CompletableFuture foreman = CompletableFuture.runAsync(new Runnable() { - private int prevSize = 0; - - private boolean checkProgress(Object[] a) { - int size = a.length; - if (size < prevSize) throw new RuntimeException("WRONG WAY"); - if (size > maxSize) throw new RuntimeException("OVERSHOOT"); - if (size == maxSize) return true; - prevSize = size; - return false; - } - - @Override - public void run() { - try { - Integer[] empty = new Integer[0]; - while (true) { - if (checkProgress(m.values().toArray())) return; - if (checkProgress(m.keySet().toArray())) return; - if (checkProgress(m.values().toArray(empty))) return; - if (checkProgress(m.keySet().toArray(empty))) return; - } - } - catch (Throwable t) { - throwable[0] = t; - } - } - }); - - // Create workers - // Each worker will put globally unique keys into the map - CompletableFuture[] workers = IntStream.range(0, nWorkers). - mapToObj(w -> CompletableFuture.runAsync(() -> { - for (int i = 0, o = w * sizePerWorker; i < sizePerWorker; i++) - m.put(o + i, i); - })). - toArray(CompletableFuture[]::new); - - // Wait for workers and then foreman to complete - CompletableFuture.allOf(workers).join(); - foreman.join(); - - if (throwable[0] != null) - throw throwable[0]; - } -}