You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by dc...@apache.org on 2021/08/19 22:18:24 UTC

svn commit: r49567 [10/14] - in /dev/datasketches/memory/2.0.0-RC1: ./ apache-datasketches-memory-2.0.0-src/ apache-datasketches-memory-2.0.0-src/datasketches-memory-java11/ apache-datasketches-memory-2.0.0-src/datasketches-memory-java11/src/ apache-da...

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/CompareAndCopy.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/CompareAndCopy.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/CompareAndCopy.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,522 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import static org.apache.datasketches.memory.internal.UnsafeUtil.CHAR_SHIFT;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.DOUBLE_SHIFT;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.FLOAT_SHIFT;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.INT_SHIFT;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.LONG_SHIFT;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.SHORT_SHIFT;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.checkBounds;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
+import static org.apache.datasketches.memory.internal.Util.UNSAFE_COPY_THRESHOLD_BYTES;
+
+/**
+ * @author Lee Rhodes
+ */
+@SuppressWarnings("restriction")
+final class CompareAndCopy {
+
+  private CompareAndCopy() { }
+
+  static int compare(
+      final BaseStateImpl state1, final long offsetBytes1, final long lengthBytes1,
+      final BaseStateImpl state2, final long offsetBytes2, final long lengthBytes2) {
+    state1.checkValid();
+    checkBounds(offsetBytes1, lengthBytes1, state1.getCapacity());
+    state2.checkValid();
+    checkBounds(offsetBytes2, lengthBytes2, state2.getCapacity());
+    final long cumOff1 = state1.getCumulativeOffset(offsetBytes1);
+    final long cumOff2 = state2.getCumulativeOffset(offsetBytes2);
+    final Object arr1 = state1.getUnsafeObject();
+    final Object arr2 = state2.getUnsafeObject();
+    if ((arr1 != arr2) || (cumOff1 != cumOff2)) {
+      final long lenBytes = Math.min(lengthBytes1, lengthBytes2);
+      for (long i = 0; i < lenBytes; i++) {
+        final int byte1 = unsafe.getByte(arr1, cumOff1 + i);
+        final int byte2 = unsafe.getByte(arr2, cumOff2 + i);
+        if (byte1 < byte2) { return -1; }
+        if (byte1 > byte2) { return  1; }
+      }
+    }
+    return Long.compare(lengthBytes1, lengthBytes2);
+  }
+
+  static boolean equals(final BaseStateImpl state1, final BaseStateImpl state2) {
+    final long cap1 = state1.getCapacity();
+    final long cap2 = state2.getCapacity();
+    return (cap1 == cap2) && equals(state1, 0, state2, 0, cap1);
+  }
+
+  //Developer notes: this is subtlely different from (campare == 0) in that this has an early
+  // stop if the arrays and offsets are the same as there is only one length.  Also this can take
+  // advantage of chunking with longs, while compare cannot.
+  static boolean equals(
+      final BaseStateImpl state1, final long offsetBytes1,
+      final BaseStateImpl state2, final long offsetBytes2, long lengthBytes) {
+    state1.checkValid();
+    checkBounds(offsetBytes1, lengthBytes, state1.getCapacity());
+    state2.checkValid();
+    checkBounds(offsetBytes2, lengthBytes, state2.getCapacity());
+    long cumOff1 = state1.getCumulativeOffset(offsetBytes1);
+    long cumOff2 = state2.getCumulativeOffset(offsetBytes2);
+    final Object arr1 = state1.getUnsafeObject(); //could be null
+    final Object arr2 = state2.getUnsafeObject(); //could be null
+    if ((arr1 == arr2) && (cumOff1 == cumOff2)) { return true; }
+
+    while (lengthBytes >= Long.BYTES) {
+      final int chunk = (int) Math.min(lengthBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      // int-counted loop to avoid safepoint polls (otherwise why we chunk by
+      // UNSAFE_COPY_MEMORY_THRESHOLD)
+      int i = 0;
+      for (; i <= (chunk - Long.BYTES); i += Long.BYTES) {
+        final long v1 = unsafe.getLong(arr1, cumOff1 + i);
+        final long v2 = unsafe.getLong(arr2, cumOff2 + i);
+        if (v1 != v2) { return false; }
+      }
+      lengthBytes -= i;
+      cumOff1 += i;
+      cumOff2 += i;
+    }
+    //check the remainder bytes, if any
+    return (lengthBytes == 0) || equalsByBytes(arr1, cumOff1, arr2, cumOff2, (int) lengthBytes);
+  }
+
+  //use only for short runs
+  private static boolean equalsByBytes(final Object arr1, final long cumOff1, final Object arr2,
+      final long cumOff2, final int lenBytes) {
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lenBytes; i++) {
+      final int v1 = unsafe.getByte(arr1, cumOff1 + i);
+      final int v2 = unsafe.getByte(arr2, cumOff2 + i);
+      if (v1 != v2) { return false; }
+    }
+    return true;
+  }
+
+  static void copy(final BaseStateImpl srcState, final long srcOffsetBytes,
+      final BaseStateImpl dstState, final long dstOffsetBytes, final long lengthBytes) {
+    srcState.checkValid();
+    checkBounds(srcOffsetBytes, lengthBytes, srcState.getCapacity());
+    dstState.checkValid();
+    checkBounds(dstOffsetBytes, lengthBytes, dstState.getCapacity());
+    final long srcAdd = srcState.getCumulativeOffset(srcOffsetBytes);
+    final long dstAdd = dstState.getCumulativeOffset(dstOffsetBytes);
+    copyMemory(srcState.getUnsafeObject(), srcAdd, dstState.getUnsafeObject(), dstAdd,
+        lengthBytes);
+  }
+
+  //Used by all of the get/put array methods in BufferImpl and MemoryImpl classes
+  static final void copyMemoryCheckingDifferentObject(final Object srcUnsafeObj,
+      final long srcAdd, final Object dstUnsafeObj, final long dstAdd, final long lengthBytes) {
+    if (srcUnsafeObj != dstUnsafeObj) {
+      copyNonOverlappingMemoryWithChunking(srcUnsafeObj, srcAdd, dstUnsafeObj, dstAdd,
+          lengthBytes);
+    } else {
+      throw new IllegalArgumentException("Not expecting to copy to/from array which is the "
+          + "underlying object of the memory at the same time");
+    }
+  }
+
+  //only valid and bounds checks have been performed at this point
+  private static void copyMemory(final Object srcUnsafeObj, final long srcAdd,
+      final Object dstUnsafeObj, final long dstAdd, final long lengthBytes) {
+    if (srcUnsafeObj != dstUnsafeObj) {
+      //either srcArray != dstArray OR one of them is off-heap
+      copyNonOverlappingMemoryWithChunking(srcUnsafeObj, srcAdd, dstUnsafeObj, dstAdd,
+          lengthBytes);
+    } else { //either srcArray == dstArray OR both src and dst are off-heap
+      copyMemoryOverlapAddressCheck(srcUnsafeObj, srcAdd, dstUnsafeObj, dstAdd, lengthBytes);
+    }
+  }
+
+  /**
+   * At this point either srcArray == dstArray OR both src and dst are off-heap.
+   * Performs overlapping address check. If addresses do not overlap, proceed to
+   * {@link #copyNonOverlappingMemoryWithChunking(Object, long, Object, long, long)}; otherwise
+   * fall back on <i>Unsafe.copyMemory(...)</i> tolerating potentially long
+   * Time to Safe Point pauses.
+   * If srcAdd == dstAdd an exception will be thrown.
+   * @param srcUnsafeObj The source array object, it may be null.
+   * @param srcAdd The cumulative source offset
+   * @param dstUnsafeObj The destination array object, it may be null
+   * @param dstAdd The cumulative destination offset
+   * @param lengthBytes The length to be copied in bytes
+   */
+  private static void copyMemoryOverlapAddressCheck(final Object srcUnsafeObj, final long srcAdd,
+      final Object dstUnsafeObj, final long dstAdd, final long lengthBytes) {
+    if (((srcAdd + lengthBytes) <= dstAdd) || ((dstAdd + lengthBytes) <= srcAdd)) {
+      copyNonOverlappingMemoryWithChunking(srcUnsafeObj, srcAdd, dstUnsafeObj, dstAdd,
+          lengthBytes);
+      return;
+    }
+    if (srcAdd == dstAdd) {
+      throw new IllegalArgumentException(
+          "Attempt to copy a block of memory exactly in-place, should be a bug");
+    }
+    // If regions do overlap, fall back to unsafe.copyMemory, tolerating potentially long
+    // Time to Safe Point pauses.
+    unsafe.copyMemory(srcUnsafeObj, srcAdd, dstUnsafeObj, dstAdd, lengthBytes);
+  }
+
+  /**
+   * This copies only non-overlapping memory in chunks to avoid safepoint delays.
+   * Java 9 may not require the chunking.
+   * @param srcUnsafeObj The source array object, it may be null.
+   * @param srcAdd The cumulative source offset
+   * @param dstUnsafeObj The destination array object, it may be null
+   * @param dstAdd The cumulative destination offset
+   * @param lengthBytes The length to be copied in bytes
+   * @see #UNSAFE_COPY_THRESHOLD_BYTES
+   */
+  private static void copyNonOverlappingMemoryWithChunking(final Object srcUnsafeObj,
+      long srcAdd, final Object dstUnsafeObj, long dstAdd, long lengthBytes) {
+    while (lengthBytes > 0) {
+      final long chunk = Math.min(lengthBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      unsafe.copyMemory(srcUnsafeObj, srcAdd, dstUnsafeObj, dstAdd, chunk);
+      lengthBytes -= chunk;
+      srcAdd += chunk;
+      dstAdd += chunk;
+    }
+  }
+
+  static void getNonNativeChars(final Object unsafeObj, long cumOffsetBytes,
+      long copyBytes, final char[] dstArray, int dstOffsetChars,
+      int lengthChars) {
+    checkBounds(dstOffsetChars, lengthChars, dstArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkChars = (int) (chunkBytes >> CHAR_SHIFT);
+      getCharArrayChunk(unsafeObj, cumOffsetBytes, dstArray, dstOffsetChars, chunkChars);
+      cumOffsetBytes += chunkBytes;
+      dstOffsetChars += chunkChars;
+      copyBytes -= chunkBytes;
+      lengthChars -= chunkChars;
+    }
+    getCharArrayChunk(unsafeObj, cumOffsetBytes, dstArray, dstOffsetChars, lengthChars);
+  }
+
+  private static void getCharArrayChunk(final Object unsafeObj, final long cumOffsetBytes,
+      final char[] dstArray, final int dstOffsetChars, final int lengthChars) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthChars; i++) {
+      dstArray[dstOffsetChars + i] = Character.reverseBytes(
+          unsafe.getChar(unsafeObj, cumOffsetBytes + (((long) i) << CHAR_SHIFT)));
+    }
+  }
+
+  static void getNonNativeDoubles(final Object unsafeObj, long cumOffsetBytes,
+      long copyBytes, final double[] dstArray, int dstOffsetDoubles,
+      int lengthDoubles) {
+    checkBounds(dstOffsetDoubles, lengthDoubles, dstArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkDoubles = (int) (chunkBytes >> DOUBLE_SHIFT);
+      getDoubleArrayChunk(unsafeObj, cumOffsetBytes,
+          dstArray, dstOffsetDoubles, chunkDoubles);
+      cumOffsetBytes += chunkBytes;
+      dstOffsetDoubles += chunkDoubles;
+      copyBytes -= chunkBytes;
+      lengthDoubles -= chunkDoubles;
+    }
+    getDoubleArrayChunk(unsafeObj, cumOffsetBytes,
+        dstArray, dstOffsetDoubles, lengthDoubles);
+  }
+
+  private static void getDoubleArrayChunk(final Object unsafeObj, final long cumOffsetBytes,
+      final double[] dstArray, final int dstOffsetDoubles, final int lengthDoubles) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthDoubles; i++) {
+      dstArray[dstOffsetDoubles + i] = Double.longBitsToDouble(Long.reverseBytes(
+          unsafe.getLong(unsafeObj, cumOffsetBytes + (((long) i) << DOUBLE_SHIFT))));
+    }
+  }
+
+  static void getNonNativeFloats(final Object unsafeObj, long cumOffsetBytes,
+      long copyBytes, final float[] dstArray, int dstOffsetFloats,
+      int lengthFloats) {
+    checkBounds(dstOffsetFloats, lengthFloats, dstArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkFloats = (int) (chunkBytes >> FLOAT_SHIFT);
+      getFloatArrayChunk(unsafeObj, cumOffsetBytes, dstArray, dstOffsetFloats, chunkFloats);
+      cumOffsetBytes += chunkBytes;
+      dstOffsetFloats += chunkFloats;
+      copyBytes -= chunkBytes;
+      lengthFloats -= chunkFloats;
+    }
+    getFloatArrayChunk(unsafeObj, cumOffsetBytes, dstArray, dstOffsetFloats, lengthFloats);
+  }
+
+  private static void getFloatArrayChunk(final Object unsafeObj, final long cumOffsetBytes,
+      final float[] dstArray, final int dstOffsetFloats, final int lengthFloats) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthFloats; i++) {
+      dstArray[dstOffsetFloats + i] = Float.intBitsToFloat(Integer.reverseBytes(
+          unsafe.getInt(unsafeObj, cumOffsetBytes + (((long) i) << FLOAT_SHIFT))));
+    }
+  }
+
+  static void getNonNativeInts(final Object unsafeObj, long cumOffsetBytes,
+      long copyBytes, final int[] dstArray, int dstOffsetInts,
+      int lengthInts) {
+    checkBounds(dstOffsetInts, lengthInts, dstArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkInts = (int) (chunkBytes >> INT_SHIFT);
+      getIntArrayChunk(unsafeObj, cumOffsetBytes, dstArray, dstOffsetInts, chunkInts);
+      cumOffsetBytes += chunkBytes;
+      dstOffsetInts += chunkInts;
+      copyBytes -= chunkBytes;
+      lengthInts -= chunkInts;
+    }
+    getIntArrayChunk(unsafeObj, cumOffsetBytes, dstArray, dstOffsetInts, lengthInts);
+  }
+
+  private static void getIntArrayChunk(final Object unsafeObj, final long cumOffsetBytes,
+      final int[] dstArray, final int dstOffsetInts, final int lengthInts) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthInts; i++) {
+      dstArray[dstOffsetInts + i] = Integer.reverseBytes(
+          unsafe.getInt(unsafeObj, cumOffsetBytes + (((long) i) << INT_SHIFT)));
+    }
+  }
+
+  static void getNonNativeLongs(final Object unsafeObj, long cumOffsetBytes,
+      long copyBytes, final long[] dstArray, int dstOffsetLongs,
+      int lengthLongs) {
+    checkBounds(dstOffsetLongs, lengthLongs, dstArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkLongs = (int) (chunkBytes >> LONG_SHIFT);
+      getLongArrayChunk(unsafeObj, cumOffsetBytes, dstArray, dstOffsetLongs, chunkLongs);
+      cumOffsetBytes += chunkBytes;
+      dstOffsetLongs += chunkLongs;
+      copyBytes -= chunkBytes;
+      lengthLongs -= chunkLongs;
+    }
+    getLongArrayChunk(unsafeObj, cumOffsetBytes, dstArray, dstOffsetLongs, lengthLongs);
+  }
+
+  private static void getLongArrayChunk(final Object unsafeObj, final long cumOffsetBytes,
+      final long[] dstArray, final int dstOffsetLongs, final int lengthLongs) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthLongs; i++) {
+      dstArray[dstOffsetLongs + i] = Long.reverseBytes(
+          unsafe.getLong(unsafeObj, cumOffsetBytes + (((long) i) << LONG_SHIFT)));
+    }
+  }
+
+  static void getNonNativeShorts(final Object unsafeObj, long cumOffsetBytes,
+      long copyBytes, final short[] dstArray, int dstOffsetShorts,
+      int lengthShorts) {
+    checkBounds(dstOffsetShorts, lengthShorts, dstArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkShorts = (int) (chunkBytes >> SHORT_SHIFT);
+      getShortArrayChunk(unsafeObj, cumOffsetBytes, dstArray, dstOffsetShorts, chunkShorts);
+      cumOffsetBytes += chunkBytes;
+      dstOffsetShorts += chunkShorts;
+      copyBytes -= chunkBytes;
+      lengthShorts -= chunkShorts;
+    }
+    getShortArrayChunk(unsafeObj, cumOffsetBytes, dstArray, dstOffsetShorts, lengthShorts);
+  }
+
+  private static void getShortArrayChunk(final Object unsafeObj, final long cumOffsetBytes,
+      final short[] dstArray, final int dstOffsetShorts, final int lengthShorts) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthShorts; i++) {
+      dstArray[dstOffsetShorts + i] = Short.reverseBytes(
+          unsafe.getShort(unsafeObj, cumOffsetBytes + (((long) i) << SHORT_SHIFT)));
+    }
+  }
+
+  static void putNonNativeChars(final char[] srcArray, int srcOffsetChars, int lengthChars,
+      long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
+    checkBounds(srcOffsetChars, lengthChars, srcArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkChars = (int) (chunkBytes >> CHAR_SHIFT);
+      putCharArrayChunk(srcArray, srcOffsetChars, chunkChars, unsafeObj, cumOffsetBytes);
+      cumOffsetBytes += chunkBytes;
+      srcOffsetChars += chunkChars;
+      copyBytes -= chunkBytes;
+      lengthChars -= chunkChars;
+    }
+    putCharArrayChunk(srcArray, srcOffsetChars, lengthChars, unsafeObj, cumOffsetBytes);
+  }
+
+  private static void putCharArrayChunk(final char[] srcArray, final int srcOffsetChars,
+      final int lengthChars, final Object unsafeObj, final long cumOffsetBytes) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthChars; i++) {
+      unsafe.putChar(unsafeObj, cumOffsetBytes + (((long) i) << CHAR_SHIFT),
+          Character.reverseBytes(srcArray[srcOffsetChars + i]));
+    }
+  }
+
+  static void putNonNativeDoubles(final double[] srcArray, int srcOffsetDoubles,
+      int lengthDoubles, long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
+    checkBounds(srcOffsetDoubles, lengthDoubles, srcArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkDoubles = (int) (chunkBytes >> DOUBLE_SHIFT);
+      putDoubleArrayChunk(srcArray, srcOffsetDoubles, chunkDoubles,
+          unsafeObj, cumOffsetBytes);
+      cumOffsetBytes += chunkBytes;
+      srcOffsetDoubles += chunkDoubles;
+      copyBytes -= chunkBytes;
+      lengthDoubles -= chunkDoubles;
+    }
+    putDoubleArrayChunk(srcArray, srcOffsetDoubles, lengthDoubles,
+        unsafeObj, cumOffsetBytes);
+  }
+
+  private static void putDoubleArrayChunk(final double[] srcArray, final int srcOffsetDoubles,
+      final int lengthDoubles, final Object unsafeObj, final long cumOffsetBytes) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthDoubles; i++) {
+      unsafe.putLong(unsafeObj, cumOffsetBytes + (((long) i) << DOUBLE_SHIFT),
+          Long.reverseBytes(Double.doubleToRawLongBits(srcArray[srcOffsetDoubles + i])));
+    }
+  }
+
+  static void putNonNativeFloats(final float[] srcArray, int srcOffsetFloats,
+      int lengthFloats, long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
+    checkBounds(srcOffsetFloats, lengthFloats, srcArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkFloats = (int) (chunkBytes >> FLOAT_SHIFT);
+      putFloatArrayChunk(srcArray, srcOffsetFloats, chunkFloats, unsafeObj, cumOffsetBytes);
+      cumOffsetBytes += chunkBytes;
+      srcOffsetFloats += chunkFloats;
+      copyBytes -= chunkBytes;
+      lengthFloats -= chunkFloats;
+    }
+    putFloatArrayChunk(srcArray, srcOffsetFloats, lengthFloats, unsafeObj, cumOffsetBytes);
+  }
+
+  private static void putFloatArrayChunk(final float[] srcArray, final int srcOffsetFloats,
+      final int lengthFloats, final Object unsafeObj, final long cumOffsetBytes) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthFloats; i++) {
+      unsafe.putInt(unsafeObj, cumOffsetBytes + (((long) i) << FLOAT_SHIFT),
+          Integer.reverseBytes(Float.floatToRawIntBits(srcArray[srcOffsetFloats + i])));
+    }
+  }
+
+  static void putNonNativeInts(final int[] srcArray, int srcOffsetInts, int lengthInts,
+      long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
+    checkBounds(srcOffsetInts, lengthInts, srcArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkInts = (int) (chunkBytes >> INT_SHIFT);
+      putIntArrayChunk(srcArray, srcOffsetInts, chunkInts, unsafeObj, cumOffsetBytes);
+      cumOffsetBytes += chunkBytes;
+      srcOffsetInts += chunkInts;
+      copyBytes -= chunkBytes;
+      lengthInts -= chunkInts;
+    }
+    putIntArrayChunk(srcArray, srcOffsetInts, lengthInts, unsafeObj, cumOffsetBytes);
+  }
+
+  private static void putIntArrayChunk(final int[] srcArray, final int srcOffsetInts,
+      final int lengthInts, final Object unsafeObj, final long cumOffsetBytes) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthInts; i++) {
+      unsafe.putInt(unsafeObj, cumOffsetBytes + (((long) i) << INT_SHIFT),
+          Integer.reverseBytes(srcArray[srcOffsetInts + i]));
+    }
+  }
+
+  static void putNonNativeLongs(final long[] srcArray, int srcOffsetLongs, int lengthLongs,
+      long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
+    checkBounds(srcOffsetLongs, lengthLongs, srcArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkLongs = (int) (chunkBytes >> LONG_SHIFT);
+      putLongArrayChunk(srcArray, srcOffsetLongs, chunkLongs, unsafeObj, cumOffsetBytes);
+      cumOffsetBytes += chunkBytes;
+      srcOffsetLongs += chunkLongs;
+      copyBytes -= chunkBytes;
+      lengthLongs -= chunkLongs;
+    }
+    putLongArrayChunk(srcArray, srcOffsetLongs, lengthLongs, unsafeObj, cumOffsetBytes);
+  }
+
+  private static void putLongArrayChunk(final long[] srcArray, final int srcOffsetLongs,
+      final int lengthLongs, final Object unsafeObj, final long cumOffsetBytes) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthLongs; i++) {
+      unsafe.putLong(unsafeObj, cumOffsetBytes + (((long) i) << LONG_SHIFT),
+          Long.reverseBytes(srcArray[srcOffsetLongs + i]));
+    }
+  }
+
+  static void putNonNativeShorts(final short[] srcArray, int srcOffsetShorts,
+      int lengthShorts, long copyBytes, final Object unsafeObj, long cumOffsetBytes) {
+    checkBounds(srcOffsetShorts, lengthShorts, srcArray.length);
+    while (copyBytes > UNSAFE_COPY_THRESHOLD_BYTES) {
+      final long chunkBytes = Math.min(copyBytes, UNSAFE_COPY_THRESHOLD_BYTES);
+      final int chunkShorts = (int) (chunkBytes >> SHORT_SHIFT);
+      putShortArrayChunk(srcArray, srcOffsetShorts, chunkShorts, unsafeObj, cumOffsetBytes);
+      cumOffsetBytes += chunkBytes;
+      srcOffsetShorts += chunkShorts;
+      copyBytes -= chunkBytes;
+      lengthShorts -= chunkShorts;
+    }
+    putShortArrayChunk(srcArray, srcOffsetShorts, lengthShorts, unsafeObj, cumOffsetBytes);
+  }
+
+  private static void putShortArrayChunk(final short[] srcArray, final int srcOffsetShorts,
+      final int lengthShorts, final Object unsafeObj, final long cumOffsetBytes) {
+    // JDK 9 adds native intrinsics for such bulk non-native ordered primitive memory copy.
+    // TODO-JDK9 use them when the library adds support for JDK 9
+    // int-counted loop to avoid safepoint polls
+    for (int i = 0; i < lengthShorts; i++) {
+      unsafe.putShort(unsafeObj, cumOffsetBytes + (((long) i) << SHORT_SHIFT),
+          Short.reverseBytes(srcArray[srcOffsetShorts + i]));
+    }
+  }
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableBufferImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableBufferImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableBufferImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+
+/**
+ * Implementation of {@link WritableBuffer} for direct memory, non-native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class DirectNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
+  private static final int id = BUFFER | NONNATIVE | DIRECT;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final StepBoolean valid; //a reference only
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  DirectNonNativeWritableBufferImpl(
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final StepBoolean valid,
+      final MemoryRequestServer memReqSvr) {
+    super(null, nativeBaseOffset, regionOffset, capacityBytes);
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.valid = valid;
+    this.memReqSvr = memReqSvr;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new DirectWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid, memReqSvr)
+        : new DirectNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid, memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toDuplicate(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | DUPLICATE;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new DirectWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr)
+        : new DirectNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr);
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableMemory(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new DirectWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr)
+        : new DirectNonNativeWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    assertValid();
+    return memReqSvr;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  public boolean isValid() {
+    return valid.get();
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableMemoryImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableMemoryImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectNonNativeWritableMemoryImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/**
+ * Implementation of {@link WritableMemory} for direct memory, non-native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class DirectNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
+  private static final int id = MEMORY | NONNATIVE | DIRECT;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final StepBoolean valid; //a reference only
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  DirectNonNativeWritableMemoryImpl(
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final StepBoolean valid,
+      final MemoryRequestServer memReqSvr) {
+    super(null, nativeBaseOffset, regionOffset, capacityBytes);
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.valid = valid;
+    this.memReqSvr = memReqSvr;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new DirectWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid, memReqSvr)
+        : new DirectNonNativeWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid, memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableBuffer(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new DirectWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr)
+        : new DirectNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    assertValid();
+    return memReqSvr;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  public boolean isValid() {
+    return valid.get();
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableBufferImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableBufferImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableBufferImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+
+/**
+ * Implementation of {@link WritableBuffer} for direct memory, native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class DirectWritableBufferImpl extends NativeWritableBufferImpl {
+  private static final int id = BUFFER | NATIVE | DIRECT;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final StepBoolean valid; //a reference only
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  DirectWritableBufferImpl(
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final StepBoolean valid,
+      final MemoryRequestServer memReqSvr) {
+    super(null, nativeBaseOffset, regionOffset, capacityBytes);
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.valid = valid;
+    this.memReqSvr = memReqSvr;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new DirectWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid, memReqSvr)
+        : new DirectNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid, memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toDuplicate(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | DUPLICATE;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new DirectWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr)
+        : new DirectNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr);
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableMemory(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new DirectWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr)
+        : new DirectNonNativeWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    assertValid();
+    return memReqSvr;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  public boolean isValid() {
+    return valid.get();
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableMemoryImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableMemoryImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/DirectWritableMemoryImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/**
+ * Implementation of {@link WritableMemory} for direct memory, native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class DirectWritableMemoryImpl extends NativeWritableMemoryImpl {
+  private static final int id = MEMORY | NATIVE | DIRECT;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final StepBoolean valid; //a reference only
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  DirectWritableMemoryImpl(
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final StepBoolean valid,
+      final MemoryRequestServer memReqSvr) {
+    super(null, nativeBaseOffset, regionOffset, capacityBytes);
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.valid = valid;
+    this.memReqSvr = memReqSvr;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new DirectWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid, memReqSvr)
+        : new DirectNonNativeWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid, memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableBuffer(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new DirectWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr)
+        : new DirectNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid, memReqSvr);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    assertValid();
+    return memReqSvr;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  public boolean isValid() {
+    return valid.get();
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableBufferImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableBufferImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableBufferImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+
+/**
+ * Implementation of {@link WritableBuffer} for heap-based, non-native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class HeapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
+  private static final int id = BUFFER | NONNATIVE | HEAP;
+  private final Object unsafeObj;
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  HeapNonNativeWritableBufferImpl(
+      final Object unsafeObj,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final MemoryRequestServer memReqSvr) {
+    super(unsafeObj, 0L, regionOffset, capacityBytes);
+    this.unsafeObj = unsafeObj;
+    this.memReqSvr = memReqSvr;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new HeapWritableBufferImpl(
+            unsafeObj, getRegionOffset(offsetBytes), capacityBytes, type, memReqSvr)
+        : new HeapNonNativeWritableBufferImpl(
+            unsafeObj, getRegionOffset(offsetBytes), capacityBytes, type, memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toDuplicate(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | DUPLICATE;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new HeapWritableBufferImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr)
+        : new HeapNonNativeWritableBufferImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr);
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableMemory(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new HeapWritableMemoryImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr)
+        : new HeapNonNativeWritableMemoryImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    return memReqSvr;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  Object getUnsafeObject() {
+    return unsafeObj;
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableMemoryImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableMemoryImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapNonNativeWritableMemoryImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/**
+ * Implementation of {@link WritableMemory} for heap-based, non-native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class HeapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
+  private static final int id = MEMORY | NONNATIVE | HEAP;
+  private final Object unsafeObj;
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  HeapNonNativeWritableMemoryImpl(
+      final Object unsafeObj,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final MemoryRequestServer memReqSvr) {
+    super(unsafeObj, 0L, regionOffset, capacityBytes);
+    this.unsafeObj = unsafeObj;
+    this.memReqSvr = memReqSvr;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new HeapWritableMemoryImpl(
+            unsafeObj, getRegionOffset(offsetBytes), capacityBytes, type, memReqSvr)
+        : new HeapNonNativeWritableMemoryImpl(
+            unsafeObj, getRegionOffset(offsetBytes), capacityBytes, type, memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableBuffer(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new HeapWritableBufferImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr)
+        : new HeapNonNativeWritableBufferImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    return memReqSvr;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  Object getUnsafeObject() {
+    return unsafeObj;
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableBufferImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableBufferImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableBufferImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+
+/**
+ * Implementation of {@link WritableBuffer} for heap-based, native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class HeapWritableBufferImpl extends NativeWritableBufferImpl {
+  private static final int id = BUFFER | NATIVE | HEAP;
+  private final Object unsafeObj;
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  HeapWritableBufferImpl(
+      final Object unsafeObj,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final MemoryRequestServer memReqSvr) {
+    super(unsafeObj, 0L, regionOffset, capacityBytes);
+    this.unsafeObj = unsafeObj;
+    this.memReqSvr = memReqSvr;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new HeapWritableBufferImpl(
+            unsafeObj, getRegionOffset(offsetBytes), capacityBytes, type, memReqSvr)
+        : new HeapNonNativeWritableBufferImpl(
+            unsafeObj, getRegionOffset(offsetBytes), capacityBytes, type, memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toDuplicate(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | DUPLICATE;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new HeapWritableBufferImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr)
+        : new HeapNonNativeWritableBufferImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr);
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableMemory(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new HeapWritableMemoryImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr)
+        : new HeapNonNativeWritableMemoryImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    return memReqSvr;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  Object getUnsafeObject() {
+    return unsafeObj;
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableMemoryImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableMemoryImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/HeapWritableMemoryImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/**
+ * Implementation of {@link WritableMemory} for heap-based, native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class HeapWritableMemoryImpl extends NativeWritableMemoryImpl {
+  private static final int id = MEMORY | NATIVE | HEAP;
+  private final Object unsafeObj;
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+
+  HeapWritableMemoryImpl(
+      final Object unsafeObj,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final MemoryRequestServer memReqSvr) {
+    super(unsafeObj, 0L, regionOffset, capacityBytes);
+    this.unsafeObj = unsafeObj;
+    this.memReqSvr = memReqSvr;
+    this.typeId = (byte) (id | (typeId & 0x7));
+
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new HeapWritableMemoryImpl(
+            unsafeObj, getRegionOffset(offsetBytes), capacityBytes, type, memReqSvr)
+        : new HeapNonNativeWritableMemoryImpl(
+            unsafeObj, getRegionOffset(offsetBytes), capacityBytes, type, memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableBuffer(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new HeapWritableBufferImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr)
+        : new HeapNonNativeWritableBufferImpl(
+            unsafeObj, getRegionOffset(), getCapacity(), type, memReqSvr);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    return memReqSvr;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  Object getUnsafeObject() {
+    return unsafeObj;
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/Ints.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/Ints.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/Ints.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+/** Equivalent of Guava's Ints. */
+public final class Ints {
+
+  private Ints() {}
+
+  /**
+   * Checks if a cast of a long to an int is within the range of an int
+   * @param v the given long
+   * @return returns the cast int, or throws an exception that the long was out-of-range of an int.
+   */
+  public static int checkedCast(final long v) {
+    final int result = (int) v;
+    if (result != v) {
+      throw new IllegalArgumentException("Out of range: " + v);
+    }
+    return result;
+  }
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapHandleImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapHandleImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapHandleImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import org.apache.datasketches.memory.MapHandle;
+import org.apache.datasketches.memory.Memory;
+
+class MapHandleImpl implements MapHandle {
+
+  final AllocateDirectMap dirMap;
+  BaseWritableMemoryImpl wMem;
+
+  MapHandleImpl(final AllocateDirectMap dirMap, final BaseWritableMemoryImpl wMem) {
+    this.dirMap = dirMap;
+    this.wMem = wMem;
+  }
+
+  @Override
+  public Memory get() {
+    return wMem;
+  }
+
+  @Override
+  public void close() {
+    if (dirMap.doClose("MapHandle")) {
+      wMem = null;
+    }
+  }
+
+  @Override
+  public void load() {
+    dirMap.load();
+  }
+
+  @Override
+  public boolean isLoaded() {
+    return dirMap.isLoaded();
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableBufferImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableBufferImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableBufferImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+
+/**
+ * Implementation of {@link WritableBuffer} for map memory, non-native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class MapNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
+  private static final int id = BUFFER | NONNATIVE | MAP;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final StepBoolean valid; //a reference only
+  private final byte typeId;
+
+  MapNonNativeWritableBufferImpl(
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final StepBoolean valid) {
+    super(null, nativeBaseOffset, regionOffset, capacityBytes);
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.valid = valid;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new MapWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid)
+        : new MapNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid);
+  }
+
+  @Override
+  BaseWritableBufferImpl toDuplicate(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | DUPLICATE;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new MapWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid)
+        : new MapNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid);
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableMemory(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new MapWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid)
+        : new MapNonNativeWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    return null;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  public boolean isValid() {
+    return valid.get();
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableMemoryImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableMemoryImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapNonNativeWritableMemoryImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/**
+ * Implementation of {@link WritableMemory} for map memory, non-native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class MapNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
+  private static final int id = MEMORY | NONNATIVE | MAP;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final StepBoolean valid; //a reference only
+  private final byte typeId;
+
+  MapNonNativeWritableMemoryImpl(
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final StepBoolean valid) {
+    super(null, nativeBaseOffset, regionOffset, capacityBytes);
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.valid = valid;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new MapWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid)
+        : new MapNonNativeWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid);
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableBuffer(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new MapWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid)
+        : new MapNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    return null;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  public boolean isValid() {
+    return valid.get();
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableBufferImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableBufferImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableBufferImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+
+/**
+ * Implementation of {@link WritableBuffer} for map memory, native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class MapWritableBufferImpl extends NativeWritableBufferImpl {
+  private static final int id = BUFFER | NATIVE | MAP;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final StepBoolean valid; //a reference only
+  private final byte typeId;
+
+  MapWritableBufferImpl(
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final StepBoolean valid) {
+    super(null, nativeBaseOffset, regionOffset, capacityBytes);
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.valid = valid;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new MapWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid)
+        : new MapNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid);
+  }
+
+  @Override
+  BaseWritableBufferImpl toDuplicate(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | DUPLICATE;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new MapWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid)
+        : new MapNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid);
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableMemory(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new MapWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid)
+        : new MapNonNativeWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    return null;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  public boolean isValid() {
+    return valid.get();
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableMemoryImpl.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableMemoryImpl.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MapWritableMemoryImpl.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/**
+ * Implementation of {@link WritableMemory} for map memory, native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class MapWritableMemoryImpl extends NativeWritableMemoryImpl {
+  private static final int id = MEMORY | NATIVE | MAP;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final StepBoolean valid; //a reference only
+  private final byte typeId;
+
+  MapWritableMemoryImpl(
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final StepBoolean valid) {
+    super(null, nativeBaseOffset, regionOffset, capacityBytes);
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.valid = valid;
+    this.typeId = (byte) (id | (typeId & 0x7));
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableRegion(final long offsetBytes, final long capacityBytes,
+      final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | REGION;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new MapWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid)
+        : new MapNonNativeWritableMemoryImpl(
+            nativeBaseOffset, getRegionOffset(offsetBytes), capacityBytes, type, valid);
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableBuffer(final boolean readOnly, final ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new MapWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid)
+        : new MapNonNativeWritableBufferImpl(
+            nativeBaseOffset, getRegionOffset(), getCapacity(), type, valid);
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    return null;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  public boolean isValid() {
+    return valid.get();
+  }
+
+}

Added: dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MemoryCleaner.java
==============================================================================
--- dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MemoryCleaner.java (added)
+++ dev/datasketches/memory/2.0.0-RC1/apache-datasketches-memory-2.0.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/MemoryCleaner.java Thu Aug 19 22:18:24 2021
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.memory.internal;
+
+import sun.misc.Cleaner;
+
+/**
+ * Extracts a version-dependent reference to the `sun.misc.Cleaner` into
+ * a standalone class. The package name for Cleaner has changed in
+ * later versions. The appropriate class will be loaded by the class loader
+ * depending on the Java version that is used.
+ * For more information, see: https://openjdk.java.net/jeps/238
+ */
+@SuppressWarnings("restriction")
+public class MemoryCleaner {
+    private final Cleaner cleaner;
+
+    /**
+     * Creates a new `sun.misc.Cleaner`.
+     * @param referent the object to be cleaned
+     * @param deallocator - the cleanup code to be run when the cleaner is invoked.
+     * return MemoryCleaner
+     */
+    public MemoryCleaner(final Object referent, final Runnable deallocator) {
+        cleaner = Cleaner.create(referent, deallocator);
+    }
+
+    /**
+     * Runs this cleaner, if it has not been run before.
+     */
+    public void clean() {
+        cleaner.clean();
+    }
+}
+



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org