Skip to content

Commit

Permalink
Merge branch 'main' into target_is_6.0.X
Browse files Browse the repository at this point in the history
  • Loading branch information
leerho committed Feb 18, 2025
2 parents 8bab1da + 36b980a commit 0a4d369
Show file tree
Hide file tree
Showing 14 changed files with 294 additions and 1,109 deletions.
11 changes: 2 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,6 @@ under the License.

<modelVersion>4.0.0</modelVersion>

<!--
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>32</version>
</parent> -->

<groupId>org.apache.datasketches</groupId>
<artifactId>datasketches-memory</artifactId>
<version>6.0.0</version>
Expand Down Expand Up @@ -85,7 +78,7 @@ under the License.

<properties>
<!-- Test -->
<testng.version>7.10.2</testng.version>
<testng.version>7.11.0</testng.version>

<!-- System-wide properties -->
<maven.version>3.6.3</maven.version>
Expand Down Expand Up @@ -189,7 +182,7 @@ under the License.
<configuration>
<rules>
<requireJavaVersion>
<version>${java.version}</version>
<version>${java.version},</version>
</requireJavaVersion>
<requireMavenVersion>
<version>[${maven.version},4.0.0)</version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,39 +27,121 @@
* manage continuous requests for larger or smaller memory.
* This capability is only available for writable, non-file-memory-mapping resources.
*
* <p>The operation of this implementation is controlled by three conditions:</p>
* <ul>
* <li><b><i>origOffHeap:</i></b> If <i>true</i>, the originally allocated WritableMemory is off-heap.</li>
*
* <li><b><i>oneArena:</i></b> If <i>true</i>, all subsequent off-heap allocations will use the same Arena
* obtained from the original off-heap WritableMemory. Otherwise, subsequent off-heap allocations will
* use a new confined Arena created by this implementation.</li>
*
* <li><b><i>offHeap:</i></b> If <i>true</i>, all subsequent allocations will be off-heap.
* If the originally allocated WritableMemory is on-heap, this variable is ignored.</li>
* </ul>
*
* <p>These three variables work together as follows:</p>
*
* <ul>
* <li>If the original WritableMemory is on-heap, all subsequent allocations will also be on-heap.</li>
*
* <li>If <i>origOffHeap</i> = <i>true</i>, <i>oneArena</i> = <i>true</i>, and <i>offHeap</i> = <i>true</i>,
* all subsequent allocations will also be off-heap and associated with the original Arena.
* It is the responsibility of the user to close the original Arena using a Try-With-Resource block, or directly.</li>
*
* <li>If the original WritableMemory is off-heap, <i>oneArena</i> is true, and <i>offHeap</i> is false,
* all subsequent allocations will be on-heap.
* It is the responsibility of the user to close the original Arena using a Try-With-Resource block, or directly.</li>
*
* <li>If the original WritableMemory is off-heap, <i>oneArena</i> is false, and <i>offHeap</i> is true,
* all subsequent allocations will also be off-heap and associated with a new confined Arena assigned by this implementation.
* It is the responsibility of the user to close the original Arena using a Try-With-Resource block, or directly,
* and close the last returned new WritableMemory directly.</li>
* </ul>
*
* <p>In summary:</p>
*
* <table> <caption><b>Configuration Options</b></caption>
* <tr><th>Original Off-Heap</th> <th>OneArena</th> <th>OffHeap</th> <th>Subsequent Allocations</th></tr>
* <tr><td>false</td> <td>N/A</td> <td>N/A</td> <td>All on-heap</td></tr>
* <tr><td>true</td> <td>N/A</td> <td>false</td> <td>All on-heap</td></tr>
* <tr><td>true</td> <td>true</td> <td>true</td> <td>All off-heap in original Arena</td></tr>
* <tr><td>true</td> <td>false</td> <td>true</td> <td>All off-heap in separate Arenas</td></tr>
* </table>
*
* @author Lee Rhodes
*/
@SuppressWarnings("resource") //can't use TWRs here
public final class DefaultMemoryRequestServer implements MemoryRequestServer {
private final long alignmentBytes;
private final ByteOrder byteOrder;
private final boolean oneArena;
private final boolean offHeap;

/**
* Default constructor.
*/
public DefaultMemoryRequestServer() { }
public DefaultMemoryRequestServer() {
alignmentBytes = 8;
byteOrder = ByteOrder.nativeOrder();
oneArena = false;
offHeap = false;
}

@Override
public WritableMemory request(
final long newCapacityBytes,
/**
* Optional constructor 1.
* @param oneArena if true, the original arena will be used for all requested allocations.
* @param offHeap if true, new allocations will be off-heap.
*/
public DefaultMemoryRequestServer(
final boolean oneArena,
final boolean offHeap) {
this.alignmentBytes = 8;
this.byteOrder = ByteOrder.nativeOrder();
this.oneArena = oneArena;
this.offHeap = offHeap;
}

/**
* Optional constructor 2.
* @param alignmentBytes requested segment alignment for all allocations. Typically 1, 2, 4 or 8.
* @param byteOrder the given <i>ByteOrder</i>. It must be non-null.
* @param oneArena if true, the same arena will be used for all requested allocations.
* @param offHeap if true, new allocations will be off-heap.
*/
public DefaultMemoryRequestServer(
final long alignmentBytes,
final ByteOrder byteOrder,
final Arena arena) {
final WritableMemory newWmem;
final boolean oneArena,
final boolean offHeap) {
this.alignmentBytes = alignmentBytes;
this.byteOrder = byteOrder;
this.oneArena = oneArena;
this.offHeap = offHeap;
}

if (arena != null) {
newWmem = WritableMemory.allocateDirect(newCapacityBytes, alignmentBytes, byteOrder, this, arena);
}
else { //On-heap
@Override
public WritableMemory request(
final WritableMemory oldWmem,
final long newCapacityBytes) {

//On-heap
if (oldWmem.getArena() == null || !offHeap) {
if (newCapacityBytes > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Requested capacity exceeds Integer.MAX_VALUE.");
}
newWmem = WritableMemory.allocate((int)newCapacityBytes, byteOrder, this);
return WritableMemory.allocate((int)newCapacityBytes, byteOrder, this);
}

return newWmem;
//Acquire Arena
final Arena arena = (oneArena) ? oldWmem.getArena() : Arena.ofConfined();
return WritableMemory.allocateDirect(newCapacityBytes, alignmentBytes, byteOrder, this, arena);
}

@Override
public void requestClose(final Arena arena) {
if (arena.scope().isAlive()) { arena.close(); }
public void requestClose(final WritableMemory wmemToClose) {
final Arena arena = wmemToClose.getArena();
if (oneArena || arena == null || !arena.scope().isAlive()) { return; } //can't close
arena.close();
}

}
14 changes: 7 additions & 7 deletions src/main/java/org/apache/datasketches/memory/Memory.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ static Memory wrap(
int lengthBytes,
ByteOrder byteOrder) {
final MemorySegment slice = MemorySegment.ofArray(array).asSlice(offsetBytes, lengthBytes).asReadOnly();
return WritableMemoryImpl.wrapSegmentAsArray(slice, byteOrder, null);
return WritableMemoryImpl.wrapSegment(slice, byteOrder);
}

//intentionally removed wrap(boolean[])
Expand All @@ -234,7 +234,7 @@ static Memory wrap(
*/
static Memory wrap(char[] array) {
final MemorySegment seg = MemorySegment.ofArray(array).asReadOnly();
return WritableMemoryImpl.wrapSegmentAsArray(seg, ByteOrder.nativeOrder(), null);
return WritableMemoryImpl.wrapSegment(seg, ByteOrder.nativeOrder());
}

/**
Expand All @@ -244,7 +244,7 @@ static Memory wrap(char[] array) {
*/
static Memory wrap(short[] array) {
final MemorySegment seg = MemorySegment.ofArray(array).asReadOnly();
return WritableMemoryImpl.wrapSegmentAsArray(seg, ByteOrder.nativeOrder(), null);
return WritableMemoryImpl.wrapSegment(seg, ByteOrder.nativeOrder());
}

/**
Expand All @@ -254,7 +254,7 @@ static Memory wrap(short[] array) {
*/
static Memory wrap(int[] array) {
final MemorySegment seg = MemorySegment.ofArray(array).asReadOnly();
return WritableMemoryImpl.wrapSegmentAsArray(seg, ByteOrder.nativeOrder(), null);
return WritableMemoryImpl.wrapSegment(seg, ByteOrder.nativeOrder());
}

/**
Expand All @@ -264,7 +264,7 @@ static Memory wrap(int[] array) {
*/
static Memory wrap(long[] array) {
final MemorySegment seg = MemorySegment.ofArray(array).asReadOnly();
return WritableMemoryImpl.wrapSegmentAsArray(seg, ByteOrder.nativeOrder(), null);
return WritableMemoryImpl.wrapSegment(seg, ByteOrder.nativeOrder());
}

/**
Expand All @@ -274,7 +274,7 @@ static Memory wrap(long[] array) {
*/
static Memory wrap(float[] array) {
final MemorySegment seg = MemorySegment.ofArray(array).asReadOnly();
return WritableMemoryImpl.wrapSegmentAsArray(seg, ByteOrder.nativeOrder(), null);
return WritableMemoryImpl.wrapSegment(seg, ByteOrder.nativeOrder());
}

/**
Expand All @@ -284,7 +284,7 @@ static Memory wrap(float[] array) {
*/
static Memory wrap(double[] array) {
final MemorySegment seg = MemorySegment.ofArray(array).asReadOnly();
return WritableMemoryImpl.wrapSegmentAsArray(seg, ByteOrder.nativeOrder(), null);
return WritableMemoryImpl.wrapSegment(seg, ByteOrder.nativeOrder());
}
//END OF CONSTRUCTOR-TYPE METHODS

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@

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 or less memory
* for heap and off-heap WritableMemory resources that are not file-memory-mapped backed resources.
Expand All @@ -33,26 +30,21 @@
public interface MemoryRequestServer {

/**
* Request new WritableMemory with the given newCapacityBytes.
* Request a new WritableMemory with the given newCapacityBytes.
* @param oldWmem the previous WritableMemory to be possibly closed and which provides an associated Arena
* that may be used for allocating the new WritableMemory.
* If the arena is null, the requested WritableMemory will be on-heap.
* @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 on-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(
long newCapacityBytes,
long alignmentBytes,
ByteOrder byteOrder,
Arena arena);
WritableMemory request(WritableMemory oldWmem, long newCapacityBytes);

/**
* Request to close the area managing all the related resources, if applicable.
* Be careful when you request to close the given Arena, you may be closing other resources as well.
* @param arena the given arena to use to close all its managed resources.
* Request to close the given WritableMemory. If applicable, it will be closed by its associated Arena.
* Be careful. Closing the associated Arena may be closing other resources as well.
* @param wmemToClose the given WritableMemory to close.
*/
void requestClose( Arena arena);
void requestClose(WritableMemory wmemToClose);

}
Loading

0 comments on commit 0a4d369

Please sign in to comment.