Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java
 Tue May 21 21:11:49 2024
@@ -0,0 +1,135 @@
+/*
+ * 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.unsafe;
+
+import java.util.logging.Logger;
+
+/**
+ * Provides access to direct (native) memory.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+@SuppressWarnings("restriction")
+final class AllocateDirect {
+  static final Logger LOG = 
Logger.getLogger(AllocateDirect.class.getCanonicalName());
+
+  private final Deallocator deallocator;
+  private final long nativeBaseOffset;
+  private final MemoryCleaner cleaner;
+
+  /**
+   * Base Constructor for allocate native memory.
+   *
+   * <p>Allocates and provides access to capacityBytes directly in native 
(off-heap) memory
+   * leveraging the MemoryImpl interface.
+   * The allocated memory will be 8-byte aligned, but may not be page aligned.
+   * @param capacityBytes the the requested capacity of off-heap memory. 
Cannot be zero.
+   */
+  AllocateDirect(final long capacityBytes) {
+    final boolean pageAligned = NioBits.isPageAligned();
+    final long pageSize = NioBits.pageSize();
+    final long allocationSize = capacityBytes + (pageAligned ? pageSize : 0);
+    NioBits.reserveMemory(allocationSize, capacityBytes);
+
+    final long nativeAddress;
+    try {
+      nativeAddress = unsafe.allocateMemory(allocationSize);
+    } catch (final OutOfMemoryError err) {
+      NioBits.unreserveMemory(allocationSize, capacityBytes);
+      throw new RuntimeException(err);
+    }
+    if (pageAligned && ((nativeAddress % pageSize) != 0)) {
+      //Round up to page boundary
+      nativeBaseOffset = (nativeAddress & ~(pageSize - 1L)) + pageSize;
+    } else {
+      nativeBaseOffset = nativeAddress;
+    }
+    deallocator = new Deallocator(nativeAddress, allocationSize, 
capacityBytes);
+    cleaner = new MemoryCleaner(this, deallocator);
+  }
+
+  boolean doClose() {
+    try {
+      if (deallocator.deallocate(false)) {
+        // This Cleaner.clean() call effectively just removes the Cleaner from 
the internal linked
+        // list of all cleaners. It will delegate to Deallocator.deallocate() 
which will be a no-op
+        // because the valid state is already changed.
+        cleaner.clean();
+        return true;
+      }
+      return false;
+    } finally {
+      BaseStateImpl.reachabilityFence(this);
+    }
+  }
+
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  StepBoolean getValid() {
+    return deallocator.getValid();
+  }
+
+  static final class Deallocator implements Runnable {
+    //This is the only place the actual native address is kept for use by 
unsafe.freeMemory();
+    private final long nativeAddress;
+    private final long allocationSize;
+    private final long capacity;
+    private final StepBoolean valid = new StepBoolean(true); //only place for 
this
+
+    Deallocator(final long nativeAddress, final long allocationSize, final 
long capacity) {
+      BaseStateImpl.currentDirectMemoryAllocations_.incrementAndGet();
+      BaseStateImpl.currentDirectMemoryAllocated_.addAndGet(capacity);
+      this.nativeAddress = nativeAddress;
+      this.allocationSize = allocationSize;
+      this.capacity = capacity;
+      assert (nativeAddress != 0);
+    }
+
+    StepBoolean getValid() {
+      return valid;
+    }
+
+    @Override
+    public void run() {
+      deallocate(true);
+    }
+
+    boolean deallocate(final boolean calledFromCleaner) {
+      if (valid.change()) {
+        if (calledFromCleaner) {
+          // Warn about non-deterministic resource cleanup.
+          LOG.warning("A WritableHandle was not closed manually");
+        }
+        unsafe.freeMemory(nativeAddress);
+        NioBits.unreserveMemory(allocationSize, capacity);
+        BaseStateImpl.currentDirectMemoryAllocations_.decrementAndGet();
+        BaseStateImpl.currentDirectMemoryAllocated_.addAndGet(-capacity);
+        return true;
+      }
+      return false;
+    }
+  }
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirect.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java
 Tue May 21 21:11:49 2024
@@ -0,0 +1,316 @@
+/*
+ * 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.unsafe;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.logging.Logger;
+
+import org.apache.datasketches.memory.Map;
+import org.apache.datasketches.memory.MemoryCloseException;
+
+import sun.nio.ch.FileChannelImpl;
+
+/**
+ * Allocates direct memory used to memory map files for read operations.
+ * (including those &gt; 2GB).
+ *
+ * <p>To understand how it works, reference native code for map0, unmap0:
+ * <a 
href="http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/f940e7a48b72/src/solaris/native/sun/nio/ch/FileChannelImpl.c";>
+ * FileChannelImpl.c</a></p>
+ *
+ * <p>To understand how it works, reference native code for load0(), 
isLoaded0(), and force0():
+ * <a 
href="http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/f940e7a48b72/src/solaris/native/java/nio/MappedByteBuffer.c";>
+ * MappedByteBuffer.c</a></p>
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ * @author Praveenkumar Venkatesan
+ */
+@SuppressWarnings("restriction")
+class AllocateDirectMap implements Map {
+  static final Logger LOG = 
Logger.getLogger(AllocateDirectMap.class.getCanonicalName());
+
+  private static final int MAP_RO = 0;
+  private static final int MAP_RW = 1;
+
+  private static final Method FILE_CHANNEL_IMPL_MAP0_METHOD;
+  static final Method FILE_CHANNEL_IMPL_UNMAP0_METHOD;
+
+  private static final Method MAPPED_BYTE_BUFFER_LOAD0_METHOD;
+  private static final Method MAPPED_BYTE_BUFFER_ISLOADED0_METHOD;
+  static final Method MAPPED_BYTE_BUFFER_FORCE0_METHOD;
+
+  static {
+    try { //The FileChannelImpl methods map0 and unmap0 still exist in 16
+      FILE_CHANNEL_IMPL_MAP0_METHOD = FileChannelImpl.class
+          .getDeclaredMethod("map0", int.class, long.class, long.class); 
//JDK14 add boolean.class
+      FILE_CHANNEL_IMPL_MAP0_METHOD.setAccessible(true);
+
+      FILE_CHANNEL_IMPL_UNMAP0_METHOD = FileChannelImpl.class
+          .getDeclaredMethod("unmap0", long.class, long.class); //OK through 
jDK16
+      FILE_CHANNEL_IMPL_UNMAP0_METHOD.setAccessible(true);
+
+
+      //The MappedByteBuffer methods load0, isLoaded0 and force0 are removed 
in 15
+      MAPPED_BYTE_BUFFER_LOAD0_METHOD = MappedByteBuffer.class
+          .getDeclaredMethod("load0", long.class, long.class); //JDK15 removed
+      MAPPED_BYTE_BUFFER_LOAD0_METHOD.setAccessible(true);
+
+      MAPPED_BYTE_BUFFER_ISLOADED0_METHOD = MappedByteBuffer.class
+          .getDeclaredMethod("isLoaded0", long.class, long.class, int.class); 
//JDK15 removed
+      MAPPED_BYTE_BUFFER_ISLOADED0_METHOD.setAccessible(true);
+
+      MAPPED_BYTE_BUFFER_FORCE0_METHOD = MappedByteBuffer.class
+          .getDeclaredMethod("force0", FileDescriptor.class, long.class, 
long.class); //JDK15 removed
+      MAPPED_BYTE_BUFFER_FORCE0_METHOD.setAccessible(true);
+    } catch (final SecurityException | NoSuchMethodException e) {
+      throw new RuntimeException("Could not reflect static methods: " + e);
+    }
+  }
+
+  private final Deallocator deallocator;
+  private final MemoryCleaner cleaner;
+
+  final long capacityBytes;
+  final RandomAccessFile raf;
+  final long nativeBaseOffset;
+  final boolean resourceReadOnly;
+
+  //called from AllocateDirectWritableMap constructor
+  AllocateDirectMap(final File file, final long fileOffsetBytes, final long 
capacityBytes,
+      final boolean localReadOnly) {
+    this.capacityBytes = capacityBytes;
+    resourceReadOnly = isFileReadOnly(file);
+    final long fileLength = file.length();
+    if ((localReadOnly || resourceReadOnly) && fileOffsetBytes + capacityBytes 
> fileLength) {
+      throw new IllegalArgumentException(
+          "Read-only mode and requested map length is greater than current 
file length: "
+          + "Requested Length = " + (fileOffsetBytes + capacityBytes)
+          + ", Current File Length = " + fileLength);
+    }
+    raf = mapper(file, fileOffsetBytes, capacityBytes, resourceReadOnly);
+    nativeBaseOffset = map(raf.getChannel(), resourceReadOnly, 
fileOffsetBytes, capacityBytes);
+    deallocator = new Deallocator(nativeBaseOffset, capacityBytes, raf);
+    cleaner = new MemoryCleaner(this, deallocator);
+  }
+
+  //Map Interface
+
+  @Override
+  public void load() {
+    madvise();
+    // Performance optimization. Read a byte from each page to bring it into 
memory.
+    final int ps = NioBits.pageSize();
+    final int count = NioBits.pageCount(capacityBytes);
+    long offset = nativeBaseOffset;
+    for (int i = 0; i < count; i++) {
+      unsafe.getByte(offset);
+      offset += ps;
+    }
+  }
+
+  @Override
+  public boolean isLoaded() {
+    try {
+      final int pageCount = NioBits.pageCount(capacityBytes);
+      return (boolean) MAPPED_BYTE_BUFFER_ISLOADED0_METHOD
+          //isLoaded0 is effectively static, so 
ZERO_READ_ONLY_DIRECT_BYTE_BUFFER is not modified
+          .invoke(AccessByteBuffer.ZERO_READ_ONLY_DIRECT_BYTE_BUFFER,
+              nativeBaseOffset,
+              capacityBytes,
+              pageCount);
+    } catch (final  IllegalAccessException | IllegalArgumentException | 
InvocationTargetException e) {
+      throw new RuntimeException(
+              String.format("Encountered %s exception while loading", 
e.getClass()));
+    }
+  }
+  // End Map Interface
+
+  @Override
+  public void close() {
+    doClose("AllocateDirectMap");
+  }
+
+  boolean doClose(final String resource) {
+    try {
+      if (deallocator.deallocate(false)) {
+        // This Cleaner.clean() call effectively just removes the Cleaner from 
the internal linked
+        // list of all cleaners. It will delegate to Deallocator.deallocate() 
which will be a no-op
+        // because the valid state is already changed.
+        cleaner.clean();
+        return true;
+      }
+      return false;
+    } catch (final Exception e) {
+        throw new MemoryCloseException(resource);
+    } finally {
+      BaseStateImpl.reachabilityFence(this);
+    }
+  }
+
+  StepBoolean getValid() {
+    return deallocator.getValid();
+  }
+
+  // Private methods
+  /**
+   * called by load(). Calls the native method load0 in MappedByteBuffer.java, 
implemented
+   * in MappedByteBuffer.c. See reference at top of class. load0 allows 
setting a mapping length
+   * of greater than 2GB.
+   */
+  private void madvise() {
+    try {
+      MAPPED_BYTE_BUFFER_LOAD0_METHOD
+        //load0 is effectively static, so ZERO_READ_ONLY_DIRECT_BYTE_BUFFER is 
not modified
+        .invoke(AccessByteBuffer.ZERO_READ_ONLY_DIRECT_BYTE_BUFFER,
+            nativeBaseOffset,
+            capacityBytes);
+    } catch (final  IllegalAccessException | IllegalArgumentException | 
InvocationTargetException e) {
+      throw new RuntimeException(
+          String.format("Encountered %s exception while loading", 
e.getClass()));
+    }
+  }
+
+  //Does the actual mapping work, resourceReadOnly must already be set
+  private static RandomAccessFile mapper(final File file, final long 
fileOffset,
+      final long capacityBytes, final boolean resourceReadOnly)  {
+
+    final String mode = resourceReadOnly ? "r" : "rw";
+    final RandomAccessFile raf;
+    try {
+      raf = new RandomAccessFile(file, mode);
+      if (fileOffset + capacityBytes > raf.length()) {
+        raf.setLength(fileOffset + capacityBytes);
+      }
+    } catch (final IOException e) {
+      throw new RuntimeException(e);
+    }
+    return raf;
+  }
+
+  /**
+   * Creates a mapping of the FileChannel starting at position and of size 
length to pages
+   * in the OS. This may throw OutOfMemory error if you have exhausted memory.
+   * You can try to force garbage collection and re-attempt.
+   *
+   * <p>map0 is a native method of FileChannelImpl.java implemented in 
FileChannelImpl.c.
+   * See reference at top of class.</p>
+   *
+   * @param fileChannel the FileChannel
+   * @param position the offset in bytes into the FileChannel
+   * @param lengthBytes the length in bytes
+   * @return the native base offset address
+   * @throws RuntimeException Encountered an exception while mapping
+   */
+  private static long map(final FileChannel fileChannel, final boolean 
resourceReadOnly,
+      final long position, final long lengthBytes) {
+    final int pagePosition = (int) (position % unsafe.pageSize());
+    final long mapPosition = position - pagePosition;
+    final long mapSize = lengthBytes + pagePosition;
+    final int mapMode = resourceReadOnly ? MAP_RO : MAP_RW;
+    //final boolean isSync = true; //required as of JDK14, but it is more 
complex
+    try {
+      final long nativeBaseOffset = //JDK14 add isSync
+        (long) FILE_CHANNEL_IMPL_MAP0_METHOD.invoke(fileChannel, mapMode, 
mapPosition, mapSize);
+      return nativeBaseOffset;
+    } catch (final InvocationTargetException e) {
+      throw new RuntimeException("Exception while mapping", 
e.getTargetException());
+    } catch (final IllegalAccessException e) {
+      throw new RuntimeException("Exception while mapping", e);
+    }
+  }
+
+  public static boolean isFileReadOnly(final File file) {
+    return (!file.canWrite());
+  }
+
+  private static final class Deallocator implements Runnable {
+    private final RandomAccessFile myRaf;
+    private final FileChannel myFc;
+    //This is the only place the actual native offset is kept for use by 
unsafe.freeMemory();
+    private final long actualNativeBaseOffset;
+    private final long myCapacity;
+    private final StepBoolean valid = new StepBoolean(true); //only place for 
this
+
+    Deallocator(final long nativeBaseOffset, final long capacityBytes,
+        final RandomAccessFile raf) {
+      BaseStateImpl.currentDirectMemoryMapAllocations_.incrementAndGet();
+      BaseStateImpl.currentDirectMemoryMapAllocated_.addAndGet(capacityBytes);
+      myRaf = raf;
+      assert myRaf != null;
+      myFc = myRaf.getChannel();
+      actualNativeBaseOffset = nativeBaseOffset;
+      assert actualNativeBaseOffset != 0;
+      myCapacity = capacityBytes;
+      assert myCapacity != 0;
+    }
+
+    StepBoolean getValid() {
+      return valid;
+    }
+
+    @Override
+    public void run() {
+      deallocate(true);
+    }
+
+    boolean deallocate(final boolean calledFromCleaner) {
+      if (valid.change()) {
+        if (calledFromCleaner) {
+          // Warn about non-deterministic resource cleanup.
+          LOG.warning("A WritableMapHandleImpl was not closed manually");
+        }
+        try {
+          unmap();
+        }
+        finally {
+          BaseStateImpl.currentDirectMemoryMapAllocations_.decrementAndGet();
+          
BaseStateImpl.currentDirectMemoryMapAllocated_.addAndGet(-myCapacity);
+        }
+        return true;
+      }
+      return false;
+    }
+
+    /**
+     * Removes existing mapping.  <i>unmap0</i> is a native method in 
FileChannelImpl.c. See
+     * reference at top of class.
+     */
+    private void unmap() throws RuntimeException {
+      try {
+        FILE_CHANNEL_IMPL_UNMAP0_METHOD.invoke(myFc, actualNativeBaseOffset, 
myCapacity);
+        myRaf.close();
+      } catch (final IllegalAccessException | IllegalArgumentException | 
InvocationTargetException | IOException e) {
+        throw new RuntimeException(
+            String.format("Encountered %s exception while freeing memory", 
e.getClass()));
+      }
+    }
+  } //End of class Deallocator
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectMap.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java
 Tue May 21 21:11:49 2024
@@ -0,0 +1,63 @@
+/*
+ * 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.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.datasketches.memory.ReadOnlyException;
+import org.apache.datasketches.memory.WritableMap;
+
+/**
+ * Allocates direct memory used to memory map files for write operations
+ * (including those &gt; 2GB).
+ *
+ * @author Lee Rhodes
+ * @author Roman Leventov
+ * @author Praveenkumar Venkatesan
+ */
+//Called from WritableMemoryImpl, implements combo of WritableMemoryImpl with 
WritableMap resource
+final class AllocateDirectWritableMap extends AllocateDirectMap implements 
WritableMap {
+
+  AllocateDirectWritableMap(final File file, final long fileOffsetBytes,
+      final long capacityBytes, final boolean localReadOnly) {
+    super(file, fileOffsetBytes, capacityBytes, localReadOnly);
+  }
+
+  //Added by WritableMap Interface
+
+  @Override
+  public void force() {
+    if (resourceReadOnly) {
+      throw new ReadOnlyException("MemoryImpl Mapped File is Read Only.");
+    }
+    try {
+      MAPPED_BYTE_BUFFER_FORCE0_METHOD
+          //force0 is effectively static, so ZERO_READ_ONLY_DIRECT_BYTE_BUFFER 
is not modified
+          .invoke(AccessByteBuffer.ZERO_READ_ONLY_DIRECT_BYTE_BUFFER,
+              raf.getFD(),
+              nativeBaseOffset,
+              capacityBytes);
+    } catch (final IOException | IllegalAccessException | 
IllegalArgumentException | InvocationTargetException e) {
+      throw new RuntimeException(String.format("Encountered %s exception in 
force. " + e.getClass()));
+    }
+  }
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/AllocateDirectWritableMap.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java
 Tue May 21 21:11:49 2024
@@ -0,0 +1,117 @@
+/*
+ * 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.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+
+/**
+ * Implementation of {@link WritableBuffer} for ByteBuffer, non-native byte 
order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class BBNonNativeWritableBufferImpl extends NonNativeWritableBufferImpl {
+  private static final int id = BUFFER | NONNATIVE | BYTEBUF;
+  private final Object unsafeObj;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until 
we are done with it.
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  BBNonNativeWritableBufferImpl(
+      final Object unsafeObj,
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final ByteBuffer byteBuf,
+      final MemoryRequestServer memReqSvr) {
+    super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
+    this.unsafeObj = unsafeObj;
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.byteBuf = byteBuf;
+    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 BBWritableBufferImpl(
+          unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), 
capacityBytes, type, byteBuf, memReqSvr)
+        : new BBNonNativeWritableBufferImpl(
+          unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), 
capacityBytes, type, byteBuf, memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toDuplicate(final boolean readOnly, final ByteOrder 
byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | DUPLICATE;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new BBWritableBufferImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr)
+        : new BBNonNativeWritableBufferImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr);
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableMemory(final boolean readOnly, final 
ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new BBWritableMemoryImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr)
+        : new BBNonNativeWritableMemoryImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr);
+  }
+
+  @Override
+  public ByteBuffer getByteBuffer() {
+    assertValid();
+    return byteBuf;
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    assertValid();
+    return memReqSvr;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  Object getUnsafeObject() {
+    assertValid();
+    return unsafeObj;
+  }
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableBufferImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java
 Tue May 21 21:11:49 2024
@@ -0,0 +1,107 @@
+/*
+ * 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.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/**
+ * Implementation of {@link WritableMemory} for ByteBuffer, non-native byte 
order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class BBNonNativeWritableMemoryImpl extends NonNativeWritableMemoryImpl {
+  private static final int id = MEMORY | NONNATIVE | BYTEBUF;
+  private final Object unsafeObj;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until 
we are done with it.
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  BBNonNativeWritableMemoryImpl(
+      final Object unsafeObj,
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final ByteBuffer byteBuf,
+      final MemoryRequestServer memReqSvr) {
+    super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
+    this.unsafeObj = unsafeObj;
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.byteBuf = byteBuf;
+    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 BBWritableMemoryImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), 
capacityBytes, type, getByteBuffer(), memReqSvr)
+        : new BBNonNativeWritableMemoryImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), 
capacityBytes, type, getByteBuffer(), memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableBuffer(final boolean readOnly, final 
ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new BBWritableBufferImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr)
+        : new BBNonNativeWritableBufferImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr);
+  }
+
+  @Override
+  public ByteBuffer getByteBuffer() {
+    assertValid();
+    return byteBuf;
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    assertValid();
+    return memReqSvr;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  Object getUnsafeObject() {
+    assertValid();
+    return unsafeObj;
+  }
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBNonNativeWritableMemoryImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java
 Tue May 21 21:11:49 2024
@@ -0,0 +1,117 @@
+/*
+ * 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.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableBuffer;
+
+/**
+ * Implementation of {@link WritableBuffer} for ByteBuffer, native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class BBWritableBufferImpl extends NativeWritableBufferImpl {
+  private static final int id = BUFFER | NATIVE | BYTEBUF;
+  private final Object unsafeObj;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until 
we are done with it.
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  BBWritableBufferImpl(
+      final Object unsafeObj,
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final ByteBuffer byteBuf,
+      final MemoryRequestServer memReqSvr) {
+    super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
+    this.unsafeObj = unsafeObj;
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.byteBuf = byteBuf;
+    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 BBWritableBufferImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), 
capacityBytes, type, byteBuf, memReqSvr)
+        : new BBNonNativeWritableBufferImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), 
capacityBytes, type, byteBuf, memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toDuplicate(final boolean readOnly, final ByteOrder 
byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly) | DUPLICATE;
+    return Util.isNativeByteOrder(byteOrder)
+        ? new BBWritableBufferImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr)
+        : new BBNonNativeWritableBufferImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr);
+  }
+
+  @Override
+  BaseWritableMemoryImpl toWritableMemory(final boolean readOnly, final 
ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new BBWritableMemoryImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr)
+        : new BBNonNativeWritableMemoryImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr);
+  }
+
+  @Override
+  public ByteBuffer getByteBuffer() {
+    assertValid();
+    return byteBuf;
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    assertValid();
+    return memReqSvr;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  Object getUnsafeObject() {
+    assertValid();
+    return unsafeObj;
+  }
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableBufferImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java
 Tue May 21 21:11:49 2024
@@ -0,0 +1,107 @@
+/*
+ * 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.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/**
+ * Implementation of {@link WritableMemory} for ByteBuffer, native byte order.
+ *
+ * @author Roman Leventov
+ * @author Lee Rhodes
+ */
+final class BBWritableMemoryImpl extends NativeWritableMemoryImpl {
+  private static final int id = MEMORY | NATIVE | BYTEBUF;
+  private final Object unsafeObj;
+  private final long nativeBaseOffset; //used to compute cumBaseOffset
+  private final ByteBuffer byteBuf; //holds a reference to a ByteBuffer until 
we are done with it.
+  private final MemoryRequestServer memReqSvr;
+  private final byte typeId;
+
+  BBWritableMemoryImpl(
+      final Object unsafeObj,
+      final long nativeBaseOffset,
+      final long regionOffset,
+      final long capacityBytes,
+      final int typeId,
+      final ByteBuffer byteBuf,
+      final MemoryRequestServer memReqSvr) {
+    super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
+    this.unsafeObj = unsafeObj;
+    this.nativeBaseOffset = nativeBaseOffset;
+    this.byteBuf = byteBuf;
+    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 BBWritableMemoryImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), 
capacityBytes, type, getByteBuffer(), memReqSvr)
+        : new BBNonNativeWritableMemoryImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(offsetBytes), 
capacityBytes, type, getByteBuffer(), memReqSvr);
+  }
+
+  @Override
+  BaseWritableBufferImpl toWritableBuffer(final boolean readOnly, final 
ByteOrder byteOrder) {
+    final int type = setReadOnlyType(typeId, readOnly);
+    return Util.isNativeByteOrder(byteOrder)
+        ? new BBWritableBufferImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr)
+        : new BBNonNativeWritableBufferImpl(
+            unsafeObj, nativeBaseOffset, getRegionOffset(), getCapacity(), 
type, byteBuf, memReqSvr);
+  }
+
+  @Override
+  public ByteBuffer getByteBuffer() {
+    assertValid();
+    return byteBuf;
+  }
+
+  @Override
+  public MemoryRequestServer getMemoryRequestServer() {
+    assertValid();
+    return memReqSvr;
+  }
+
+  @Override
+  long getNativeBaseOffset() {
+    return nativeBaseOffset;
+  }
+
+  @Override
+  int getTypeId() {
+    return typeId & 0xff;
+  }
+
+  @Override
+  Object getUnsafeObject() {
+    assertValid();
+    return unsafeObj;
+  }
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BBWritableMemoryImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseBufferImpl.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseBufferImpl.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseBufferImpl.java
 Tue May 21 21:11:49 2024
@@ -0,0 +1,218 @@
+/*
+ * 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.BaseBuffer;
+import org.apache.datasketches.memory.ReadOnlyException;
+
+/**
+ * A new positional API. This is different from and simpler than Java 
BufferImpl positional approach.
+ * <ul><li>All based on longs instead of ints.</li>
+ * <li>Eliminated "mark". Rarely used and confusing with its silent side 
effects.</li>
+ * <li>The invariants are {@code 0 <= start <= position <= end <= 
capacity}.</li>
+ * <li>It always starts up as (0, 0, capacity, capacity).</li>
+ * <li>You set (start, position, end) in one call with
+ * {@link #setStartPositionEnd(long, long, long)}</li>
+ * <li>Position can be set directly or indirectly when using the positional 
get/put methods.
+ * <li>Added incrementPosition(long), which is much easier when you know the 
increment.</li>
+ * <li>This approach eliminated a number of methods and checks, and has no 
unseen side effects,
+ * e.g., mark being invalidated.</li>
+ * <li>Clearer method naming (IMHO).</li>
+ * </ul>
+ *
+ * @author Lee Rhodes
+ */
+public abstract class BaseBufferImpl extends BaseStateImpl implements 
BaseBuffer {
+  private long capacity;
+  private long start = 0;
+  private long pos = 0;
+  private long end;
+
+  //Pass-through ctor
+  BaseBufferImpl(final Object unsafeObj, final long nativeBaseOffset,
+      final long regionOffset, final long capacityBytes) {
+    super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
+    capacity = end = capacityBytes;
+  }
+
+  @Override
+  public final BaseBufferImpl incrementPosition(final long increment) {
+    incrementAndAssertPositionForRead(pos, increment);
+    return this;
+  }
+
+  @Override
+  public final BaseBufferImpl incrementAndCheckPosition(final long increment) {
+    incrementAndCheckPositionForRead(pos, increment);
+    return this;
+  }
+
+  @Override
+  public final long getEnd() {
+    return end;
+  }
+
+  @Override
+  public final long getPosition() {
+    return pos;
+  }
+
+  @Override
+  public final long getStart() {
+    return start;
+  }
+
+  @Override
+  public final long getRemaining()  {
+    return end - pos;
+  }
+
+  @Override
+  public final boolean hasRemaining() {
+    return (end - pos) > 0;
+  }
+
+  @Override
+  public final BaseBufferImpl resetPosition() {
+    pos = start;
+    return this;
+  }
+
+  @Override
+  public final BaseBufferImpl setPosition(final long position) {
+    assertInvariants(start, position, end, capacity);
+    pos = position;
+    return this;
+  }
+
+  @Override
+  public final BaseBufferImpl setAndCheckPosition(final long position) {
+    checkInvariants(start, position, end, capacity);
+    pos = position;
+    return this;
+  }
+
+  @Override
+  public final BaseBufferImpl setStartPositionEnd(final long start, final long 
position,
+      final long end) {
+    assertInvariants(start, position, end, capacity);
+    this.start = start;
+    this.end = end;
+    pos = position;
+    return this;
+  }
+
+  @Override
+  public final BaseBufferImpl setAndCheckStartPositionEnd(final long start, 
final long position,
+      final long end) {
+    checkInvariants(start, position, end, capacity);
+    this.start = start;
+    this.end = end;
+    pos = position;
+    return this;
+  }
+
+  //RESTRICTED
+  //Position checks are only used for Buffers
+  //asserts are used for primitives, not used at runtime
+  final void incrementAndAssertPositionForRead(final long position, final long 
increment) {
+    assertValid();
+    final long newPos = position + increment;
+    assertInvariants(start, newPos, end, capacity);
+    pos = newPos;
+  }
+
+  final void incrementAndAssertPositionForWrite(final long position, final 
long increment) {
+    assertValid();
+    assert !isReadOnly() : "BufferImpl is read-only.";
+    final long newPos = position + increment;
+    assertInvariants(start, newPos, end, capacity);
+    pos = newPos;
+  }
+
+  //checks are used for arrays and apply at runtime
+  final void incrementAndCheckPositionForRead(final long position, final long 
increment) {
+    checkValid();
+    final long newPos = position + increment;
+    checkInvariants(start, newPos, end, capacity);
+    pos = newPos;
+  }
+
+  final void incrementAndCheckPositionForWrite(final long position, final long 
increment) {
+    checkValidForWrite();
+    final long newPos = position + increment;
+    checkInvariants(start, newPos, end, capacity);
+    pos = newPos;
+  }
+
+  final void checkValidForWrite() {
+    checkValid();
+    if (isReadOnly()) {
+      throw new ReadOnlyException("BufferImpl is read-only.");
+    }
+  }
+
+  /**
+   * The invariants equation is: {@code 0 <= start <= position <= end <= 
capacity}.
+   * If this equation is violated and assertions are enabled,
+   * an <i>AssertionError</i> will be thrown.
+   * @param start the lowest start position
+   * @param pos the current position
+   * @param end the highest position
+   * @param cap the capacity of the backing buffer.
+   */
+  static final void assertInvariants(final long start, final long pos, final 
long end,
+      final long cap) {
+    assert (start | pos | end | cap | (pos - start) | (end - pos) | (cap - 
end) ) >= 0L
+        : "Violation of Invariants: "
+        + "start: " + start
+        + " <= pos: " + pos
+        + " <= end: " + end
+        + " <= cap: " + cap
+        + "; (pos - start): " + (pos - start)
+        + ", (end - pos): " + (end - pos)
+        + ", (cap - end): " + (cap - end);
+  }
+
+  /**
+   * The invariants equation is: {@code 0 <= start <= position <= end <= 
capacity}.
+   * If this equation is violated an <i>IllegalArgumentException</i> will be 
thrown.
+   * @param start the lowest start position
+   * @param pos the current position
+   * @param end the highest position
+   * @param cap the capacity of the backing buffer.
+   */
+  static final void checkInvariants(final long start, final long pos, final 
long end,
+        final long cap) {
+    if ((start | pos | end | cap | (pos - start) | (end - pos) | (cap - end) ) 
< 0L) {
+      throw new IllegalArgumentException(
+          "Violation of Invariants: "
+              + "start: " + start
+              + " <= pos: " + pos
+              + " <= end: " + end
+              + " <= cap: " + cap
+              + "; (pos - start): " + (pos - start)
+              + ", (end - pos): " + (end - pos)
+              + ", (cap - end): " + (cap - end)
+      );
+    }
+  }
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseBufferImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseStateImpl.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseStateImpl.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseStateImpl.java
 Tue May 21 21:11:49 2024
@@ -0,0 +1,495 @@
+/*
+ * 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.LS;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.assertBounds;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.checkBounds;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.datasketches.memory.BaseState;
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.ReadOnlyException;
+
+/**
+ * Keeps key configuration state for MemoryImpl and BufferImpl plus some 
common static variables
+ * and check methods.
+ *
+ * @author Lee Rhodes
+ */
+@SuppressWarnings("restriction")
+public abstract class BaseStateImpl implements BaseState {
+
+  //Monitoring
+  static final AtomicLong currentDirectMemoryAllocations_ = new AtomicLong();
+  static final AtomicLong currentDirectMemoryAllocated_ = new AtomicLong();
+  static final AtomicLong currentDirectMemoryMapAllocations_ = new 
AtomicLong();
+  static final AtomicLong currentDirectMemoryMapAllocated_ = new AtomicLong();
+
+  //class type IDs. Do not change the bit orders
+  //The first 3 bits are set dynamically
+  // 0000 0XXX
+  static final int READONLY = 1;
+  static final int REGION = 2;
+  static final int DUPLICATE = 4;
+
+  //The following 4 bits are set by the 16 leaf nodes
+  // 000X X000
+  static final int HEAP = 0;
+  static final int DIRECT = 1 << 3;
+  static final int MAP = 2 << 3;
+  static final int BYTEBUF = 3 << 3;
+
+  // 00X0 0000
+  static final int NATIVE = 0;
+  static final int NONNATIVE = 1 << 5;
+
+  // 0X00 0000
+  static final int MEMORY = 0;
+  static final int BUFFER = 1 << 6;
+
+  private final long capacityBytes_;
+
+  /**
+   * This becomes the base offset used by all Unsafe calls. It is cumulative 
in that in includes
+   * all offsets from regions, user-defined offsets when creating MemoryImpl, 
and the array object
+   * header offset when creating MemoryImpl from primitive arrays.
+   */
+  private final long cumBaseOffset_;
+
+  /**
+   *
+   * @param unsafeObj The primitive backing array. It may be null. Used by 
Unsafe calls.
+   * @param nativeBaseOffset The off-heap memory address including 
DirectByteBuffer split offsets.
+   * @param regionOffset This offset defines address zero of this object 
(usually a region)
+   * relative to address zero of the backing resource. It is used to compute 
cumBaseOffset.
+   * This will be loaded from heap ByteBuffers, which have a similar field 
used for slices.
+   * It is used by region() and writableRegion().
+   * This offset does not include the size of an object array header, if there 
is one.
+   * @param capacityBytes the capacity of this object. Used by all methods 
when checking bounds.
+   */
+  BaseStateImpl(final Object unsafeObj, final long nativeBaseOffset, final 
long regionOffset,
+      final long capacityBytes) {
+    capacityBytes_ = capacityBytes;
+    cumBaseOffset_ = regionOffset + (unsafeObj == null
+        ? nativeBaseOffset
+        : UnsafeUtil.getArrayBaseOffset(unsafeObj.getClass()));
+  }
+
+  //Byte Order Related
+
+  @Override
+  public final ByteOrder getTypeByteOrder() {
+    return isNonNativeType() ? Util.NON_NATIVE_BYTE_ORDER : 
ByteOrder.nativeOrder();
+  }
+
+  /**
+   * Returns true if the given byteOrder is the same as the native byte order.
+   * @param byteOrder the given byte order
+   * @return true if the given byteOrder is the same as the native byte order.
+   */
+  public static boolean isNativeByteOrder(final ByteOrder byteOrder) {
+    if (byteOrder == null) {
+      throw new IllegalArgumentException("ByteOrder parameter cannot be 
null.");
+    }
+    return ByteOrder.nativeOrder() == byteOrder;
+  }
+
+  @Override
+  public final boolean isByteOrderCompatible(final ByteOrder byteOrder) {
+    final ByteOrder typeBO = getTypeByteOrder();
+    return typeBO == ByteOrder.nativeOrder() && typeBO == byteOrder;
+  }
+
+  @Override
+  public final boolean equals(final Object that) {
+    if (this == that) { return true; }
+    return that instanceof BaseStateImpl
+      ? CompareAndCopy.equals(this, (BaseStateImpl) that)
+      : false;
+  }
+
+  @Override
+  public final boolean equalTo(final long thisOffsetBytes, final Object that,
+      final long thatOffsetBytes, final long lengthBytes) {
+    return that instanceof BaseStateImpl
+      ? CompareAndCopy.equals(this, thisOffsetBytes, (BaseStateImpl) that, 
thatOffsetBytes, lengthBytes)
+      : false;
+  }
+
+  //Overridden by ByteBuffer Leafs
+  @Override
+  public ByteBuffer getByteBuffer() {
+    return null;
+  }
+
+  @Override
+  public final long getCapacity() {
+    assertValid();
+    return capacityBytes_;
+  }
+
+  @Override
+  public final long getCumulativeOffset() {
+    assertValid();
+    return cumBaseOffset_;
+  }
+
+  @Override
+  public final long getCumulativeOffset(final long offsetBytes) {
+    assertValid();
+    return cumBaseOffset_ + offsetBytes;
+  }
+
+  //Documented in WritableMemory and WritableBuffer interfaces.
+  //Implemented in the Leaf nodes; Required here by toHex(...).
+  abstract MemoryRequestServer getMemoryRequestServer();
+
+  //Overridden by ByteBuffer, Direct and Map leafs
+  long getNativeBaseOffset() {
+    return 0;
+  }
+
+  @Override
+  public final long getRegionOffset() {
+    final Object unsafeObj = getUnsafeObject();
+    return unsafeObj == null
+        ? cumBaseOffset_ - getNativeBaseOffset()
+        : cumBaseOffset_ - UnsafeUtil.getArrayBaseOffset(unsafeObj.getClass());
+  }
+
+  @Override
+  public final long getRegionOffset(final long offsetBytes) {
+    return getRegionOffset() + offsetBytes;
+  }
+
+  //Overridden by all leafs
+  abstract int getTypeId();
+
+  //Overridden by Heap and ByteBuffer Leafs. Made public as getArray() in 
WritableMemoryImpl and
+  // WritableBufferImpl
+  Object getUnsafeObject() {
+    return null;
+  }
+
+  @Override
+  public final boolean hasArray() {
+    assertValid();
+    return getUnsafeObject() != null;
+  }
+
+  @Override
+  public final int hashCode() {
+    return (int) xxHash64(0, capacityBytes_, 0); //xxHash64() calls 
checkValid()
+  }
+
+  @Override
+  public final long xxHash64(final long offsetBytes, final long lengthBytes, 
final long seed) {
+    checkValid();
+    return XxHash64.hash(getUnsafeObject(), cumBaseOffset_ + offsetBytes, 
lengthBytes, seed);
+  }
+
+  @Override
+  public final long xxHash64(final long in, final long seed) {
+    return XxHash64.hash(in, seed);
+  }
+
+  @Override
+  public final boolean hasByteBuffer() {
+    assertValid();
+    return getByteBuffer() != null;
+  }
+
+  @Override
+  public final boolean isDirect() {
+    return getUnsafeObject() == null;
+  }
+
+  @Override
+  public final boolean isReadOnly() {
+    assertValid();
+    return isReadOnlyType();
+  }
+
+  @Override
+  public final boolean isSameResource(final Object that) {
+    checkValid();
+    if (that == null) { return false; }
+    final BaseStateImpl that1 = (BaseStateImpl) that;
+    that1.checkValid();
+    if (this == that1) { return true; }
+
+    return cumBaseOffset_ == that1.cumBaseOffset_
+            && capacityBytes_ == that1.capacityBytes_
+            && getUnsafeObject() == that1.getUnsafeObject()
+            && getByteBuffer() == that1.getByteBuffer();
+  }
+
+  //Overridden by Direct and Map leafs
+  @Override
+  public boolean isValid() {
+    return true;
+  }
+
+  //ASSERTS AND CHECKS
+  final void assertValid() {
+    assert isValid() : "MemoryImpl not valid.";
+  }
+
+  void checkValid() {
+    if (!isValid()) {
+      throw new IllegalStateException("MemoryImpl not valid.");
+    }
+  }
+
+  final void assertValidAndBoundsForRead(final long offsetBytes, final long 
lengthBytes) {
+    assertValid();
+    // capacityBytes_ is intentionally read directly instead of calling 
getCapacity()
+    // because the later can make JVM to not inline the assert code path (and 
entirely remove it)
+    // even though it does nothing in production code path.
+    assertBounds(offsetBytes, lengthBytes, capacityBytes_);
+  }
+
+  final void assertValidAndBoundsForWrite(final long offsetBytes, final long 
lengthBytes) {
+    assertValid();
+    // capacityBytes_ is intentionally read directly instead of calling 
getCapacity()
+    // because the later can make JVM to not inline the assert code path (and 
entirely remove it)
+    // even though it does nothing in production code path.
+    assertBounds(offsetBytes, lengthBytes, capacityBytes_);
+    assert !isReadOnly() : "MemoryImpl is read-only.";
+  }
+
+  @Override
+  public final void checkValidAndBounds(final long offsetBytes, final long 
lengthBytes) {
+    checkValid();
+    //read capacityBytes_ directly to eliminate extra checkValid() call
+    checkBounds(offsetBytes, lengthBytes, capacityBytes_);
+  }
+
+  final void checkValidAndBoundsForWrite(final long offsetBytes, final long 
lengthBytes) {
+    checkValid();
+    //read capacityBytes_ directly to eliminate extra checkValid() call
+    checkBounds(offsetBytes, lengthBytes, capacityBytes_);
+    if (isReadOnly()) {
+      throw new ReadOnlyException("MemoryImpl is read-only.");
+    }
+  }
+
+  //TYPE ID Management
+  final boolean isReadOnlyType() {
+    return (getTypeId() & READONLY) > 0;
+  }
+
+  final static byte setReadOnlyType(final byte type, final boolean readOnly) {
+    return (byte)((type & ~1) | (readOnly ? READONLY : 0));
+  }
+
+  final boolean isRegionType() {
+    return (getTypeId() & REGION) > 0;
+  }
+
+  final boolean isDuplicateType() {
+    return (getTypeId() & DUPLICATE) > 0;
+  }
+
+  //The following are set by the leaf nodes
+  final boolean isBufferType() {
+    return (getTypeId() & BUFFER) > 0;
+  }
+
+  final boolean isNonNativeType() {
+    return (getTypeId() & NONNATIVE) > 0;
+  }
+
+  final boolean isHeapType() {
+    return (getTypeId() >>> 3 & 3) == 0;
+  }
+
+  final boolean isDirectType() {
+    return (getTypeId() >>> 3 & 3) == 1;
+  }
+
+  final boolean isMapType() {
+    return (getTypeId() >>> 3 & 3) == 2;
+  }
+
+  final boolean isBBType() {
+    return (getTypeId() >>> 3 & 3) == 3;
+  }
+
+  //TO STRING
+  /**
+   * Decodes the resource type. This is primarily for debugging.
+   * @param typeId the given typeId
+   * @return a human readable string.
+   */
+  public static final String typeDecode(final int typeId) {
+    final StringBuilder sb = new StringBuilder();
+    final int group1 = typeId & 0x7;
+    switch (group1) {
+      case 1 : sb.append("ReadOnly, "); break;
+      case 2 : sb.append("Region, "); break;
+      case 3 : sb.append("ReadOnly Region, "); break;
+      case 4 : sb.append("Duplicate, "); break;
+      case 5 : sb.append("ReadOnly Duplicate, "); break;
+      case 6 : sb.append("Region Duplicate, "); break;
+      case 7 : sb.append("ReadOnly Region Duplicate, "); break;
+      default: break;
+    }
+    final int group2 = (typeId >>> 3) & 0x3;
+    switch (group2) {
+      case 0 : sb.append("Heap, "); break;
+      case 1 : sb.append("Direct, "); break;
+      case 2 : sb.append("Map, "); break;
+      case 3 : sb.append("ByteBuffer, "); break;
+      default: break;
+    }
+    final int group3 = (typeId >>> 5) & 0x1;
+    switch (group3) {
+      case 0 : sb.append("Native, "); break;
+      case 1 : sb.append("NonNative, "); break;
+      default: break;
+    }
+    final int group4 = (typeId >>> 6) & 0x1;
+    switch (group4) {
+      case 0 : sb.append("Memory"); break;
+      case 1 : sb.append("Buffer"); break;
+      default: break;
+    }
+    return sb.toString();
+  }
+
+  @Override
+  public final String toHexString(final String header, final long offsetBytes,
+      final int lengthBytes) {
+    checkValid();
+    final String klass = this.getClass().getSimpleName();
+    final String s1 = String.format("(..., %d, %d)", offsetBytes, lengthBytes);
+    final long hcode = hashCode() & 0XFFFFFFFFL;
+    final String call = ".toHexString" + s1 + ", hashCode: " + hcode;
+    final StringBuilder sb = new StringBuilder();
+    sb.append("### ").append(klass).append(" SUMMARY ###").append(LS);
+    sb.append("Header Comment      : ").append(header).append(LS);
+    sb.append("Call Parameters     : ").append(call);
+    return toHex(this, sb.toString(), offsetBytes, lengthBytes);
+  }
+
+  /**
+   * Returns a formatted hex string of an area of this object.
+   * Used primarily for testing.
+   * @param state the BaseStateImpl
+   * @param preamble a descriptive header
+   * @param offsetBytes offset bytes relative to the MemoryImpl start
+   * @param lengthBytes number of bytes to convert to a hex string
+   * @return a formatted hex string in a human readable array
+   */
+  static final String toHex(final BaseStateImpl state, final String preamble, 
final long offsetBytes,
+      final int lengthBytes) {
+    final long capacity = state.getCapacity();
+    UnsafeUtil.checkBounds(offsetBytes, lengthBytes, capacity);
+    final StringBuilder sb = new StringBuilder();
+    final Object uObj = state.getUnsafeObject();
+    final String uObjStr;
+    final long uObjHeader;
+    if (uObj == null) {
+      uObjStr = "null";
+      uObjHeader = 0;
+    } else {
+      uObjStr =  uObj.getClass().getSimpleName() + ", " + (uObj.hashCode() & 
0XFFFFFFFFL);
+      uObjHeader = UnsafeUtil.getArrayBaseOffset(uObj.getClass());
+    }
+    final ByteBuffer bb = state.getByteBuffer();
+    final String bbStr = bb == null ? "null"
+            : bb.getClass().getSimpleName() + ", " + (bb.hashCode() & 
0XFFFFFFFFL);
+    final MemoryRequestServer memReqSvr = state.getMemoryRequestServer();
+    final String memReqStr = memReqSvr != null
+        ? memReqSvr.getClass().getSimpleName() + ", " + (memReqSvr.hashCode() 
& 0XFFFFFFFFL)
+        : "null";
+    final long cumBaseOffset = state.getCumulativeOffset();
+    sb.append(preamble).append(LS);
+    sb.append("UnsafeObj, hashCode : ").append(uObjStr).append(LS);
+    sb.append("UnsafeObjHeader     : ").append(uObjHeader).append(LS);
+    sb.append("ByteBuf, hashCode   : ").append(bbStr).append(LS);
+    sb.append("RegionOffset        : 
").append(state.getRegionOffset()).append(LS);
+    sb.append("Capacity            : ").append(capacity).append(LS);
+    sb.append("CumBaseOffset       : ").append(cumBaseOffset).append(LS);
+    sb.append("MemReq, hashCode    : ").append(memReqStr).append(LS);
+    sb.append("Valid               : ").append(state.isValid()).append(LS);
+    sb.append("Read Only           : ").append(state.isReadOnly()).append(LS);
+    sb.append("Type Byte Order     : 
").append(state.getTypeByteOrder().toString()).append(LS);
+    sb.append("Native Byte Order   : 
").append(ByteOrder.nativeOrder().toString()).append(LS);
+    sb.append("JDK Runtime Version : ").append(UnsafeUtil.JDK).append(LS);
+    //Data detail
+    sb.append("Data, littleEndian  :  0  1  2  3  4  5  6  7");
+
+    for (long i = 0; i < lengthBytes; i++) {
+      final int b = unsafe.getByte(uObj, cumBaseOffset + offsetBytes + i) & 
0XFF;
+      if (i % 8 == 0) { //row header
+        sb.append(String.format("%n%20s: ", offsetBytes + i));
+      }
+      sb.append(String.format("%02x ", b));
+    }
+    sb.append(LS);
+
+    return sb.toString();
+  }
+
+  //MONITORING
+
+  /**
+   * Gets the current number of active direct memory allocations.
+   * @return the current number of active direct memory allocations.
+   */
+  public static final long getCurrentDirectMemoryAllocations() {
+    return BaseStateImpl.currentDirectMemoryAllocations_.get();
+  }
+
+  /**
+   * Gets the current size of active direct memory allocated.
+   * @return the current size of active direct memory allocated.
+   */
+  public static final long getCurrentDirectMemoryAllocated() {
+    return BaseStateImpl.currentDirectMemoryAllocated_.get();
+  }
+
+  /**
+   * Gets the current number of active direct memory map allocations.
+   * @return the current number of active direct memory map allocations.
+   */
+  public static final long getCurrentDirectMemoryMapAllocations() {
+    return BaseStateImpl.currentDirectMemoryMapAllocations_.get();
+  }
+
+  /**
+   * Gets the current size of active direct memory map allocated.
+   * @return the current size of active direct memory map allocated.
+   */
+  public static final long getCurrentDirectMemoryMapAllocated() {
+    return BaseStateImpl.currentDirectMemoryMapAllocated_.get();
+  }
+
+  //REACHABILITY FENCE
+  static void reachabilityFence(final Object obj) { }
+
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseStateImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
==============================================================================
--- 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
 (added)
+++ 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
 Tue May 21 21:11:49 2024
@@ -0,0 +1,431 @@
+/*
+ * 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.ARRAY_BOOLEAN_BASE_OFFSET;
+import static 
org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_BOOLEAN_INDEX_SCALE;
+import static 
org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_BYTE_BASE_OFFSET;
+import static 
org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_BYTE_INDEX_SCALE;
+import static 
org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_CHAR_INDEX_SCALE;
+import static 
org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_INT_INDEX_SCALE;
+import static 
org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_LONG_INDEX_SCALE;
+import static 
org.apache.datasketches.memory.internal.UnsafeUtil.ARRAY_SHORT_INDEX_SCALE;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.checkBounds;
+import static org.apache.datasketches.memory.internal.UnsafeUtil.unsafe;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Objects;
+
+import org.apache.datasketches.memory.Buffer;
+import org.apache.datasketches.memory.Memory;
+import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.ReadOnlyException;
+import org.apache.datasketches.memory.WritableBuffer;
+import org.apache.datasketches.memory.WritableMemory;
+
+/*
+ * Developer notes: The heavier methods, such as put/get arrays, duplicate, 
region, clear, fill,
+ * compareTo, etc., use hard checks (check*() and incrementAndCheck*() 
methods), which execute at
+ * runtime and throw exceptions if violated. The cost of the runtime checks 
are minor compared to
+ * the rest of the work these methods are doing.
+ *
+ * <p>The light weight methods, such as put/get primitives, use asserts 
(assert*() and
+ * incrementAndAssert*() methods), which only execute when asserts are enabled 
and JIT will remove
+ * them entirely from production runtime code. The offset versions of the 
light weight methods will
+ * simplify to a single unsafe call, which is further simplified by JIT to an 
intrinsic that is
+ * often a single CPU instruction.
+ */
+
+/**
+ * Common base of native-ordered and non-native-ordered {@link WritableBuffer} 
implementations.
+ * Contains methods which are agnostic to the byte order.
+ */
+@SuppressWarnings("restriction")
+public abstract class BaseWritableBufferImpl extends BaseBufferImpl implements 
WritableBuffer {
+
+  //Pass-through ctor
+  BaseWritableBufferImpl(final Object unsafeObj, final long nativeBaseOffset,
+      final long regionOffset, final long capacityBytes) {
+    super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes);
+  }
+
+  /**
+   * The static constructor that chooses the correct ByteBuffer leaf node 
based on the byte order.
+   * @param byteBuf the ByteBuffer being wrapped
+   * @param localReadOnly the requested read-only state
+   * @param byteOrder the requested byteOrder
+   * @param memReqSvr the requested MemoryRequestServer, which may be null.
+   * @return this class constructed via the leaf node.
+   */
+  public static BaseWritableBufferImpl wrapByteBuffer(
+      final ByteBuffer byteBuf, final boolean localReadOnly, final ByteOrder 
byteOrder,
+      final MemoryRequestServer memReqSvr) {
+    final AccessByteBuffer abb = new AccessByteBuffer(byteBuf);
+    final int typeId = (abb.resourceReadOnly || localReadOnly) ? READONLY : 0;
+    final BaseWritableBufferImpl bwbi = Util.isNativeByteOrder(byteOrder)
+        ? new BBWritableBufferImpl(abb.unsafeObj, abb.nativeBaseOffset,
+            abb.regionOffset, abb.capacityBytes, typeId, byteBuf, memReqSvr)
+        : new BBNonNativeWritableBufferImpl(abb.unsafeObj, 
abb.nativeBaseOffset,
+            abb.regionOffset, abb.capacityBytes,  typeId, byteBuf, memReqSvr);
+    bwbi.setStartPositionEnd(0, byteBuf.position(), byteBuf.limit());
+    return bwbi;
+  }
+
+  //REGIONS
+  @Override
+  public Buffer region() {
+    return writableRegionImpl(getPosition(), getEnd() - getPosition(), true, 
getTypeByteOrder());
+  }
+
+  @Override
+  public Buffer region(final long offsetBytes, final long capacityBytes, final 
ByteOrder byteOrder) {
+    final WritableBuffer buf = writableRegionImpl(offsetBytes, capacityBytes, 
true, byteOrder);
+    buf.setAndCheckStartPositionEnd(0, 0, capacityBytes);
+    return buf;
+  }
+
+  @Override
+  public WritableBuffer writableRegion() {
+    return writableRegionImpl(getPosition(), getEnd() - getPosition(), false, 
getTypeByteOrder());
+  }
+
+  @Override
+  public WritableBuffer writableRegion(final long offsetBytes, final long 
capacityBytes, final ByteOrder byteOrder) {
+    final WritableBuffer wbuf = writableRegionImpl(offsetBytes, capacityBytes, 
false, byteOrder);
+    wbuf.setAndCheckStartPositionEnd(0, 0, capacityBytes);
+    return wbuf;
+  }
+
+  WritableBuffer writableRegionImpl(final long offsetBytes, final long 
capacityBytes,
+      final boolean localReadOnly, final ByteOrder byteOrder) {
+    if (isReadOnly() && !localReadOnly) {
+      throw new ReadOnlyException("Writable region of a read-only Buffer is 
not allowed.");
+    }
+    checkValidAndBounds(offsetBytes, capacityBytes);
+    final boolean readOnly = isReadOnly() || localReadOnly;
+    final WritableBuffer wbuf = toWritableRegion(offsetBytes, capacityBytes, 
readOnly, byteOrder);
+    wbuf.setStartPositionEnd(0, 0, capacityBytes);
+    return wbuf;
+  }
+
+  abstract BaseWritableBufferImpl toWritableRegion(
+      long offsetBytes, long capcityBytes, boolean readOnly, ByteOrder 
byteOrder);
+
+  //DUPLICATES
+  @Override
+  public Buffer duplicate() {
+    return writableDuplicateImpl(true, getTypeByteOrder());
+  }
+
+  @Override
+  public Buffer duplicate(final ByteOrder byteOrder) {
+    return writableDuplicateImpl(true, byteOrder);
+  }
+
+  @Override
+  public WritableBuffer writableDuplicate() {
+    return writableDuplicateImpl(false, getTypeByteOrder());
+  }
+
+  @Override
+  public WritableBuffer writableDuplicate(final ByteOrder byteOrder) {
+    return writableDuplicateImpl(false, byteOrder);
+  }
+
+  WritableBuffer writableDuplicateImpl(final boolean localReadOnly, final 
ByteOrder byteOrder) {
+    if (isReadOnly() && !localReadOnly) {
+      throw new ReadOnlyException("Writable duplicate of a read-only Buffer is 
not allowed.");
+    }
+    final boolean readOnly = isReadOnly() || localReadOnly;
+    final WritableBuffer wbuf = toDuplicate(readOnly, byteOrder);
+    wbuf.setStartPositionEnd(getStart(), getPosition(), getEnd());
+    return wbuf;
+  }
+
+  abstract BaseWritableBufferImpl toDuplicate(boolean readOnly, ByteOrder 
byteOrder);
+
+  //AS MEMORY
+  @Override
+  public Memory asMemory(final ByteOrder byteOrder) {
+    return asWritableMemory(true, byteOrder);
+  }
+
+  @Override
+  public WritableMemory asWritableMemory(final ByteOrder byteOrder) {
+    return asWritableMemory(false, byteOrder);
+  }
+
+  WritableMemory asWritableMemory(final boolean localReadOnly, final ByteOrder 
byteOrder) {
+    Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
+    if (isReadOnly() && !localReadOnly) {
+      throw new ReadOnlyException(
+          "Converting a read-only Buffer to a writable Memory is not 
allowed.");
+    }
+    final boolean readOnly = isReadOnly() || localReadOnly;
+    final WritableMemory wmem = toWritableMemory(readOnly, byteOrder);
+    return wmem;
+  }
+
+  abstract BaseWritableMemoryImpl toWritableMemory(boolean readOnly, ByteOrder 
byteOrder);
+
+  //PRIMITIVE getX() and getXArray()
+  @Override
+  public final boolean getBoolean() {
+    final long pos = getPosition();
+    incrementAndAssertPositionForRead(pos, ARRAY_BOOLEAN_INDEX_SCALE);
+    return unsafe.getBoolean(getUnsafeObject(), getCumulativeOffset(pos));
+  }
+
+  @Override
+  public final boolean getBoolean(final long offsetBytes) {
+    assertValidAndBoundsForRead(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE);
+    return unsafe.getBoolean(getUnsafeObject(), 
getCumulativeOffset(offsetBytes));
+  }
+
+  @Override
+  public final void getBooleanArray(final boolean[] dstArray, final int 
dstOffsetBooleans,
+      final int lengthBooleans) {
+    final long pos = getPosition();
+    final long copyBytes = lengthBooleans;
+    incrementAndCheckPositionForRead(pos, copyBytes);
+    checkBounds(dstOffsetBooleans, lengthBooleans, dstArray.length);
+    CompareAndCopy.copyMemoryCheckingDifferentObject(
+            getUnsafeObject(),
+            getCumulativeOffset(pos),
+            dstArray,
+            ARRAY_BOOLEAN_BASE_OFFSET + dstOffsetBooleans,
+            copyBytes);
+  }
+
+  @Override
+  public final byte getByte() {
+    final long pos = getPosition();
+    incrementAndAssertPositionForRead(pos, ARRAY_BYTE_INDEX_SCALE);
+    return unsafe.getByte(getUnsafeObject(), getCumulativeOffset(pos));
+  }
+
+  @Override
+  public final byte getByte(final long offsetBytes) {
+    assertValidAndBoundsForRead(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
+    return unsafe.getByte(getUnsafeObject(), getCumulativeOffset(offsetBytes));
+  }
+
+  @Override
+  public final void getByteArray(final byte[] dstArray, final int 
dstOffsetBytes,
+      final int lengthBytes) {
+    final long pos = getPosition();
+    final long copyBytes = lengthBytes;
+    incrementAndCheckPositionForRead(pos, copyBytes);
+    checkBounds(dstOffsetBytes, lengthBytes, dstArray.length);
+    CompareAndCopy.copyMemoryCheckingDifferentObject(
+            getUnsafeObject(),
+            getCumulativeOffset(pos),
+            dstArray,
+            ARRAY_BYTE_BASE_OFFSET + dstOffsetBytes,
+            copyBytes);
+  }
+
+  //PRIMITIVE getX() Native Endian (used by both endians)
+  final char getNativeOrderedChar() {
+    final long pos = getPosition();
+    incrementAndAssertPositionForRead(pos, ARRAY_CHAR_INDEX_SCALE);
+    return unsafe.getChar(getUnsafeObject(), getCumulativeOffset(pos));
+  }
+
+  final char getNativeOrderedChar(final long offsetBytes) {
+    assertValidAndBoundsForRead(offsetBytes, ARRAY_CHAR_INDEX_SCALE);
+    return unsafe.getChar(getUnsafeObject(), getCumulativeOffset(offsetBytes));
+  }
+
+  final int getNativeOrderedInt() {
+    final long pos = getPosition();
+    incrementAndAssertPositionForRead(pos, ARRAY_INT_INDEX_SCALE);
+    return unsafe.getInt(getUnsafeObject(), getCumulativeOffset(pos));
+  }
+
+  final int getNativeOrderedInt(final long offsetBytes) {
+    assertValidAndBoundsForRead(offsetBytes, ARRAY_INT_INDEX_SCALE);
+    return unsafe.getInt(getUnsafeObject(), getCumulativeOffset(offsetBytes));
+  }
+
+  final long getNativeOrderedLong() {
+    final long pos = getPosition();
+    incrementAndAssertPositionForRead(pos, ARRAY_LONG_INDEX_SCALE);
+    return unsafe.getLong(getUnsafeObject(), getCumulativeOffset(pos));
+  }
+
+  final long getNativeOrderedLong(final long offsetBytes) {
+    assertValidAndBoundsForRead(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    return unsafe.getLong(getUnsafeObject(), getCumulativeOffset(offsetBytes));
+  }
+
+  final short getNativeOrderedShort() {
+    final long pos = getPosition();
+    incrementAndAssertPositionForRead(pos, ARRAY_SHORT_INDEX_SCALE);
+    return unsafe.getShort(getUnsafeObject(), getCumulativeOffset(pos));
+  }
+
+  final short getNativeOrderedShort(final long offsetBytes) {
+    assertValidAndBoundsForRead(offsetBytes, ARRAY_SHORT_INDEX_SCALE);
+    return unsafe.getShort(getUnsafeObject(), 
getCumulativeOffset(offsetBytes));
+  }
+
+  //OTHER PRIMITIVE READ METHODS: copyTo, compareTo
+  @Override
+  public final int compareTo(final long thisOffsetBytes, final long 
thisLengthBytes,
+      final Buffer thatBuf, final long thatOffsetBytes, final long 
thatLengthBytes) {
+    return CompareAndCopy.compare((BaseStateImpl)this, thisOffsetBytes, 
thisLengthBytes,
+        (BaseStateImpl)thatBuf, thatOffsetBytes, thatLengthBytes);
+  }
+
+  /*
+   * Develper notes: There is no copyTo for Buffers because of the ambiguity 
of what to do with
+   * the positional values. Switch to MemoryImpl view to do copyTo.
+   */
+
+  //PRIMITIVE putX() and putXArray() implementations
+  @Override
+  public final void putBoolean(final boolean value) {
+    final long pos = getPosition();
+    incrementAndAssertPositionForWrite(pos, ARRAY_BOOLEAN_INDEX_SCALE);
+    unsafe.putBoolean(getUnsafeObject(), getCumulativeOffset(pos), value);
+  }
+
+  @Override
+  public final void putBoolean(final long offsetBytes, final boolean value) {
+    assertValidAndBoundsForWrite(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE);
+    unsafe.putBoolean(getUnsafeObject(), getCumulativeOffset(offsetBytes), 
value);
+  }
+
+  @Override
+  public final void putBooleanArray(final boolean[] srcArray, final int 
srcOffsetBooleans,
+      final int lengthBooleans) {
+    final long pos = getPosition();
+    final long copyBytes = lengthBooleans;
+    incrementAndCheckPositionForWrite(pos, copyBytes);
+    checkBounds(srcOffsetBooleans, lengthBooleans, srcArray.length);
+    CompareAndCopy.copyMemoryCheckingDifferentObject(
+            srcArray,
+            ARRAY_BOOLEAN_BASE_OFFSET + srcOffsetBooleans,
+            getUnsafeObject(),
+            getCumulativeOffset(pos),
+            copyBytes);
+  }
+
+  @Override
+  public final void putByte(final byte value) {
+    final long pos = getPosition();
+    incrementAndAssertPositionForWrite(pos, ARRAY_BYTE_INDEX_SCALE);
+    unsafe.putByte(getUnsafeObject(), getCumulativeOffset(pos), value);
+  }
+
+  @Override
+  public final void putByte(final long offsetBytes, final byte value) {
+    assertValidAndBoundsForWrite(offsetBytes, ARRAY_BYTE_INDEX_SCALE);
+    unsafe.putByte(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
+  }
+
+  @Override
+  public final void putByteArray(final byte[] srcArray, final int 
srcOffsetBytes,
+      final int lengthBytes) {
+    final long pos = getPosition();
+    final long copyBytes = lengthBytes;
+    incrementAndCheckPositionForWrite(pos, copyBytes);
+    checkBounds(srcOffsetBytes, lengthBytes, srcArray.length);
+    CompareAndCopy.copyMemoryCheckingDifferentObject(
+            srcArray,
+            ARRAY_BYTE_BASE_OFFSET + srcOffsetBytes,
+            getUnsafeObject(),
+            getCumulativeOffset(pos),
+            copyBytes);
+  }
+
+  //PRIMITIVE putX() Native Endian (used by both endians)
+  final void putNativeOrderedChar(final char value) {
+    final long pos = getPosition();
+    incrementAndAssertPositionForWrite(pos, ARRAY_CHAR_INDEX_SCALE);
+    unsafe.putChar(getUnsafeObject(), getCumulativeOffset(pos), value);
+  }
+
+  final void putNativeOrderedChar(final long offsetBytes, final char value) {
+    assertValidAndBoundsForWrite(offsetBytes, ARRAY_CHAR_INDEX_SCALE);
+    unsafe.putChar(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
+  }
+
+  final void putNativeOrderedInt(final int value) {
+    final long pos = getPosition();
+    incrementAndAssertPositionForWrite(pos, ARRAY_INT_INDEX_SCALE);
+    unsafe.putInt(getUnsafeObject(), getCumulativeOffset(pos), value);
+  }
+
+  final void putNativeOrderedInt(final long offsetBytes, final int value) {
+    assertValidAndBoundsForWrite(offsetBytes, ARRAY_INT_INDEX_SCALE);
+    unsafe.putInt(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
+  }
+
+  final void putNativeOrderedLong(final long value) {
+    final long pos = getPosition();
+    incrementAndAssertPositionForWrite(pos, ARRAY_LONG_INDEX_SCALE);
+    unsafe.putLong(getUnsafeObject(), getCumulativeOffset(pos), value);
+  }
+
+  final void putNativeOrderedLong(final long offsetBytes, final long value) {
+    assertValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE);
+    unsafe.putLong(getUnsafeObject(), getCumulativeOffset(offsetBytes), value);
+  }
+
+  final void putNativeOrderedShort(final short value) {
+    final long pos = getPosition();
+    incrementAndAssertPositionForWrite(pos, ARRAY_SHORT_INDEX_SCALE);
+    unsafe.putShort(getUnsafeObject(), getCumulativeOffset(pos), value);
+  }
+
+  final void putNativeOrderedShort(final long offsetBytes, final short value) {
+    assertValidAndBoundsForWrite(offsetBytes, ARRAY_SHORT_INDEX_SCALE);
+    unsafe.putShort(getUnsafeObject(), getCumulativeOffset(offsetBytes), 
value);
+  }
+
+  //OTHER
+  @Override
+  public final Object getArray() {
+    assertValid();
+    return getUnsafeObject();
+  }
+
+  @Override
+  public final void clear() {
+    fill((byte)0);
+  }
+
+  @Override
+  public final void fill(final byte value) {
+    checkValidForWrite();
+    long pos = getPosition();
+    long len = getEnd() - pos;
+    checkInvariants(getStart(), pos + len, getEnd(), getCapacity());
+    while (len > 0) {
+      final long chunk = Math.min(len, Util.UNSAFE_COPY_THRESHOLD_BYTES);
+      unsafe.setMemory(getUnsafeObject(), getCumulativeOffset(pos), chunk, 
value);
+      pos += chunk;
+      len -= chunk;
+    }
+  }
+}

Propchange: 
dev/datasketches/memory/2.2.0-RC1/apache-datasketches-memory-2.2.0-src/datasketches-memory-java8/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
------------------------------------------------------------------------------
    svn:executable = *



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to