This is an automated email from the ASF dual-hosted git repository. leerho pushed a commit to branch changes_in_main_tree in repository https://gitbox.apache.org/repos/asf/datasketches-memory.git
commit d13507b07a9d6803b899ca9e7efe3048b2e113e6 Author: Lee Rhodes <[email protected]> AuthorDate: Thu Jan 23 20:47:40 2025 -0800 Changes in /main/ tree to accommodate the new FFM API in Java 21. --- .../memory/DefaultMemoryRequestServer.java | 45 +++------------- .../datasketches/memory/MemoryRequestServer.java | 53 +++++-------------- .../org/apache/datasketches/memory/Resource.java | 37 +------------ .../apache/datasketches/memory/WritableMemory.java | 60 ++++------------------ .../datasketches/memory/internal/ResourceImpl.java | 17 ------ 5 files changed, 32 insertions(+), 180 deletions(-) diff --git a/src/main/java/org/apache/datasketches/memory/DefaultMemoryRequestServer.java b/src/main/java/org/apache/datasketches/memory/DefaultMemoryRequestServer.java index 0bcbd34..100355d 100644 --- a/src/main/java/org/apache/datasketches/memory/DefaultMemoryRequestServer.java +++ b/src/main/java/org/apache/datasketches/memory/DefaultMemoryRequestServer.java @@ -24,72 +24,43 @@ import java.nio.ByteOrder; /** * This example MemoryRequestServer is simple but demonstrates one of many ways to - * manage continuous requests for larger memory. + * manage continuous requests for larger or smaller memory. * This capability is only available for writable, non-file-memory-mapping resources. * * @author Lee Rhodes */ public final class DefaultMemoryRequestServer implements MemoryRequestServer { - private final boolean offHeap; //create the new memory off-heap; otherwise, on-heap - private final boolean copyOldToNew; //copy data from old memory to new memory. /** * Default constructor. - * Create new memory on-heap and do not copy old contents to new memory. */ public DefaultMemoryRequestServer() { - this(false, false); - } - - /** - * Constructor with parameters - * @param offHeap if true, the returned new memory will be off heap - * @param copyOldToNew if true, the data from the current memory will be copied to the new memory, - * starting at address 0, and through the currentMemory capacity. - */ - public DefaultMemoryRequestServer( - final boolean offHeap, - final boolean copyOldToNew) { - this.offHeap = offHeap; - this.copyOldToNew = copyOldToNew; } @Override public WritableMemory request( - final WritableMemory currentWmem, final long newCapacityBytes, + final long alignmentBytes, + final ByteOrder byteOrder, final Arena arena) { - final ByteOrder order = currentWmem.getTypeByteOrder(); - final long currentBytes = currentWmem.getCapacity(); final WritableMemory newWmem; - if (newCapacityBytes <= currentBytes) { - throw new IllegalArgumentException("newCapacityBytes must be > currentBytes"); - } - - if (offHeap) { - newWmem = WritableMemory.allocateDirect(newCapacityBytes, 8, order, this, arena); + if (arena != null) { + newWmem = WritableMemory.allocateDirect(newCapacityBytes, alignmentBytes, byteOrder, this, arena); } else { //On-heap if (newCapacityBytes > Integer.MAX_VALUE) { throw new IllegalArgumentException("Requested capacity exceeds Integer.MAX_VALUE."); } - newWmem = WritableMemory.allocate((int)newCapacityBytes, order, this); - } - - if (copyOldToNew) { - currentWmem.copyTo(0, newWmem, 0, currentBytes); + newWmem = WritableMemory.allocate((int)newCapacityBytes, byteOrder, this); } return newWmem; } @Override - public void requestClose( - final WritableMemory memToClose, - final WritableMemory newMemory) { - //try to make this operation idempotent. - if (memToClose.isCloseable()) { memToClose.close(); } + public void requestClose(final Arena arena) { + if (arena.scope().isAlive()) { arena.close(); } } } diff --git a/src/main/java/org/apache/datasketches/memory/MemoryRequestServer.java b/src/main/java/org/apache/datasketches/memory/MemoryRequestServer.java index 8a0453a..648a25a 100644 --- a/src/main/java/org/apache/datasketches/memory/MemoryRequestServer.java +++ b/src/main/java/org/apache/datasketches/memory/MemoryRequestServer.java @@ -20,9 +20,10 @@ package org.apache.datasketches.memory; import java.lang.foreign.Arena; +import java.nio.ByteOrder; /** - * The MemoryRequestServer is a callback interface to provide a means to request more memory + * The MemoryRequestServer is a callback interface to provide a means to request more or less memory * for heap and off-heap WritableMemory resources that are not file-memory-mapped backed resources. * * <p>Note: this only works with Java 21. @@ -32,53 +33,25 @@ import java.lang.foreign.Arena; public interface MemoryRequestServer { /** - * Request new WritableMemory with the given newCapacityBytes. The current WritableMemory can be used to - * determine the byte order of the returned WritableMemory and other properties. A new confined Arena is - * assigned. - * @param currentWritableMemory the current writableMemory of the client. It must be non-null. - * @param newCapacityBytes The capacity being requested. It must be > the capacity of the currentWritableMemory. - * @return new WritableMemory with the requested capacity. - */ - default WritableMemory request( - WritableMemory currentWritableMemory, - long newCapacityBytes) { - - return request(currentWritableMemory, newCapacityBytes, Arena.ofConfined()); - } - - /** - * Request new WritableMemory with the given newCapacityBytes. The current Writable Memory can be used to - * determine the byte order of the returned WritableMemory and other properties. - * @param currentWritableMemory the current writableMemory of the client. It must be non-null. - * @param newCapacityBytes The capacity being requested. It must be > the capacity of the currentWritableMemory. - * @param arena the Arena to be used for the newly allocated memory. It must be non-null. + * Request new WritableMemory with the given newCapacityBytes. + * @param newCapacityBytes The capacity being requested. + * @param alignmentBytes requested segment alignment. Typically 1, 2, 4 or 8. + * @param byteOrder the given <i>ByteOrder</i>. It must be non-null. + * @param arena the given arena to manage the new off-heap WritableMemory. + * If arena is null, the requested WritableMemory will be off-heap. * Warning: This class is not thread-safe. Specifying an Arena that allows multiple threads is not recommended. * @return new WritableMemory with the requested capacity. */ WritableMemory request( - WritableMemory currentWritableMemory, long newCapacityBytes, + long alignmentBytes, + ByteOrder byteOrder, Arena arena); /** - * Request to close the resource, if applicable. - * - * @param memToClose the relevant WritableMemory to be considered for closing. It must be non-null. - */ - default void requestClose(WritableMemory memToClose) { - requestClose(memToClose, null); - } - - /** - * Request to close the resource, if applicable. - * - * @param memToClose the relevant WritableMemory to be considered for closing. It must be non-null. - * @param newMemory the newly allocated WritableMemory. - * The newMemory reference is returned from the client for the convenience of the system that - * owns the responsibility of memory allocation. It may be null. + * Request to close the area managing all the related resources, if applicable. + * @param arena the given arena to use to close all its managed resources. */ - void requestClose( - WritableMemory memToClose, - WritableMemory newMemory); + void requestClose( Arena arena); } diff --git a/src/main/java/org/apache/datasketches/memory/Resource.java b/src/main/java/org/apache/datasketches/memory/Resource.java index 3dcdfef..3306bcb 100644 --- a/src/main/java/org/apache/datasketches/memory/Resource.java +++ b/src/main/java/org/apache/datasketches/memory/Resource.java @@ -20,8 +20,6 @@ package org.apache.datasketches.memory; import java.lang.foreign.Arena; -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.Linker.Option; import java.lang.foreign.MemorySegment; import java.lang.foreign.MemorySegment.Scope; import java.nio.ByteBuffer; @@ -32,7 +30,7 @@ import java.nio.ByteOrder; * * @author Lee Rhodes */ -public interface Resource extends AutoCloseable { +public interface Resource { //MemoryRequestServer logic @@ -92,32 +90,6 @@ public interface Resource extends AutoCloseable { */ ByteBuffer asByteBufferView(ByteOrder order); - /** - * <i>From Java 21 java.lang.foreign.Arena::close():</i> - * Closes this arena. If this method completes normally, the arena scope is no longer {@linkplain Scope#isAlive() alive}, - * and all the memory segments associated with it can no longer be accessed. Furthermore, any off-heap region of memory backing the - * segments obtained from this arena are also released. - * - * <p>This operation is not idempotent; that is, closing an already closed arena <em>always</em> results in an - * exception being thrown. This reflects a deliberate design choice: failure to close an arena might reveal a bug - * in the underlying application logic.</p> - * - * <p>If this method completes normally, then {@code java.lang.foreign.Arena.scope().isAlive() == false}. - * Implementations are allowed to throw {@link UnsupportedOperationException} if an explicit close operation is - * not supported.</p> - * - * @see java.lang.foreign.MemorySegment.Scope#isAlive() - * - * @throws IllegalStateException if the arena has already been closed. - * @throws IllegalStateException if a segment associated with this arena is being accessed concurrently, e.g. - * by a {@linkplain java.lang.foreign.Linker#downcallHandle(FunctionDescriptor, Option...) downcall method handle}. - * @throws WrongThreadException if this arena is confined, and this method is called from a thread - * other than the arena's owner thread. - * @throws UnsupportedOperationException if this arena cannot be closed explicitly. - */ - @Override - void close(); - /** * Compares the bytes of this Resource to <i>that</i> Resource. * Returns <i>(this < that) ? (some negative value) : (this > that) ? (some positive value) : 0;</i>. @@ -198,13 +170,6 @@ public interface Resource extends AutoCloseable { */ boolean hasByteBuffer(); - /** - * Return true if this resource is likely to be closeable, but not guaranteed. - * There is no way to determine if the specific type of Arena is explicitly closeable. - * @return true if this resource is likely to be closeable. - */ - boolean isCloseable(); - /** * Is the underlying resource scope alive? * @return true, if the underlying resource scope is alive. diff --git a/src/main/java/org/apache/datasketches/memory/WritableMemory.java b/src/main/java/org/apache/datasketches/memory/WritableMemory.java index 7395ec6..23d0ba0 100644 --- a/src/main/java/org/apache/datasketches/memory/WritableMemory.java +++ b/src/main/java/org/apache/datasketches/memory/WritableMemory.java @@ -73,40 +73,18 @@ public interface WritableMemory extends Memory { /** * Maps the entire given file into native-ordered WritableMemory for write operations with Arena.ofConfined(). * Calling this method is equivalent to calling - * {@link #writableMap(File, long, long, ByteOrder) writableMap(file, 0, file.length(), ByteOrder.nativeOrder())}. + * {@link #writableMap(File, long, long, ByteOrder, Arena) writableMap(file, 0, file.length(), ByteOrder.nativeOrder(), arena)}. * @param file the given file to map. It must be non-null and writable. + * @param arena the given arena to manage the new off-heap WritableMemory. It must be non-null. + * Warning: This class is not thread-safe. Specifying an Arena that allows multiple threads is not recommended. * @return a file-mapped WritableMemory * @throws IllegalArgumentException if file is not readable or not writable. * @throws IOException if the specified path does not point to an existing file, or if some other I/O error occurs. * @throws SecurityException If a security manager is installed and it denies an unspecified permission * required by the implementation. */ - static WritableMemory writableMap(File file) throws IOException { - return WritableMemoryImpl.wrapMap(file, 0, file.length(), ByteOrder.nativeOrder(), false, Arena.ofConfined()); - } - - /** - * Maps the specified portion of the given file into Memory for write operations with Arena.ofConfined(). - * Calling this method is equivalent to calling - * {@link #writableMap(File, long, long, ByteOrder, Arena) - * writableMap(file, fileOffsetBytes, capacityBytes, ByteOrder, Arena.ofConfined())}. - * @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 ≥ 0. - * @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. - * @throws IllegalArgumentException -- if file is not writable. - * @throws IOException - if the specified path does not point to an existing file, or if some other I/O error occurs. - * @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, - ByteOrder byteOrder) throws IOException { - return WritableMemoryImpl.wrapMap(file, fileOffsetBytes, capacityBytes, byteOrder, false, Arena.ofConfined()); + static WritableMemory writableMap(File file, Arena arena) throws IOException { + return WritableMemoryImpl.wrapMap(file, 0, file.length(), ByteOrder.nativeOrder(), false, arena); } /** @@ -115,8 +93,9 @@ public interface WritableMemory extends Memory { * @param fileOffsetBytes the position in the given file in bytes. It must not be negative. * @param capacityBytes the size of the mapped Memory. * @param byteOrder the given <i>ByteOrder</i>. It must be non-null. - * @param arena the given arena to map. It must be non-null. + * @param arena the given arena to manage the new off-heap WritableMemory. It must be non-null. * Warning: This class is not thread-safe. Specifying an Arena that allows multiple threads is not recommended. + * * @return a file-mapped WritableMemory. * @throws IllegalArgumentException if file is not readable or not writable. * @throws IOException if the specified path does not point to an existing file, or if some other I/O error occurs. @@ -139,34 +118,15 @@ public interface WritableMemory extends Memory { * The allocated memory will be 8-byte aligned. * Native byte order is assumed. * A new DefaultMemoryRequestServer() is created. - * A new Arena.ofConfined() is created. * * <p><b>NOTE:</b> Native/Direct memory acquired may have garbage in it. * It is the responsibility of the using application to clear this memory, if required, * and to call <i>close()</i> when done.</p> * @param capacityBytes the size of the desired memory in bytes. - * Warning: This class is not thread-safe. - * - * @return WritableMemory for this off-heap, native resource. - */ - static WritableMemory allocateDirect(long capacityBytes) { - return allocateDirect(capacityBytes, 8, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer(), Arena.ofConfined()); - } - - /** - * Allocates and provides access to capacityBytes directly in native (off-heap) memory. - * The allocated memory will be 8-byte aligned. - * Native byte order is assumed. - * A new DefaultMemoryRequestServer() is created. - * - * <p><b>NOTE:</b> Native/Direct memory acquired may have garbage in it. - * It is the responsibility of the using application to clear this memory, if required, - * and to call <i>close()</i> when done.</p> - * @param capacityBytes the size of the desired memory in bytes. - * @param arena the given arena to use. It must be non-null. + * @param arena the given arena to manage the new off-heap WritableMemory. It must be non-null. * Warning: This class is not thread-safe. Specifying an Arena that allows multiple threads is not recommended. * - * @return WritableMemory for this off-heap, native resource. + * @return a WritableMemory for this off-heap resource. */ static WritableMemory allocateDirect(long capacityBytes, Arena arena) { return allocateDirect(capacityBytes, 8, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer(), arena); @@ -184,7 +144,7 @@ public interface WritableMemory extends Memory { * @param byteOrder the given <i>ByteOrder</i>. 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. - * @param arena the given arena to use. It must be non-null. + * @param arena the given arena to manage the new off-heap WritableMemory. It must be non-null. * Warning: This class is not thread-safe. Specifying an Arena that allows multiple threads is not recommended. * * @return a WritableMemory for this off-heap resource. diff --git a/src/main/java/org/apache/datasketches/memory/internal/ResourceImpl.java b/src/main/java/org/apache/datasketches/memory/internal/ResourceImpl.java index 3d86ac0..46e1b18 100644 --- a/src/main/java/org/apache/datasketches/memory/internal/ResourceImpl.java +++ b/src/main/java/org/apache/datasketches/memory/internal/ResourceImpl.java @@ -358,18 +358,6 @@ abstract class ResourceImpl implements Resource { return byteBuffer; } - @Override - public void close() { - if (arena != null) { - try { - arena.close(); - } - catch (final UnsupportedOperationException uoe) { - // ignored as it seems there's no reliable way to determine if the Arena is closeable or not - } - } //not idempotent - } - @Override public final int compareTo(final long thisOffsetBytes, final long thisLengthBytes, final Resource that, final long thatOffsetBytes, final long thatLengthBytes) { @@ -424,11 +412,6 @@ abstract class ResourceImpl implements Resource { return typeBO == ByteOrder.nativeOrder() && typeBO == byteOrder; } - @Override - public boolean isCloseable() { - return ((seg.isNative() || seg.isMapped()) && seg.scope().isAlive()); - } - @Override public final boolean isDirect() { assert seg.isNative() == (typeId & DIRECT) > 0; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
