diff --git a/pom.xml b/pom.xml
index ab960c92f..2396b15c5 100755
--- a/pom.xml
+++ b/pom.xml
@@ -15,7 +15,8 @@
~ along with this program. If not, see .
-->
-
+net.openhft
@@ -46,7 +47,7 @@
net.openhftchronicle-bompom
- 1.11.16
+ 1.12.10import
diff --git a/src/main/java/net/openhft/chronicle/hash/impl/SizePrefixedBlob.java b/src/main/java/net/openhft/chronicle/hash/impl/SizePrefixedBlob.java
index 7547d6ef5..d4d47348d 100644
--- a/src/main/java/net/openhft/chronicle/hash/impl/SizePrefixedBlob.java
+++ b/src/main/java/net/openhft/chronicle/hash/impl/SizePrefixedBlob.java
@@ -23,7 +23,7 @@ public final class SizePrefixedBlob {
public static final int SELF_BOOTSTRAPPING_HEADER_OFFSET = 12;
public static final int READY = 0;
- public static final int NOT_READY = 0x80000000;
+ public static final int NOT_COMPLETE = 0x80000000;
public static final int DATA = 0;
public static final int META_DATA = 0x40000000;
diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
index f44b62d3e..305832252 100755
--- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
+++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
@@ -135,6 +135,62 @@ public final class ChronicleMapBuilder implements
LoggerFactory.getLogger(ChronicleMapBuilder.class.getName());
private static final double UNDEFINED_DOUBLE_CONFIG = Double.NaN;
+ private static final ConcurrentHashMap fileLockingControl =
+ new ConcurrentHashMap<>(128);
+ private static int MAX_BOOTSTRAPPING_HEADER_SIZE = (int) MemoryUnit.KILOBYTES.toBytes(16);
+ SerializationBuilder keyBuilder;
+ SerializationBuilder valueBuilder;
+ K averageKey;
+ V averageValue;
+ /**
+ * Default timeout is 1 minute. Even loopback tests converge often in the course of seconds,
+ * let alone WAN replication over many nodes might take tens of seconds.
+ *
+ * TODO review
+ */
+ long cleanupTimeout = 1;
+ TimeUnit cleanupTimeoutUnit = TimeUnit.MINUTES;
+ boolean cleanupRemovedEntries = true;
+
+ //////////////////////////////
+ // Configuration fields
+ DefaultValueProvider defaultValueProvider = DefaultSpi.defaultValueProvider();
+ byte replicationIdentifier = -1;
+ MapMethods methods = DefaultSpi.mapMethods();
+ MapEntryOperations entryOperations = mapEntryOperations();
+ MapRemoteOperations remoteOperations = mapRemoteOperations();
+ // not final because of cloning
+ private ChronicleMapBuilderPrivateAPI privateAPI =
+ new ChronicleMapBuilderPrivateAPI<>(this);
+ // used when configuring the number of segments.
+ private int minSegments = -1;
+ private int actualSegments = -1;
+ // used when reading the number of entries per
+ private long entriesPerSegment = -1L;
+ private long actualChunksPerSegmentTier = -1L;
+ private double averageKeySize = UNDEFINED_DOUBLE_CONFIG;
+ private K sampleKey;
+ private double averageValueSize = UNDEFINED_DOUBLE_CONFIG;
+ private V sampleValue;
+ private int actualChunkSize = 0;
+ private int worstAlignment = -1;
+ private int maxChunksPerEntry = -1;
+ private int alignment = UNDEFINED_ALIGNMENT_CONFIG;
+ private long entries = -1L;
+ private double maxBloatFactor = 1.0;
+ private boolean allowSegmentTiering = true;
+ private double nonTieredSegmentsPercentile = 0.99999;
+ private boolean aligned64BitMemoryOperationsAtomic = OS.is64Bit();
+ private ChecksumEntries checksumEntries = ChecksumEntries.IF_PERSISTED;
+ private boolean putReturnsNull = false;
+ private boolean removeReturnsNull = false;
+ private boolean replicated;
+ private boolean persisted;
+
+ ChronicleMapBuilder(Class keyClass, Class valueClass) {
+ keyBuilder = new SerializationBuilder<>(keyClass);
+ valueBuilder = new SerializationBuilder<>(valueClass);
+ }
private static boolean isDefined(double config) {
return !isNaN(config);
@@ -155,14 +211,8 @@ public final class ChronicleMapBuilder implements
return (long) v;
}
- private static int MAX_BOOTSTRAPPING_HEADER_SIZE = (int) MemoryUnit.KILOBYTES.toBytes(16);
-
- private static final ConcurrentHashMap fileLockingControl =
- new ConcurrentHashMap<>(128);
-
- interface FileIOAction {
- void fileIOAction() throws IOException;
- }
+ //////////////////////////////
+ // Instance fields
/**
* When Chronicle Maps are created using {@link #createPersistedTo(File)} or
@@ -189,73 +239,6 @@ public final class ChronicleMapBuilder implements
});
}
- // not final because of cloning
- private ChronicleMapBuilderPrivateAPI privateAPI =
- new ChronicleMapBuilderPrivateAPI<>(this);
-
- //////////////////////////////
- // Configuration fields
-
- SerializationBuilder keyBuilder;
- SerializationBuilder valueBuilder;
-
- // used when configuring the number of segments.
- private int minSegments = -1;
- private int actualSegments = -1;
- // used when reading the number of entries per
- private long entriesPerSegment = -1L;
- private long actualChunksPerSegmentTier = -1L;
- private double averageKeySize = UNDEFINED_DOUBLE_CONFIG;
- K averageKey;
- private K sampleKey;
- private double averageValueSize = UNDEFINED_DOUBLE_CONFIG;
- V averageValue;
- private V sampleValue;
- private int actualChunkSize = 0;
- private int worstAlignment = -1;
- private int maxChunksPerEntry = -1;
- private int alignment = UNDEFINED_ALIGNMENT_CONFIG;
- private long entries = -1L;
- private double maxBloatFactor = 1.0;
- private boolean allowSegmentTiering = true;
- private double nonTieredSegmentsPercentile = 0.99999;
- private boolean aligned64BitMemoryOperationsAtomic = OS.is64Bit();
-
- enum ChecksumEntries {YES, NO, IF_PERSISTED}
- private ChecksumEntries checksumEntries = ChecksumEntries.IF_PERSISTED;
-
- private boolean putReturnsNull = false;
- private boolean removeReturnsNull = false;
-
- /**
- * Default timeout is 1 minute. Even loopback tests converge often in the course of seconds,
- * let alone WAN replication over many nodes might take tens of seconds.
- *
- * TODO review
- */
- long cleanupTimeout = 1;
- TimeUnit cleanupTimeoutUnit = TimeUnit.MINUTES;
- boolean cleanupRemovedEntries = true;
-
- DefaultValueProvider defaultValueProvider = DefaultSpi.defaultValueProvider();
-
- byte replicationIdentifier = -1;
-
- MapMethods methods = DefaultSpi.mapMethods();
- MapEntryOperations entryOperations = mapEntryOperations();
- MapRemoteOperations remoteOperations = mapRemoteOperations();
-
- //////////////////////////////
- // Instance fields
-
- private boolean replicated;
- private boolean persisted;
-
- ChronicleMapBuilder(Class keyClass, Class valueClass) {
- keyBuilder = new SerializationBuilder<>(keyClass);
- valueBuilder = new SerializationBuilder<>(valueClass);
- }
-
/**
* Returns a new {@code ChronicleMapBuilder} instance which is able to {@linkplain #create()
* create} maps with the specified key and value classes.
@@ -292,6 +275,125 @@ public final class ChronicleMapBuilder implements
return obj != null ? obj + "" : "not configured";
}
+ private static void checkSizeIsStaticallyKnown(SerializationBuilder builder, String role) {
+ if (builder.sizeIsStaticallyKnown) {
+ throw new IllegalStateException("Size of " + builder.tClass +
+ " instances is constant and statically known, shouldn't be specified via " +
+ "average" + role + "Size() or average" + role + "() methods");
+ }
+ }
+
+ private static void checkAverageSize(double averageSize, String role) {
+ if (averageSize <= 0 || isNaN(averageSize) ||
+ Double.isInfinite(averageSize)) {
+ throw new IllegalArgumentException("Average " + role + " size must be a positive, " +
+ "finite number");
+ }
+ }
+
+ private static double averageSizeStoringLength(
+ SerializationBuilder builder, double averageSize) {
+ SizeMarshaller sizeMarshaller = builder.sizeMarshaller();
+ if (averageSize == round(averageSize))
+ return sizeMarshaller.storingLength(round(averageSize));
+ long lower = roundDown(averageSize);
+ long upper = lower + 1;
+ int lowerStoringLength = sizeMarshaller.storingLength(lower);
+ int upperStoringLength = sizeMarshaller.storingLength(upper);
+ if (lowerStoringLength == upperStoringLength)
+ return lowerStoringLength;
+ return lower * (upper - averageSize) + upper * (averageSize - lower);
+ }
+
+ static int greatestCommonDivisor(int a, int b) {
+ if (b == 0) return a;
+ return greatestCommonDivisor(b, a % b);
+ }
+
+ private static int maxDefaultChunksPerAverageEntry(boolean replicated) {
+ // When replicated, having 8 chunks (=> 8 bits in bitsets) per entry seems more wasteful
+ // because when replicated we have bit sets per each remote node, not only allocation
+ // bit set as when non-replicated
+ return replicated ? 4 : 8;
+ }
+
+ private static int estimateSegmentsForEntries(long size) {
+ if (size > 200 << 20)
+ return 256;
+ if (size >= 1 << 20)
+ return 128;
+ if (size >= 128 << 10)
+ return 64;
+ if (size >= 16 << 10)
+ return 32;
+ if (size >= 4 << 10)
+ return 16;
+ if (size >= 1 << 10)
+ return 8;
+ return 1;
+ }
+
+ private static long headerChecksum(ByteBuffer headerBuffer, int headerSize) {
+ return LongHashFunction.xx_r39().hashBytes(headerBuffer, SIZE_WORD_OFFSET, headerSize + 4);
+ }
+
+ private static void writeNotComplete(
+ FileChannel fileChannel, ByteBuffer headerBuffer, int headerSize) throws IOException {
+ //noinspection PointlessBitwiseExpression
+ headerBuffer.putInt(SIZE_WORD_OFFSET, NOT_COMPLETE | DATA | headerSize);
+ headerBuffer.clear().position(SIZE_WORD_OFFSET).limit(SIZE_WORD_OFFSET + 4);
+ writeFully(fileChannel, SIZE_WORD_OFFSET, headerBuffer);
+ }
+
+ /**
+ * @return ByteBuffer, with self bootstrapping header in [position, limit) range
+ */
+ private static ByteBuffer writeHeader(
+ FileChannel fileChannel, VanillaChronicleMap map) throws IOException {
+ ByteBuffer headerBuffer = ByteBuffer.allocate(
+ SELF_BOOTSTRAPPING_HEADER_OFFSET + MAX_BOOTSTRAPPING_HEADER_SIZE);
+ headerBuffer.order(LITTLE_ENDIAN);
+
+ Bytes headerBytes = Bytes.wrapForWrite(headerBuffer);
+ headerBytes.writePosition(SELF_BOOTSTRAPPING_HEADER_OFFSET);
+ Wire wire = new TextWire(headerBytes);
+ wire.getValueOut().typedMarshallable(map);
+
+ int headerLimit = (int) headerBytes.writePosition();
+ int headerSize = headerLimit - SELF_BOOTSTRAPPING_HEADER_OFFSET;
+ // First set readiness bit to READY, to compute checksum correctly
+ //noinspection PointlessBitwiseExpression
+ headerBuffer.putInt(SIZE_WORD_OFFSET, READY | DATA | headerSize);
+
+ long checksum = headerChecksum(headerBuffer, headerSize);
+ headerBuffer.putLong(HEADER_OFFSET, checksum);
+
+ // Set readiness bit to NOT_COMPLETE, because the Chronicle Map instance is not actually
+ // ready yet
+ //noinspection PointlessBitwiseExpression
+ headerBuffer.putInt(SIZE_WORD_OFFSET, NOT_COMPLETE | DATA | headerSize);
+
+ // Write the size-prefixed blob to the file
+ headerBuffer.position(0).limit(headerLimit);
+ writeFully(fileChannel, 0, headerBuffer);
+
+ headerBuffer.position(SELF_BOOTSTRAPPING_HEADER_OFFSET);
+ return headerBuffer;
+ }
+
+ private static void commitChronicleMapReady(
+ VanillaChronicleHash map, RandomAccessFile raf, ByteBuffer headerBuffer, int headerSize)
+ throws IOException {
+ FileChannel fileChannel = raf.getChannel();
+ // see HCOLL-396
+ map.msync();
+
+ //noinspection PointlessBitwiseExpression
+ headerBuffer.putInt(SIZE_WORD_OFFSET, READY | DATA | headerSize);
+ headerBuffer.clear().position(SIZE_WORD_OFFSET).limit(SIZE_WORD_OFFSET + 4);
+ writeFully(fileChannel, SIZE_WORD_OFFSET, headerBuffer);
+ }
+
@Override
public ChronicleMapBuilder clone() {
try {
@@ -475,22 +577,6 @@ public final class ChronicleMapBuilder implements
return this;
}
- private static void checkSizeIsStaticallyKnown(SerializationBuilder builder, String role) {
- if (builder.sizeIsStaticallyKnown) {
- throw new IllegalStateException("Size of " + builder.tClass +
- " instances is constant and statically known, shouldn't be specified via " +
- "average" + role + "Size() or average" + role + "() methods");
- }
- }
-
- private static void checkAverageSize(double averageSize, String role) {
- if (averageSize <= 0 || isNaN(averageSize) ||
- Double.isInfinite(averageSize)) {
- throw new IllegalArgumentException("Average " + role + " size must be a positive, " +
- "finite number");
- }
- }
-
/**
* Configures the constant number of bytes, taken by serialized form of values, put into maps,
* created by this builder. This is done by providing the {@code sampleValue}, all values should
@@ -562,16 +648,6 @@ public final class ChronicleMapBuilder implements
return keyBuilder;
}
- static class EntrySizeInfo {
- final double averageEntrySize;
- final int worstAlignment;
-
- public EntrySizeInfo(double averageEntrySize, int worstAlignment) {
- this.averageEntrySize = averageEntrySize;
- this.worstAlignment = worstAlignment;
- }
- }
-
private EntrySizeInfo entrySizeInfo() {
double size = 0;
double keySize = averageKeySize();
@@ -643,20 +719,6 @@ public final class ChronicleMapBuilder implements
return keyBuilder.constantSizeMarshaller() || sampleKey != null;
}
- private static double averageSizeStoringLength(
- SerializationBuilder builder, double averageSize) {
- SizeMarshaller sizeMarshaller = builder.sizeMarshaller();
- if (averageSize == round(averageSize))
- return sizeMarshaller.storingLength(round(averageSize));
- long lower = roundDown(averageSize);
- long upper = lower + 1;
- int lowerStoringLength = sizeMarshaller.storingLength(lower);
- int upperStoringLength = sizeMarshaller.storingLength(upper);
- if (lowerStoringLength == upperStoringLength)
- return lowerStoringLength;
- return lower * (upper - averageSize) + upper * (averageSize - lower);
- }
-
private int worstAlignmentAssumingChunkSize(
long constantSizeBeforeAlignment, int chunkSize) {
int alignment = valueAlignment();
@@ -687,11 +749,6 @@ public final class ChronicleMapBuilder implements
this.worstAlignment = worstAlignment;
}
- static int greatestCommonDivisor(int a, int b) {
- if (b == 0) return a;
- return greatestCommonDivisor(b, a % b);
- }
-
long chunkSize() {
if (actualChunkSize > 0)
return actualChunkSize;
@@ -720,13 +777,6 @@ public final class ChronicleMapBuilder implements
return (entrySizeInfo().averageEntrySize + chunkSize - 1) / chunkSize;
}
- private static int maxDefaultChunksPerAverageEntry(boolean replicated) {
- // When replicated, having 8 chunks (=> 8 bits in bitsets) per entry seems more wasteful
- // because when replicated we have bit sets per each remote node, not only allocation
- // bit set as when non-replicated
- return replicated ? 4 : 8;
- }
-
@Override
public ChronicleMapBuilder maxChunksPerEntry(int maxChunksPerEntry) {
if (maxChunksPerEntry < 1)
@@ -930,22 +980,6 @@ public final class ChronicleMapBuilder implements
: segmentsForEntries;
}
- private static int estimateSegmentsForEntries(long size) {
- if (size > 200 << 20)
- return 256;
- if (size >= 1 << 20)
- return 128;
- if (size >= 128 << 10)
- return 64;
- if (size >= 16 << 10)
- return 32;
- if (size >= 4 << 10)
- return 16;
- if (size >= 1 << 10)
- return 8;
- return 1;
- }
-
@Override
public ChronicleMapBuilder actualSegments(int actualSegments) {
checkSegments(actualSegments);
@@ -1544,7 +1578,7 @@ public final class ChronicleMapBuilder implements
int sizeWord = headerBuffer.getInt(SIZE_WORD_OFFSET);
if (!SizePrefixedBlob.isReady(sizeWord)) {
if (recover) {
- LOG.error("size-prefixed blob readiness bit is set to NOT_READY");
+ LOG.error("size-prefixed blob readiness bit is set to NOT_COMPLETE");
// the bit will be overwritten to READY in the end of recovery procedure, so nothing
// to fix right here
} else {
@@ -1562,10 +1596,6 @@ public final class ChronicleMapBuilder implements
return headerBuffer;
}
- private static long headerChecksum(ByteBuffer headerBuffer, int headerSize) {
- return LongHashFunction.xx_r39().hashBytes(headerBuffer, SIZE_WORD_OFFSET, headerSize + 4);
- }
-
private VanillaChronicleMap createWithNewFile(
VanillaChronicleMap map, File file, RandomAccessFile raf,
ByteBuffer headerBuffer, int headerSize) throws IOException {
@@ -1609,7 +1639,7 @@ public final class ChronicleMapBuilder implements
map.createMappedStoreAndSegments();
} else {
if (!overrideBuilderConfig)
- writeNotReady(fileChannel, headerBuffer, headerSize);
+ writeNotComplete(fileChannel, headerBuffer, headerSize);
// if overrideBuilderConfig = true, readiness bit is already set
// in writeHeader() call
map.recover();
@@ -1625,63 +1655,6 @@ public final class ChronicleMapBuilder implements
}
}
- private static void writeNotReady(
- FileChannel fileChannel, ByteBuffer headerBuffer, int headerSize) throws IOException {
- //noinspection PointlessBitwiseExpression
- headerBuffer.putInt(SIZE_WORD_OFFSET, NOT_READY | DATA | headerSize);
- headerBuffer.clear().position(SIZE_WORD_OFFSET).limit(SIZE_WORD_OFFSET + 4);
- writeFully(fileChannel, SIZE_WORD_OFFSET, headerBuffer);
- }
-
- /**
- * @return ByteBuffer, with self bootstrapping header in [position, limit) range
- */
- private static ByteBuffer writeHeader(
- FileChannel fileChannel, VanillaChronicleMap map) throws IOException {
- ByteBuffer headerBuffer = ByteBuffer.allocate(
- SELF_BOOTSTRAPPING_HEADER_OFFSET + MAX_BOOTSTRAPPING_HEADER_SIZE);
- headerBuffer.order(LITTLE_ENDIAN);
-
- Bytes headerBytes = Bytes.wrapForWrite(headerBuffer);
- headerBytes.writePosition(SELF_BOOTSTRAPPING_HEADER_OFFSET);
- Wire wire = new TextWire(headerBytes);
- wire.getValueOut().typedMarshallable(map);
-
- int headerLimit = (int) headerBytes.writePosition();
- int headerSize = headerLimit - SELF_BOOTSTRAPPING_HEADER_OFFSET;
- // First set readiness bit to READY, to compute checksum correctly
- //noinspection PointlessBitwiseExpression
- headerBuffer.putInt(SIZE_WORD_OFFSET, READY | DATA | headerSize);
-
- long checksum = headerChecksum(headerBuffer, headerSize);
- headerBuffer.putLong(HEADER_OFFSET, checksum);
-
- // Set readiness bit to NOT_READY, because the Chronicle Map instance is not actually
- // ready yet
- //noinspection PointlessBitwiseExpression
- headerBuffer.putInt(SIZE_WORD_OFFSET, NOT_READY | DATA | headerSize);
-
- // Write the size-prefixed blob to the file
- headerBuffer.position(0).limit(headerLimit);
- writeFully(fileChannel, 0, headerBuffer);
-
- headerBuffer.position(SELF_BOOTSTRAPPING_HEADER_OFFSET);
- return headerBuffer;
- }
-
- private static void commitChronicleMapReady(
- VanillaChronicleHash map, RandomAccessFile raf, ByteBuffer headerBuffer, int headerSize)
- throws IOException {
- FileChannel fileChannel = raf.getChannel();
- // see HCOLL-396
- map.msync();
-
- //noinspection PointlessBitwiseExpression
- headerBuffer.putInt(SIZE_WORD_OFFSET, READY | DATA | headerSize);
- headerBuffer.clear().position(SIZE_WORD_OFFSET).limit(SIZE_WORD_OFFSET + 4);
- writeFully(fileChannel, SIZE_WORD_OFFSET, headerBuffer);
- }
-
ChronicleMap createWithoutFile() {
replicated = replicationIdentifier != -1;
persisted = false;
@@ -1778,10 +1751,10 @@ public final class ChronicleMapBuilder implements
/**
* Inject your SPI code around basic {@code ChronicleMap}'s operations with entries:
* removing entries, replacing entries' value and inserting new entries.
- *
+ *
*
This affects behaviour of ordinary map.put(), map.remove(), etc. calls, as well as removes
* and replacing values during iterations, remote map calls and
- * internal replication operations.
+ * internal replication operations.
*/
public ChronicleMapBuilder entryOperations(MapEntryOperations entryOperations) {
Objects.requireNonNull(entryOperations);
@@ -1793,7 +1766,7 @@ public final class ChronicleMapBuilder implements
* Inject your SPI around logic of all {@code ChronicleMap}'s operations with individual keys:
* from {@link ChronicleMap#containsKey} to {@link ChronicleMap#acquireUsing} and
* {@link ChronicleMap#merge}.
- *
+ *
*
This affects behaviour of ordinary map calls, as well as remote calls.
*/
public ChronicleMapBuilder mapMethods(MapMethods mapMethods) {
@@ -1808,5 +1781,21 @@ public final class ChronicleMapBuilder implements
this.remoteOperations = remoteOperations;
return this;
}
+
+ enum ChecksumEntries {YES, NO, IF_PERSISTED}
+
+ interface FileIOAction {
+ void fileIOAction() throws IOException;
+ }
+
+ static class EntrySizeInfo {
+ final double averageEntrySize;
+ final int worstAlignment;
+
+ public EntrySizeInfo(double averageEntrySize, int worstAlignment) {
+ this.averageEntrySize = averageEntrySize;
+ this.worstAlignment = worstAlignment;
+ }
+ }
}
diff --git a/src/test/java/net/openhft/chronicle/map/CHMLatencyTestMain.java b/src/test/java/net/openhft/chronicle/map/CHMLatencyTestMain.java
index f169d9bac..a95d94c1d 100755
--- a/src/test/java/net/openhft/chronicle/map/CHMLatencyTestMain.java
+++ b/src/test/java/net/openhft/chronicle/map/CHMLatencyTestMain.java
@@ -17,6 +17,7 @@
package net.openhft.chronicle.map;
import net.openhft.affinity.AffinityLock;
+import net.openhft.chronicle.core.Jvm;
import net.openhft.chronicle.core.values.LongValue;
import net.openhft.chronicle.values.Values;
@@ -75,8 +76,8 @@ public class CHMLatencyTestMain {
file.delete();
ChronicleMap countersMap =
ChronicleMapBuilder.of(LongValue.class, LongValue.class)
- .entries(KEYS)
- .createPersistedTo(file);
+ .entries(KEYS)
+ .createPersistedTo(file);
// add keys
LongValue key = Values.newHeapInstance(LongValue.class);
@@ -142,13 +143,8 @@ public class CHMLatencyTestMain {
@Override
public void run() {
- while (running) {
- try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
- e.printStackTrace();
- break;
- }
+ while (running && !Thread.currentThread().isInterrupted()) {
+ Jvm.pause(1);
long delay = System.nanoTime() - sample;
if (delay > 1000 * 1000) {
System.out.println("\n" + (System.currentTimeMillis() - START_TIME) + " : Delay of " + delay / 100000 / 10.0 + " ms.");
diff --git a/src/test/java/net/openhft/chronicle/map/CHMTest5.java b/src/test/java/net/openhft/chronicle/map/CHMTest5.java
index 58f377c1f..e22e02b22 100644
--- a/src/test/java/net/openhft/chronicle/map/CHMTest5.java
+++ b/src/test/java/net/openhft/chronicle/map/CHMTest5.java
@@ -16,12 +16,12 @@
package net.openhft.chronicle.map;
-import net.openhft.chronicle.algo.bytes.Access;
import net.openhft.chronicle.algo.locks.AcquisitionStrategies;
import net.openhft.chronicle.algo.locks.ReadWriteLockingStrategy;
import net.openhft.chronicle.algo.locks.TryAcquireOperations;
import net.openhft.chronicle.algo.locks.VanillaReadWriteWithWaitsLockingStrategy;
import net.openhft.chronicle.bytes.Byteable;
+import net.openhft.chronicle.map.utility.ProcessInstanceLimiter;
import net.openhft.chronicle.values.Array;
import net.openhft.chronicle.values.Group;
import net.openhft.chronicle.values.Values;
@@ -229,14 +229,7 @@ public class CHMTest5 {
}
public static void pause(long pause) {
- long start = System.currentTimeMillis();
- long elapsedTime;
- while ((elapsedTime = System.currentTimeMillis() - start) < pause) {
- try {
- Thread.sleep(pause - elapsedTime);
- } catch (InterruptedException e) {
- }
- }
+ ProcessInstanceLimiter.pause(pause);
}
public interface CHMTest5Data {
diff --git a/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java b/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java
index cb1b9dd35..94db8d75c 100644
--- a/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java
+++ b/src/test/java/net/openhft/chronicle/map/CHMUseCasesTest.java
@@ -19,7 +19,7 @@ package net.openhft.chronicle.map;
import com.google.common.primitives.Chars;
import net.openhft.chronicle.bytes.Bytes;
import net.openhft.chronicle.bytes.BytesMarshallable;
-import net.openhft.chronicle.core.Maths;
+import net.openhft.chronicle.core.Jvm;
import net.openhft.chronicle.core.util.SerializableFunction;
import net.openhft.chronicle.core.values.*;
import net.openhft.chronicle.hash.serialization.DataAccess;
@@ -54,6 +54,103 @@ import static net.openhft.chronicle.core.Maths.divideRoundUp;
import static net.openhft.chronicle.map.fromdocs.OpenJDKAndHashMapExamplesTest.parseYYYYMMDD;
import static org.junit.Assert.*;
+enum ToString implements SerializableFunction