This is an automated email from the ASF dual-hosted git repository.

leerho pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datasketches-memory17.git

commit 742b581ce0fc0989e3e3aa53a34f6c1905bf18a9
Author: Lee Rhodes <[email protected]>
AuthorDate: Thu Sep 28 10:14:58 2023 -0700

    Wrap ResourceScope in MemoryScope.
---
 pom.xml                                            |   6 +-
 .../org/apache/datasketches/memory/BaseState.java  |  12 +-
 .../org/apache/datasketches/memory/Memory.java     |  15 +-
 .../apache/datasketches/memory/MemoryScope.java    | 135 +++++++-----------
 .../apache/datasketches/memory/WritableMemory.java |  31 ++--
 .../memory/internal/BaseStateImpl.java             |   9 +-
 .../memory/internal/BaseWritableBufferImpl.java    |   9 ++
 .../memory/internal/BaseWritableMemoryImpl.java    |  75 +++++++---
 .../memory/internal/MemoryScopeImpl.java           | 157 +++++++++++++++++++++
 .../memory/internal/NativeWritableBufferImpl.java  |   2 +-
 .../memory/internal/NativeWritableMemoryImpl.java  |   2 +-
 .../internal/NonNativeWritableBufferImpl.java      |   2 +-
 .../internal/NonNativeWritableMemoryImpl.java      |   2 +-
 13 files changed, 317 insertions(+), 140 deletions(-)

diff --git a/pom.xml b/pom.xml
index c133dbf..84cd565 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,8 +99,10 @@ under the License.
     <!-- END:UNIQUE FOR THIS JAVA COMPONENT -->
 
     <!-- Test -->
-    <!-- Version 7.4.0 fails to locate jquery.min.js for reporting on debian 
systems -->
-    <testng.version>7.5</testng.version>
+    <!-- Version 7.4.0 fails to locate jquery.min.js for reporting on debian 
systems.
+         Version 7.5 has a serious security bug, for Java 8 use 7.5.1.
+         For Java 9+ use 7.8+ -->
+    <testng.version>7.5.1</testng.version>
 
     <!-- System-wide properties -->
     <maven.version>3.5.0</maven.version>
diff --git a/src/main/java/org/apache/datasketches/memory/BaseState.java 
b/src/main/java/org/apache/datasketches/memory/BaseState.java
index 7bfbab8..e19064c 100644
--- a/src/main/java/org/apache/datasketches/memory/BaseState.java
+++ b/src/main/java/org/apache/datasketches/memory/BaseState.java
@@ -23,7 +23,6 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
 import jdk.incubator.foreign.MemorySegment;
-import jdk.incubator.foreign.ResourceScope;
 
 /**
  * Keeps key configuration state for Memory and Buffer plus some common static 
variables
@@ -38,10 +37,13 @@ public interface BaseState {
    */
   static final String LS = System.getProperty("line.separator");
 
+  /** Constant native ByteOrder */
   static final ByteOrder NATIVE_BYTE_ORDER = ByteOrder.nativeOrder();
+  /** Constant non-native ByteOrder */
   static final ByteOrder NON_NATIVE_BYTE_ORDER =
       ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN
       ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+  /** Constant default MemoryRequestServer */
   static final MemoryRequestServer defaultMemReqSvr = new 
DefaultMemoryRequestServer();
 
   /**
@@ -203,16 +205,16 @@ public interface BaseState {
   boolean isSameResource(Object that);
 
   /**
-   * Loads the contents of this mapped segment into physical memory. Please 
refer to
+   * Loads the contents of this mapped memory instance into physical memory. 
Please refer to
    * <a 
href="https://docs.oracle.com/en/java/javase/17/docs/api/jdk.incubator.foreign/jdk/incubator/foreign/MemorySegment.html#load()">load()</a>
    */
   void load();
 
   /**
-   * Returns the resource scope associated with this memory segment.
-   * @return the resource scope associated with this memory segment.
+   * Returns the MemoryScope associated with this memory instance.
+   * @return the MemoryScope associated with this memory instance.
    */
-  ResourceScope scope();
+  MemoryScope scope();
 
   //  /**
   //   * Sets the default MemoryRequestServer to be used in case of capacity 
overflow of off-heap
diff --git a/src/main/java/org/apache/datasketches/memory/Memory.java 
b/src/main/java/org/apache/datasketches/memory/Memory.java
index 1c9e5e2..778d69a 100644
--- a/src/main/java/org/apache/datasketches/memory/Memory.java
+++ b/src/main/java/org/apache/datasketches/memory/Memory.java
@@ -28,7 +28,6 @@ import java.nio.ByteOrder;
 import org.apache.datasketches.memory.internal.BaseWritableMemoryImpl;
 
 import jdk.incubator.foreign.MemorySegment;
-import jdk.incubator.foreign.ResourceScope;
 
 /**
  * Defines the read-only API for offset access to a resource.
@@ -71,10 +70,10 @@ public interface Memory extends BaseState {
   /**
    * Maps the given file into <i>Memory</i> for read operations
    * Calling this method is equivalent to calling
-   * {@link #map(File, long, long, ResourceScope, ByteOrder)
+   * {@link #map(File, long, long, MemoryScope, ByteOrder)
    * map(file, 0, file.length(), scope, ByteOrder.nativeOrder())}.
    * @param file the given file to map. It must be non-null with a 
non-negative length and readable.
-   * @param scope the given ResourceScope. It must be non-null.
+   * @param memScope the given MemoryScope. It must be non-null.
    * @return mapped Memory.
    * @throws IllegalArgumentException -- if file is not readable.
    * @throws IllegalStateException - if scope has been already closed, or if 
access occurs from a thread other
@@ -83,9 +82,9 @@ public interface Memory extends BaseState {
    * @throws SecurityException - If a security manager is installed and it 
denies an unspecified permission
    * required by the implementation.
    */
-  static Memory map(File file, ResourceScope scope)
+  static Memory map(File file, MemoryScope memScope)
       throws IllegalArgumentException, IllegalStateException, IOException, 
SecurityException {
-    return map(file, 0, file.length(), scope, ByteOrder.nativeOrder());
+    return map(file, 0, file.length(), memScope, ByteOrder.nativeOrder());
   }
 
   /**
@@ -93,7 +92,7 @@ public interface Memory extends BaseState {
    * @param file the given file to map. It must be non-null,readable and 
length &ge; 0.
    * @param fileOffsetBytes the position in the given file in bytes. It must 
not be negative.
    * @param capacityBytes the size of the mapped memory. It must not be 
negative..
-   * @param scope the given ResourceScope. It must be non-null.
+   * @param memScope the given MemoryScope. It must be non-null.
    * @param byteOrder the byte order to be used.  It must be non-null.
    * @return mapped Memory
    * @throws IllegalArgumentException -- if file is not readable.
@@ -103,9 +102,9 @@ public interface Memory extends BaseState {
    * @throws SecurityException - If a security manager is installed and it 
denies an unspecified permission
    * required by the implementation.
    */
-  static Memory map(File file, long fileOffsetBytes, long capacityBytes, 
ResourceScope scope, ByteOrder byteOrder)
+  static Memory map(File file, long fileOffsetBytes, long capacityBytes, 
MemoryScope memScope, ByteOrder byteOrder)
       throws IllegalArgumentException, IllegalStateException, IOException, 
SecurityException {
-    return BaseWritableMemoryImpl.wrapMap(file, fileOffsetBytes, 
capacityBytes, scope, true, byteOrder);
+    return BaseWritableMemoryImpl.wrapMap(file, fileOffsetBytes, 
capacityBytes, memScope, true, byteOrder);
   }
 
   //NO ALLOCATE DIRECT, makes no sense
diff --git a/src/main/java/org/apache/datasketches/memory/MemoryScope.java 
b/src/main/java/org/apache/datasketches/memory/MemoryScope.java
index fe18a9c..053c344 100644
--- a/src/main/java/org/apache/datasketches/memory/MemoryScope.java
+++ b/src/main/java/org/apache/datasketches/memory/MemoryScope.java
@@ -21,142 +21,113 @@ package org.apache.datasketches.memory;
 
 import java.lang.ref.Cleaner;
 
-import jdk.incubator.foreign.ResourceScope;
+import org.apache.datasketches.memory.internal.MemoryScopeImpl;
+
 
 /**
  * A wrapper around jdk.incubator.foreign.ResourceScope
  */
-@SuppressWarnings("resource")
-public final class MemoryScope {
-  private ResourceScope resourceScope;
-
-  private MemoryScope(final ResourceScope resourceScope) {
-    this.resourceScope = resourceScope;
-  }
-
-  /**
-   * Acquires a <i>MemoryScope.Handle</i> associated with this 
<i>MemoryScope</i>.
-   * The underlying explicit <i>ResourceScope</i> cannot be closed until all 
the scope handles
-   * acquired from it have been <i>release(Handle)</i> released.
-   * @return a <i>MemoryScope.Handle</i>.
-   */
-  public Handle acquire() {
-    return new Handle();
-  }
+public abstract class MemoryScope {
 
   /**
-   * Add a custom cleanup action which will be executed when the underlying 
<i>ResourceScope</i> is closed.
-   * The order in which custom cleanup actions are invoked once the scope is 
closed is unspecified.
-   *
-   * @param runnable the custom cleanup action to be associated with this 
scope.
-   * @throws IllegalStateException if this scope has already been closed.
+   * @return a new <i>MemoryScope</i> that wraps a 
<i>ResourceScope.globalScope()</i>.
    */
-  public void addCloseAction(final Runnable runnable) {
-    resourceScope.addCloseAction(runnable);
+  public static MemoryScope globalScope() {
+     return MemoryScopeImpl.getGlobalScope();
   }
 
   /**
-   * Closes this the underlying <i>ResourceScope</i>.
+   * @return a new <i>MemoryScope</i> that wraps a 
<i>ResourceScope.newConfiledScope()</i>.
    */
-  public void close() {
-    if (resourceScope != null) {
-    resourceScope.close();
-    }
+  public static MemoryScope newConfinedScope() {
+    return MemoryScopeImpl.getNewConfinedScope();
   }
 
   /**
-   * Returns the underlying <i>ResourceScope</i>.
-   * @return the underlying <i>ResourceScope</i>.
+   * @param cleaner a user defined <i>Cleaner</i> for this scope
+   * @return a new <i>MemoryScope</i> that wraps a 
<i>ResourceScope.newConfinedScope(Cleaner)</i>.
    */
-  ResourceScope getResourceScope() {
-    return resourceScope;
+  public static MemoryScope newConfinedScope(final Cleaner cleaner) {
+    return MemoryScopeImpl.getNewConfinedScope(cleaner);
   }
 
   /**
-   * @return a new <i>MemoryScope</i> that wraps a 
<i>ResourceScope.globalScope()</i>.
+   * @return a new <i>MemoryScope</i> that wraps a 
<i>ResourceScope.newSharedScope()</i>.
    */
-  public static MemoryScope globalScope() {
-     return new MemoryScope(ResourceScope.globalScope());
+  public static MemoryScope newSharedScope() {
+    return MemoryScopeImpl.getNewSharedScope();
   }
 
   /**
-   * Is the underlying <i>ResourceScope</i> alive?
-   * @return true if this resource scope is alive.
+   * @param cleaner a user defined <i>Cleaner</i> for this scope
+   * @return a new <i>MemoryScope</i> that wraps a 
<i>ResourceScope.newSharedScope(Cleaner)</i>.
    */
-  public boolean isAlive() {
-    return resourceScope.isAlive();
+  public static MemoryScope newSharedScope(final Cleaner cleaner) {
+    return MemoryScopeImpl.getNewSharedScope(cleaner);
   }
 
   /**
-   * Is the underlying <i>ResourceScope</i> alive?
-   * @return true if the underlying <i>ResourceScope</i> is alive.
+   * Acquires a <i>MemoryScope.Handle</i> associated with this 
<i>MemoryScope</i>.
+   * The underlying explicit <i>ResourceScope</i> cannot be closed until all 
the scope handles
+   * acquired from it have been <i>release(Handle)</i> released.
+   * @return a <i>MemoryScope.Handle</i>.
    */
-  public boolean isImplicit() {
-    return resourceScope.isImplicit();
-  }
+  public abstract Handle acquire();
 
   /**
-   * @return a new <i>MemoryScope</i> that wraps a 
<i>ResourceScope.newConfiledScope()</i>.
+   * Add a custom cleanup action which will be executed when the underlying 
<i>ResourceScope</i> is closed.
+   * The order in which custom cleanup actions are invoked once the scope is 
closed is unspecified.
+   *
+   * @param runnable the custom cleanup action to be associated with this 
scope.
+   * @throws IllegalStateException if this scope has already been closed.
    */
-  public static MemoryScope newConfinedScope() {
-    return new MemoryScope(ResourceScope.newConfinedScope());
-  }
+  public abstract void addCloseAction(final Runnable runnable);
 
   /**
-   * @param cleaner a user defined <i>Cleaner</i> for this scope
-   * @return a new <i>MemoryScope</i> that wraps a 
<i>ResourceScope.newConfinedScope(Cleaner)</i>.
+   * Closes this the underlying <i>ResourceScope</i>.
    */
-  public static MemoryScope newConfinedScope(final Cleaner cleaner) {
-    return new MemoryScope(ResourceScope.newConfinedScope(cleaner));
-  }
+  public abstract void close();
 
   /**
-   * @return a new <i>MemoryScope</i> that wraps a 
<i>ResourceScope.newSharedScope()</i>.
+   * Is the underlying <i>ResourceScope</i> alive?
+   * @return true if this resource scope is alive.
    */
-  public static MemoryScope newSharedScope() {
-    return new MemoryScope(ResourceScope.newSharedScope());
-  }
+  public abstract boolean isAlive();
 
   /**
-   * @param cleaner a user defined <i>Cleaner</i> for this scope
-   * @return a new <i>MemoryScope</i> that wraps a 
<i>ResourceScope.newSharedScope(Cleaner)</i>.
+   * Is the underlying <i>ResourceScope</i> alive?
+   * @return true if the underlying <i>ResourceScope</i> is alive.
    */
-  public static MemoryScope newSharedScope(final Cleaner cleaner) {
-    return new MemoryScope(ResourceScope.newSharedScope(cleaner));
-  }
+  public abstract boolean isImplicit();
 
   /**
    * The thread owning the underlying <i>ResourceScope</i>.
    * @return the thread owning the underlying <i>ResourceScope</i>.
    */
-  public Thread ownerThread() {
-    return resourceScope.ownerThread();
-  }
+  public abstract Thread ownerThread();
 
-  public void release(final MemoryScope.Handle handle) {
-    if (handle.scope() == this) { handle.release(handle); }
-  }
+  /**
+   * Releases the given handle
+   * @param handle the given handle
+   */
+  public abstract void release(final MemoryScope.Handle handle);
 
   /**
    * A handle for this <i>MemoryScope</i>.
    */
-  public class Handle {
-    private ResourceScope.Handle myResourceHandle;
-
-    Handle() {
-      this.myResourceHandle = resourceScope.acquire();
-    }
+  public abstract class Handle {
 
     /**
      * Returns the <i>MemoryScope</i> associated with this handle.
      * @return the <i>MemoryScope</i> associated with this handle.
      */
-    public MemoryScope scope() { return MemoryScope.this; }
+    public abstract MemoryScope scope();
+
+    /**
+     * Releases the given handle if valid.
+     * @param handle the given handle
+     */
+    public abstract void release(final MemoryScope.Handle handle);
 
-    void release(final MemoryScope.Handle handle) {
-      if (handle.myResourceHandle == myResourceHandle) {
-        MemoryScope.this.resourceScope.release(myResourceHandle);
-      }
-    }
   }
 }
diff --git a/src/main/java/org/apache/datasketches/memory/WritableMemory.java 
b/src/main/java/org/apache/datasketches/memory/WritableMemory.java
index d3e6247..d2a6d7a 100644
--- a/src/main/java/org/apache/datasketches/memory/WritableMemory.java
+++ b/src/main/java/org/apache/datasketches/memory/WritableMemory.java
@@ -27,7 +27,6 @@ import java.nio.ByteOrder;
 import org.apache.datasketches.memory.internal.BaseWritableMemoryImpl;
 
 import jdk.incubator.foreign.MemorySegment;
-import jdk.incubator.foreign.ResourceScope;
 
 /**
  * Defines the writable API for offset access to a resource.
@@ -71,10 +70,10 @@ public interface WritableMemory extends Memory {
   /**
    * Maps the entire given file into native-ordered WritableMemory for write 
operations
    * Calling this method is equivalent to calling
-   * {@link #writableMap(File, long, long, ResourceScope, ByteOrder)
+   * {@link #writableMap(File, long, long, MemoryScope, ByteOrder)
    *   writableMap(file, 0, file.length(), scope, ByteOrder.nativeOrder())}.
    * @param file the given file to map. It must be non-null with a 
non-negative length and writable.
-   * @param scope the give Resource Scope. It must be non-null.
+   * @param memScope the given MemoryScope. It must be non-null.
    * @return mapped WritableMemory
    * @throws IllegalArgumentException -- if file is not readable.
    * @throws IllegalArgumentException -- if file is not writable.
@@ -84,9 +83,9 @@ public interface WritableMemory extends Memory {
    * @throws SecurityException - If a security manager is installed and it 
denies an unspecified permission
    * required by the implementation.
    */
-  static WritableMemory writableMap(File file, ResourceScope scope)
+  static WritableMemory writableMap(File file, MemoryScope memScope)
       throws IllegalArgumentException, IllegalStateException, IOException, 
SecurityException {
-    return writableMap(file, 0, file.length(), scope, ByteOrder.nativeOrder());
+    return writableMap(file, 0, file.length(), memScope, 
ByteOrder.nativeOrder());
   }
 
   /**
@@ -94,7 +93,7 @@ public interface WritableMemory extends Memory {
    * @param file the given file to map. It must be non-null with a 
non-negative length and writable.
    * @param fileOffsetBytes the position in the given file in bytes. It must 
not be negative.
    * @param capacityBytes the size of the mapped Memory. It must be &ge; 0.
-   * @param scope the give Resource Scope. It must be non-null.
+   * @param memScope the given MemoryScope. It must be non-null.
    * @param byteOrder the byte order to be used.  It must be non-null.
    * @return mapped WritableMemory.
    * @throws IllegalArgumentException -- if file is not readable or writable.
@@ -105,9 +104,9 @@ public interface WritableMemory extends Memory {
    * @throws SecurityException - If a security manager is installed and it 
denies an unspecified permission
    * required by the implementation.
    */
-  static WritableMemory writableMap(File file, long fileOffsetBytes, long 
capacityBytes, ResourceScope scope,
+  static WritableMemory writableMap(File file, long fileOffsetBytes, long 
capacityBytes, MemoryScope memScope,
       ByteOrder byteOrder) throws IllegalArgumentException, 
IllegalStateException, IOException, SecurityException {
-    return BaseWritableMemoryImpl.wrapMap(file, fileOffsetBytes, 
capacityBytes, scope, false, byteOrder);
+    return BaseWritableMemoryImpl.wrapMap(file, fileOffsetBytes, 
capacityBytes, memScope, false, byteOrder);
   }
 
   //ALLOCATE DIRECT
@@ -120,12 +119,13 @@ public interface WritableMemory extends Memory {
    * <p><b>NOTICE:</b> It is the responsibility of the using application to 
call <i>close()</i> when done.</p>
    *
    * @param capacityBytes the size of the desired memory in bytes.
-   * @param scope the given ResourceScope. It must be non-null.
+   * @param memScope the given MemoryScope. It must be non-null.
    * @param memReqSvr A user-specified MemoryRequestServer, which may be null.
    * @return WritableMemory for this off-heap, native resource.
    */
-  static WritableMemory allocateDirect(long capacityBytes, ResourceScope 
scope, MemoryRequestServer memReqSvr) {
-    return allocateDirect(capacityBytes, 8, scope, ByteOrder.nativeOrder(), 
memReqSvr);
+  static WritableMemory allocateDirect(long capacityBytes, MemoryScope 
memScope, MemoryRequestServer memReqSvr) {
+    return allocateDirect(capacityBytes, 8, memScope,
+        ByteOrder.nativeOrder(), memReqSvr);
   }
 
   /**
@@ -137,7 +137,7 @@ public interface WritableMemory extends Memory {
    *
    * @param capacityBytes the size of the desired memory in bytes.
    * @param alignmentBytes requested segment alignment. Typically 1, 2, 4 or 8.
-   * @param scope the given ResourceScope. It must be non-null.
+   * @param memScope the given MemoryScope. It must be non-null.
    * @param byteOrder the byte order to be used.  It must be non-null.
    * @param memReqSvr A user-specified MemoryRequestServer, which may be null.
    * This is a callback mechanism for a user client of direct memory to 
request more memory.
@@ -146,10 +146,11 @@ public interface WritableMemory extends Memory {
   static WritableMemory allocateDirect(
       long capacityBytes,
       long alignmentBytes,
-      ResourceScope scope,
+      MemoryScope memScope,
       ByteOrder byteOrder,
       MemoryRequestServer memReqSvr) {
-    return BaseWritableMemoryImpl.wrapDirect(capacityBytes, alignmentBytes, 
scope, byteOrder, memReqSvr);
+    return BaseWritableMemoryImpl.wrapDirect(capacityBytes, alignmentBytes,
+        memScope, byteOrder, memReqSvr);
   }
 
   //REGIONS
@@ -547,7 +548,7 @@ public interface WritableMemory extends Memory {
    * Gets the MemoryRequestServer implementation, if set, to request 
additional memory.
    * The user must customize the actions of the MemoryRequestServer by
    * implementing the MemoryRequestServer interface and set using this method:
-   * {@link WritableMemory#allocateDirect(long, long, ResourceScope, 
ByteOrder, MemoryRequestServer)}.
+   * {@link WritableMemory#allocateDirect(long, long, MemoryScope, ByteOrder, 
MemoryRequestServer)}.
    * Simple implementation examples include the DefaultMemoryRequestServer in 
the main tree, as well as
    * the ExampleMemoryRequestServerTest and the use with ByteBuffer documented 
in the DruidIssue11544Test
    * in the test tree.
diff --git 
a/src/main/java/org/apache/datasketches/memory/internal/BaseStateImpl.java 
b/src/main/java/org/apache/datasketches/memory/internal/BaseStateImpl.java
index 7167a27..bc0e603 100644
--- a/src/main/java/org/apache/datasketches/memory/internal/BaseStateImpl.java
+++ b/src/main/java/org/apache/datasketches/memory/internal/BaseStateImpl.java
@@ -27,12 +27,12 @@ import java.util.Objects;
 
 import org.apache.datasketches.memory.BaseState;
 import org.apache.datasketches.memory.MemoryRequestServer;
+import org.apache.datasketches.memory.MemoryScope;
 import org.apache.datasketches.memory.WritableBuffer;
 import org.apache.datasketches.memory.WritableMemory;
 
 import jdk.incubator.foreign.MemoryAddress;
 import jdk.incubator.foreign.MemorySegment;
-import jdk.incubator.foreign.ResourceScope;
 
 /**
  * Keeps key configuration state for MemoryImpl and BufferImpl plus some 
common static variables
@@ -42,7 +42,7 @@ import jdk.incubator.foreign.ResourceScope;
  */
 abstract class BaseStateImpl implements BaseState {
   static final String JDK; //must be at least "1.8"
-  static final int JDK_MAJOR; //8, 11, 12, etc
+  static final int JDK_MAJOR; //8, 11, 17, 21, etc
 
   static final int BOOLEAN_SHIFT    = 0;
   static final int BYTE_SHIFT       = 0;
@@ -82,7 +82,7 @@ abstract class BaseStateImpl implements BaseState {
     JDK_MAJOR = (p[0] == 1) ? p[1] : p[0];
   }
 
-  final MemorySegment seg;
+  final MemorySegment seg; //the single reference to the MemorySegment is kept 
here.
   final int typeId;
 
   MemoryRequestServer memReqSvr;
@@ -388,8 +388,9 @@ abstract class BaseStateImpl implements BaseState {
   @Override
   public void load() { seg.load(); }
 
+  @SuppressWarnings("resource")
   @Override
-  public ResourceScope scope() { return seg.scope(); }
+  public MemoryScope scope() { return new MemoryScopeImpl(seg.scope()); }
 
   //  @Override
   //  public void setMemoryRequestServer(final MemoryRequestServer memReqSvr) {
diff --git 
a/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
 
b/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
index 68c9134..c89cf45 100644
--- 
a/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
+++ 
b/src/main/java/org/apache/datasketches/memory/internal/BaseWritableBufferImpl.java
@@ -63,6 +63,15 @@ public abstract class BaseWritableBufferImpl extends 
BaseBufferImpl implements W
 
   //BYTE BUFFER RESOURCE
 
+  /**
+   * Creates a read-only or writable, Native or Non-native endian Buffer 
instance
+   * given a ByteBuffer.
+   * @param byteBuffer the given ByteBuffer
+   * @param localReadOnly the given requested readOnly state
+   * @param byteOrder the given byte-order
+   * @return a WritableMemory instance, which may be read-only.
+   * @throws IllegalArgumentException if ByteBuffer is not writable.
+   */
   public static WritableBuffer wrapByteBuffer(
       final ByteBuffer byteBuffer,
       final boolean localReadOnly,
diff --git 
a/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java
 
b/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java
index 61a5a70..97e5108 100644
--- 
a/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java
+++ 
b/src/main/java/org/apache/datasketches/memory/internal/BaseWritableMemoryImpl.java
@@ -21,6 +21,7 @@ package org.apache.datasketches.memory.internal;
 
 import static java.nio.channels.FileChannel.MapMode.READ_ONLY;
 import static java.nio.channels.FileChannel.MapMode.READ_WRITE;
+import static java.util.Objects.requireNonNull;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -28,17 +29,16 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.channels.FileChannel;
-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.MemoryScope;
 import org.apache.datasketches.memory.WritableBuffer;
 import org.apache.datasketches.memory.WritableMemory;
 
 import jdk.incubator.foreign.MemoryAccess;
 import jdk.incubator.foreign.MemorySegment;
-import jdk.incubator.foreign.ResourceScope;
 
 /*
  * Developer notes: The heavier methods, such as put/get arrays, duplicate, 
region, clear, fill,
@@ -68,13 +68,20 @@ public abstract class BaseWritableMemoryImpl extends 
BaseStateImpl implements Wr
 
   //WRAP HEAP ARRAY RESOURCE
 
+  /**
+   * Creates a read-only or writable, Native or Non-native endian Memory 
instance
+   * given a segment containing an arbitrary on-heap array.
+   * @param seg the given segment
+   * @param byteOrder the given byte-order
+   * @param memReqSvr a MemoryRequestServer or null
+   * @return a WritableMemory instance, which may be read-only.
+   */
   public static WritableMemory wrapSegmentAsArray(
       final MemorySegment seg,
       final ByteOrder byteOrder,
       final MemoryRequestServer memReqSvr) {
-    Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
-    int type = MEMORY
-        | (seg.isReadOnly() ? READONLY : 0);
+    requireNonNull(byteOrder, "byteOrder must be non-null");
+    int type = MEMORY | (seg.isReadOnly() ? READONLY : 0);
     if (byteOrder == NON_NATIVE_BYTE_ORDER) {
       type |= NONNATIVE;
       return new NonNativeWritableMemoryImpl(seg, type, memReqSvr);
@@ -84,12 +91,21 @@ public abstract class BaseWritableMemoryImpl extends 
BaseStateImpl implements Wr
 
   //BYTE BUFFER RESOURCE
 
+  /**
+   * Creates a read-only or writable, Native or Non-native endian Memory 
instance
+   * given a ByteBuffer.
+   * @param byteBuffer the given ByteBuffer
+   * @param localReadOnly the given requested readOnly state
+   * @param byteOrder the given byte-order
+   * @return a WritableMemory instance, which may be read-only.
+   * @throws IllegalArgumentException if ByteBuffer is not writable.
+   */
   public static WritableMemory wrapByteBuffer(
       final ByteBuffer byteBuffer,
       final boolean localReadOnly,
       final ByteOrder byteOrder) {
-    Objects.requireNonNull(byteBuffer, "ByteBuffer must not be null");
-    Objects.requireNonNull(byteOrder, "ByteOrder must not be null");
+    requireNonNull(byteBuffer, "ByteBuffer must not be null");
+    requireNonNull(byteOrder, "ByteOrder must not be null");
     final ByteBuffer byteBuf;
     if (localReadOnly) {
       if (byteBuffer.isReadOnly()) {
@@ -121,23 +137,42 @@ public abstract class BaseWritableMemoryImpl extends 
BaseStateImpl implements Wr
 
   //MAP FILE RESOURCE
 
+  /**
+   * Creates a writable, Native or Non-native endian, memory-mapped Memory 
instance.
+   * @param file the given file
+   * @param fileOffsetBytes the given offset bytes in the file
+   * @param capacityBytes the size (in bytes) of the mapped memory backing the 
memory segment.
+   * @param memScope the MemoryScope that wraps the ResourceScope
+   * @param localReadOnly true if the returned segment is to be read-only
+   * @param byteOrder the give byte order
+   * @return a WritableMemory that wraps a MemorySegment
+   * @throws IllegalArgumentException if file is not writable
+   * @throws IllegalStateException during IO operations
+   * @throws IOException during IO operations
+   * @throws SecurityException due to IO security issues
+   */
   @SuppressWarnings("resource")
   public static WritableMemory wrapMap(
       final File file,
       final long fileOffsetBytes,
       final long capacityBytes,
-      final ResourceScope scope,
+      final MemoryScope memScope,
       final boolean localReadOnly,
       final ByteOrder byteOrder)
           throws IllegalArgumentException, IllegalStateException, IOException, 
SecurityException {
-    Objects.requireNonNull(file, "File must be non-null.");
-    Objects.requireNonNull(byteOrder, "ByteOrder must be non-null.");
-    Objects.requireNonNull(scope, "ResourceScope must be non-null.");
+    requireNonNull(file, "File must be non-null.");
+    requireNonNull(byteOrder, "ByteOrder must be non-null.");
+    requireNonNull(memScope, "MemoryScope must be non-null.");
     if (!file.canRead()) { throw new IllegalArgumentException("File must be 
readable."); }
     if (!localReadOnly && !file.canWrite()) { throw new 
IllegalArgumentException("File must be writable."); }
     final FileChannel.MapMode mapMode = (localReadOnly) ? READ_ONLY : 
READ_WRITE;
 
-    final MemorySegment seg = MemorySegment.mapFile(file.toPath(), 
fileOffsetBytes, capacityBytes, mapMode, scope);
+    final MemorySegment seg = MemorySegment.mapFile(
+        file.toPath(),
+        fileOffsetBytes,
+        capacityBytes,
+        mapMode,
+        ((MemoryScopeImpl)memScope).getResourceScope());
     final boolean nativeBOType = byteOrder == ByteOrder.nativeOrder();
     final int type = MEMORY | MAP | DIRECT
         | (localReadOnly ? READONLY : 0)
@@ -153,8 +188,8 @@ public abstract class BaseWritableMemoryImpl extends 
BaseStateImpl implements Wr
    * The static constructor that chooses the correct Direct leaf node based on 
the byte order.
    * @param capacityBytes the requested capacity for the Direct (off-heap) 
memory.  It must be &ge; 0.
    * @param alignmentBytes requested segment alignment. Typically 1, 2, 4 or 8.
-   * @param scope ResourceScope for the backing MemorySegment.
-   * Typically <i>ResourceScope.newConfinedScope()</i>.
+   * @param memScope MemoryScope that wraps a ResourceScope for the backing 
MemorySegment.
+   * Typically <i>MemoryScope.newConfinedScope()</i>.
    * @param byteOrder the byte order to be used.  It must be non-null.
    * @param memReqSvr A user-specified MemoryRequestServer, which may be null.
    * This is a callback mechanism for a user client of direct memory to 
request more memory.
@@ -164,15 +199,15 @@ public abstract class BaseWritableMemoryImpl extends 
BaseStateImpl implements Wr
   public static WritableMemory wrapDirect(
       final long capacityBytes,
       final long alignmentBytes,
-      final ResourceScope scope,
+      final MemoryScope memScope,
       final ByteOrder byteOrder,
       final MemoryRequestServer memReqSvr) {
-    Objects.requireNonNull(scope, "ResourceScope must be non-null");
-    Objects.requireNonNull(byteOrder, "ByteOrder must be non-null");
+    requireNonNull(memScope, "MemoryScope must be non-null");
+    requireNonNull(byteOrder, "ByteOrder must be non-null");
     final MemorySegment seg = MemorySegment.allocateNative(
         capacityBytes,
         alignmentBytes,
-        scope);
+        ((MemoryScopeImpl)memScope).getResourceScope());
     final boolean nativeBOType = byteOrder == ByteOrder.nativeOrder();
     final int type = MEMORY | DIRECT
         | (nativeBOType ? NATIVE : NONNATIVE);
@@ -202,7 +237,7 @@ public abstract class BaseWritableMemoryImpl extends 
BaseStateImpl implements Wr
       final boolean localReadOnly,
       final ByteOrder byteOrder) {
     if (!this.isAlive()) { throw new IllegalStateException("This Memory is not 
alive."); }
-    Objects.requireNonNull(byteOrder, "byteOrder must be non-null.");
+    requireNonNull(byteOrder, "byteOrder must be non-null.");
     final boolean readOnly = isReadOnly() || localReadOnly;
     final MemorySegment slice = (readOnly && !seg.isReadOnly())
         ? seg.asSlice(offsetBytes, capacityBytes).asReadOnly()
@@ -242,7 +277,7 @@ public abstract class BaseWritableMemoryImpl extends 
BaseStateImpl implements Wr
 
   private WritableBuffer asWritableBufferImpl(final boolean localReadOnly, 
final ByteOrder byteOrder) {
     if (!this.isAlive()) { throw new IllegalStateException("This Memory is not 
alive."); }
-    Objects.requireNonNull(byteOrder, "byteOrder must be non-null");
+    requireNonNull(byteOrder, "byteOrder must be non-null");
     final boolean readOnly = isReadOnly() || localReadOnly;
     final MemorySegment seg2 = (readOnly && !seg.isReadOnly()) ? 
seg.asReadOnly() : seg;
     final boolean regionType = isRegion();
diff --git 
a/src/main/java/org/apache/datasketches/memory/internal/MemoryScopeImpl.java 
b/src/main/java/org/apache/datasketches/memory/internal/MemoryScopeImpl.java
new file mode 100644
index 0000000..8b022d7
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/memory/internal/MemoryScopeImpl.java
@@ -0,0 +1,157 @@
+/*
+ * 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.lang.ref.Cleaner;
+
+import org.apache.datasketches.memory.MemoryScope;
+
+import jdk.incubator.foreign.ResourceScope;
+
+/**
+ * Implementation of MemoryScope
+ */
+@SuppressWarnings("resource")
+public class MemoryScopeImpl extends MemoryScope {
+  private ResourceScope resourceScope;
+
+  /**
+   * Constructor
+   * @param resourceScope the given ResourceScope.
+   */
+  public MemoryScopeImpl(final ResourceScope resourceScope) {
+    this.resourceScope = resourceScope;
+  }
+
+  /**
+   * Gets the GlobalScope
+   * @return the MemoryScope
+   */
+  public static MemoryScope getGlobalScope() {
+    return new MemoryScopeImpl(ResourceScope.globalScope());
+  }
+
+  /**
+   * Gets a new ConfinedScope
+   * @return the MemoryScope
+   */
+  public static MemoryScope getNewConfinedScope() {
+    return new MemoryScopeImpl(ResourceScope.newConfinedScope());
+  }
+
+  /**
+   * Gets a new ConfinedScope with Cleaner
+   * @param cleaner the given Cleaner
+   * @return the MemoryScope
+   */
+  public static MemoryScope getNewConfinedScope(final Cleaner cleaner) {
+    return new MemoryScopeImpl(ResourceScope.newConfinedScope(cleaner));
+  }
+
+  /**
+   * Gets a new SharedScope
+   * @return the MemoryScope
+   */
+  public static MemoryScope getNewSharedScope() {
+    return new MemoryScopeImpl(ResourceScope.newSharedScope());
+  }
+
+  /**
+   * Gets a new SharedScope with Cleaner
+   * @param cleaner the given Cleaner
+   * @return the MemoryScope
+   */
+  public static MemoryScope getNewSharedScope(final Cleaner cleaner) {
+    return new MemoryScopeImpl(ResourceScope.newSharedScope(cleaner));
+  }
+
+  @Override
+  public Handle acquire() {
+    return new HandleImpl();
+  }
+
+  @Override
+  public void addCloseAction(final Runnable runnable) {
+    resourceScope.addCloseAction(runnable);
+  }
+
+  @Override
+  public void close() {
+    if (resourceScope != null) {
+    resourceScope.close();
+    }
+  }
+
+  /**
+   * Returns the underlying <i>ResourceScope</i>.
+   * @return the underlying <i>ResourceScope</i>.
+   */
+  public ResourceScope getResourceScope() {
+    return resourceScope;
+  }
+
+  @Override
+  public boolean isAlive() {
+    return resourceScope.isAlive();
+  }
+
+  @Override
+  public boolean isImplicit() {
+    return resourceScope.isImplicit();
+  }
+
+  @Override
+  public Thread ownerThread() {
+    return resourceScope.ownerThread();
+  }
+
+  @Override
+  public void release(final MemoryScope.Handle handle) {
+    final HandleImpl handleImpl = (MemoryScopeImpl.HandleImpl) handle;
+    if (handleImpl.scope() == this) {
+      handleImpl.release(handleImpl);
+    }
+  }
+
+  /**
+   * Implements a handle for this <i>MemoryScope</i>.
+   */
+  public class HandleImpl extends MemoryScope.Handle {
+    private ResourceScope.Handle myResourceHandle;
+
+    /**
+     * Constructor
+     */
+    public HandleImpl() {
+      this.myResourceHandle = resourceScope.acquire();
+    }
+
+    @Override
+    public MemoryScope scope() { return MemoryScopeImpl.this; }
+
+    @Override
+    public void release(final MemoryScope.Handle handle) {
+      if ((MemoryScopeImpl.HandleImpl) handle == myResourceHandle) {
+        MemoryScopeImpl.this.resourceScope.release(myResourceHandle);
+      }
+    }
+  }
+
+}
diff --git 
a/src/main/java/org/apache/datasketches/memory/internal/NativeWritableBufferImpl.java
 
b/src/main/java/org/apache/datasketches/memory/internal/NativeWritableBufferImpl.java
index e5ec5ba..ccc7a40 100644
--- 
a/src/main/java/org/apache/datasketches/memory/internal/NativeWritableBufferImpl.java
+++ 
b/src/main/java/org/apache/datasketches/memory/internal/NativeWritableBufferImpl.java
@@ -45,7 +45,7 @@ import jdk.incubator.foreign.MemorySegment;
  */
 final class NativeWritableBufferImpl extends BaseWritableBufferImpl {
 
-  //Pass-through ctor
+  //All native endian, read-only and writable Buffer instances start 
initialization here
   NativeWritableBufferImpl(
       final MemorySegment seg,
       final int typeId,
diff --git 
a/src/main/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImpl.java
 
b/src/main/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImpl.java
index 41cb9b6..5233ab2 100644
--- 
a/src/main/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImpl.java
+++ 
b/src/main/java/org/apache/datasketches/memory/internal/NativeWritableMemoryImpl.java
@@ -44,7 +44,7 @@ import jdk.incubator.foreign.MemorySegment;
  */
 final class NativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
-  //Pass-through ctor
+  //All native endian, read-only and writable Memory instances start 
initialization here
   NativeWritableMemoryImpl(
       final MemorySegment seg,
       final int typeId,
diff --git 
a/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImpl.java
 
b/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImpl.java
index a27878e..44880e7 100644
--- 
a/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImpl.java
+++ 
b/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableBufferImpl.java
@@ -45,7 +45,7 @@ import jdk.incubator.foreign.MemorySegment;
  */
 final class NonNativeWritableBufferImpl extends BaseWritableBufferImpl {
 
-  //Pass-through ctor
+  //All non-native endian, read-only and writable Buffer instances start 
initialization here
   NonNativeWritableBufferImpl(
       final MemorySegment seg,
       final int typeId,
diff --git 
a/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImpl.java
 
b/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImpl.java
index c699e8e..ba5b478 100644
--- 
a/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImpl.java
+++ 
b/src/main/java/org/apache/datasketches/memory/internal/NonNativeWritableMemoryImpl.java
@@ -44,7 +44,7 @@ import jdk.incubator.foreign.MemorySegment;
  */
 final class NonNativeWritableMemoryImpl extends BaseWritableMemoryImpl {
 
-  //Pass-through ctor
+  //All non-native endian, read-only and writable Memory instances start 
initialization here
   NonNativeWritableMemoryImpl(
       final MemorySegment seg,
       final int typeId,


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


Reply via email to