Skip to content

Commit fe21452

Browse files
authored
Merge pull request #249 from apache/changes_in_main_tree
Changes to correct issues in 5.0.0
2 parents faec966 + c354c48 commit fe21452

23 files changed

+188
-319
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ under the License.
3434

3535
<groupId>org.apache.datasketches</groupId>
3636
<artifactId>datasketches-memory</artifactId>
37-
<version>5.0.0-SNAPSHOT</version>
37+
<version>5.1.0-SNAPSHOT</version>
3838
<packaging>jar</packaging>
3939

4040
<name>${project.artifactId}</name>

src/main/java/org/apache/datasketches/memory/DefaultMemoryRequestServer.java

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -24,72 +24,42 @@
2424

2525
/**
2626
* This example MemoryRequestServer is simple but demonstrates one of many ways to
27-
* manage continuous requests for larger memory.
27+
* manage continuous requests for larger or smaller memory.
2828
* This capability is only available for writable, non-file-memory-mapping resources.
2929
*
3030
* @author Lee Rhodes
3131
*/
3232
public final class DefaultMemoryRequestServer implements MemoryRequestServer {
33-
private final boolean offHeap; //create the new memory off-heap; otherwise, on-heap
34-
private final boolean copyOldToNew; //copy data from old memory to new memory.
3533

3634
/**
3735
* Default constructor.
38-
* Create new memory on-heap and do not copy old contents to new memory.
3936
*/
40-
public DefaultMemoryRequestServer() {
41-
this(false, false);
42-
}
43-
44-
/**
45-
* Constructor with parameters
46-
* @param offHeap if true, the returned new memory will be off heap
47-
* @param copyOldToNew if true, the data from the current memory will be copied to the new memory,
48-
* starting at address 0, and through the currentMemory capacity.
49-
*/
50-
public DefaultMemoryRequestServer(
51-
final boolean offHeap,
52-
final boolean copyOldToNew) {
53-
this.offHeap = offHeap;
54-
this.copyOldToNew = copyOldToNew;
55-
}
37+
public DefaultMemoryRequestServer() { }
5638

5739
@Override
5840
public WritableMemory request(
59-
final WritableMemory currentWmem,
6041
final long newCapacityBytes,
42+
final long alignmentBytes,
43+
final ByteOrder byteOrder,
6144
final Arena arena) {
62-
final ByteOrder order = currentWmem.getTypeByteOrder();
63-
final long currentBytes = currentWmem.getCapacity();
6445
final WritableMemory newWmem;
6546

66-
if (newCapacityBytes <= currentBytes) {
67-
throw new IllegalArgumentException("newCapacityBytes must be &gt; currentBytes");
68-
}
69-
70-
if (offHeap) {
71-
newWmem = WritableMemory.allocateDirect(newCapacityBytes, 8, order, this, arena);
47+
if (arena != null) {
48+
newWmem = WritableMemory.allocateDirect(newCapacityBytes, alignmentBytes, byteOrder, this, arena);
7249
}
7350
else { //On-heap
7451
if (newCapacityBytes > Integer.MAX_VALUE) {
7552
throw new IllegalArgumentException("Requested capacity exceeds Integer.MAX_VALUE.");
7653
}
77-
newWmem = WritableMemory.allocate((int)newCapacityBytes, order, this);
78-
}
79-
80-
if (copyOldToNew) {
81-
currentWmem.copyTo(0, newWmem, 0, currentBytes);
54+
newWmem = WritableMemory.allocate((int)newCapacityBytes, byteOrder, this);
8255
}
8356

8457
return newWmem;
8558
}
8659

8760
@Override
88-
public void requestClose(
89-
final WritableMemory memToClose,
90-
final WritableMemory newMemory) {
91-
//try to make this operation idempotent.
92-
if (memToClose.isCloseable()) { memToClose.close(); }
61+
public void requestClose(final Arena arena) {
62+
if (arena.scope().isAlive()) { arena.close(); }
9363
}
9464

9565
}

src/main/java/org/apache/datasketches/memory/MemoryRequestServer.java

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@
2020
package org.apache.datasketches.memory;
2121

2222
import java.lang.foreign.Arena;
23+
import java.nio.ByteOrder;
2324

2425
/**
25-
* The MemoryRequestServer is a callback interface to provide a means to request more memory
26+
* The MemoryRequestServer is a callback interface to provide a means to request more or less memory
2627
* for heap and off-heap WritableMemory resources that are not file-memory-mapped backed resources.
2728
*
2829
* <p>Note: this only works with Java 21.
@@ -32,53 +33,26 @@
3233
public interface MemoryRequestServer {
3334

3435
/**
35-
* Request new WritableMemory with the given newCapacityBytes. The current WritableMemory can be used to
36-
* determine the byte order of the returned WritableMemory and other properties. A new confined Arena is
37-
* assigned.
38-
* @param currentWritableMemory the current writableMemory of the client. It must be non-null.
39-
* @param newCapacityBytes The capacity being requested. It must be &gt; the capacity of the currentWritableMemory.
40-
* @return new WritableMemory with the requested capacity.
41-
*/
42-
default WritableMemory request(
43-
WritableMemory currentWritableMemory,
44-
long newCapacityBytes) {
45-
46-
return request(currentWritableMemory, newCapacityBytes, Arena.ofConfined());
47-
}
48-
49-
/**
50-
* Request new WritableMemory with the given newCapacityBytes. The current Writable Memory can be used to
51-
* determine the byte order of the returned WritableMemory and other properties.
52-
* @param currentWritableMemory the current writableMemory of the client. It must be non-null.
53-
* @param newCapacityBytes The capacity being requested. It must be &gt; the capacity of the currentWritableMemory.
54-
* @param arena the Arena to be used for the newly allocated memory. It must be non-null.
36+
* Request new WritableMemory with the given newCapacityBytes.
37+
* @param newCapacityBytes The capacity being requested.
38+
* @param alignmentBytes requested segment alignment. Typically 1, 2, 4 or 8.
39+
* @param byteOrder the given <i>ByteOrder</i>. It must be non-null.
40+
* @param arena the given arena to manage the new off-heap WritableMemory.
41+
* If arena is null, the requested WritableMemory will be off-heap.
5542
* Warning: This class is not thread-safe. Specifying an Arena that allows multiple threads is not recommended.
5643
* @return new WritableMemory with the requested capacity.
5744
*/
5845
WritableMemory request(
59-
WritableMemory currentWritableMemory,
6046
long newCapacityBytes,
47+
long alignmentBytes,
48+
ByteOrder byteOrder,
6149
Arena arena);
6250

6351
/**
64-
* Request to close the resource, if applicable.
65-
*
66-
* @param memToClose the relevant WritableMemory to be considered for closing. It must be non-null.
67-
*/
68-
default void requestClose(WritableMemory memToClose) {
69-
requestClose(memToClose, null);
70-
}
71-
72-
/**
73-
* Request to close the resource, if applicable.
74-
*
75-
* @param memToClose the relevant WritableMemory to be considered for closing. It must be non-null.
76-
* @param newMemory the newly allocated WritableMemory.
77-
* The newMemory reference is returned from the client for the convenience of the system that
78-
* owns the responsibility of memory allocation. It may be null.
52+
* Request to close the area managing all the related resources, if applicable.
53+
* Be careful when you request to close the given Arena, you may be closing other resources as well.
54+
* @param arena the given arena to use to close all its managed resources.
7955
*/
80-
void requestClose(
81-
WritableMemory memToClose,
82-
WritableMemory newMemory);
56+
void requestClose( Arena arena);
8357

8458
}

src/main/java/org/apache/datasketches/memory/Resource.java

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
package org.apache.datasketches.memory;
2121

2222
import java.lang.foreign.Arena;
23-
import java.lang.foreign.FunctionDescriptor;
24-
import java.lang.foreign.Linker.Option;
2523
import java.lang.foreign.MemorySegment;
2624
import java.lang.foreign.MemorySegment.Scope;
2725
import java.nio.ByteBuffer;
@@ -32,7 +30,7 @@
3230
*
3331
* @author Lee Rhodes
3432
*/
35-
public interface Resource extends AutoCloseable {
33+
public interface Resource {
3634

3735
//MemoryRequestServer logic
3836

@@ -92,32 +90,6 @@ public interface Resource extends AutoCloseable {
9290
*/
9391
ByteBuffer asByteBufferView(ByteOrder order);
9492

95-
/**
96-
* <i>From Java 21 java.lang.foreign.Arena::close():</i>
97-
* Closes this arena. If this method completes normally, the arena scope is no longer {@linkplain Scope#isAlive() alive},
98-
* and all the memory segments associated with it can no longer be accessed. Furthermore, any off-heap region of memory backing the
99-
* segments obtained from this arena are also released.
100-
*
101-
* <p>This operation is not idempotent; that is, closing an already closed arena <em>always</em> results in an
102-
* exception being thrown. This reflects a deliberate design choice: failure to close an arena might reveal a bug
103-
* in the underlying application logic.</p>
104-
*
105-
* <p>If this method completes normally, then {@code java.lang.foreign.Arena.scope().isAlive() == false}.
106-
* Implementations are allowed to throw {@link UnsupportedOperationException} if an explicit close operation is
107-
* not supported.</p>
108-
*
109-
* @see java.lang.foreign.MemorySegment.Scope#isAlive()
110-
*
111-
* @throws IllegalStateException if the arena has already been closed.
112-
* @throws IllegalStateException if a segment associated with this arena is being accessed concurrently, e.g.
113-
* by a {@linkplain java.lang.foreign.Linker#downcallHandle(FunctionDescriptor, Option...) downcall method handle}.
114-
* @throws WrongThreadException if this arena is confined, and this method is called from a thread
115-
* other than the arena's owner thread.
116-
* @throws UnsupportedOperationException if this arena cannot be closed explicitly.
117-
*/
118-
@Override
119-
void close();
120-
12193
/**
12294
* Compares the bytes of this Resource to <i>that</i> Resource.
12395
* Returns <i>(this &lt; that) ? (some negative value) : (this &gt; that) ? (some positive value) : 0;</i>.
@@ -170,6 +142,13 @@ boolean equalTo(
170142
*/
171143
void force();
172144

145+
/**
146+
* Returns the arena used to create this resource and possibly other resources.
147+
* Be careful when you close the returned Arena, you may be closing other resources as well.
148+
* @return the arena used to create this resource and possibly other resources.
149+
*/
150+
Arena getArena();
151+
173152
/**
174153
* Gets the capacity of this object in bytes
175154
* @return the capacity of this object in bytes
@@ -198,13 +177,6 @@ boolean equalTo(
198177
*/
199178
boolean hasByteBuffer();
200179

201-
/**
202-
* Return true if this resource is likely to be closeable, but not guaranteed.
203-
* There is no way to determine if the specific type of Arena is explicitly closeable.
204-
* @return true if this resource is likely to be closeable.
205-
*/
206-
boolean isCloseable();
207-
208180
/**
209181
* Is the underlying resource scope alive?
210182
* @return true, if the underlying resource scope is alive.
@@ -346,10 +318,14 @@ boolean equalTo(
346318
ByteBuffer toByteBuffer(ByteOrder order);
347319

348320
/**
349-
* Returns a copy of the underlying MemorySegment.
350-
* @return a copy of the underlying MemorySegment.
321+
* Returns a copy of the underlying MemorySegment in the given arena.
322+
* @param arena the given arena.
323+
* If the desired result is to be off-heap, the arena must not be null.
324+
* Otherwise, the result will be on-heap.
325+
* @param alignment requested segment alignment. Typically 1, 2, 4 or 8.
326+
* @return a copy of the underlying MemorySegment in the given arena.
351327
*/
352-
MemorySegment toMemorySegment();
328+
MemorySegment toMemorySegment(Arena arena, long alignment);
353329

354330
/**
355331
* Returns a brief description of this object.

src/main/java/org/apache/datasketches/memory/WritableMemory.java

Lines changed: 10 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -73,40 +73,18 @@ static WritableMemory writableWrap(
7373
/**
7474
* Maps the entire given file into native-ordered WritableMemory for write operations with Arena.ofConfined().
7575
* Calling this method is equivalent to calling
76-
* {@link #writableMap(File, long, long, ByteOrder) writableMap(file, 0, file.length(), ByteOrder.nativeOrder())}.
76+
* {@link #writableMap(File, long, long, ByteOrder, Arena) writableMap(file, 0, file.length(), ByteOrder.nativeOrder(), arena)}.
7777
* @param file the given file to map. It must be non-null and writable.
78+
* @param arena the given arena to manage the new off-heap WritableMemory. It must be non-null.
79+
* Warning: This class is not thread-safe. Specifying an Arena that allows multiple threads is not recommended.
7880
* @return a file-mapped WritableMemory
7981
* @throws IllegalArgumentException if file is not readable or not writable.
8082
* @throws IOException if the specified path does not point to an existing file, or if some other I/O error occurs.
8183
* @throws SecurityException If a security manager is installed and it denies an unspecified permission
8284
* required by the implementation.
8385
*/
84-
static WritableMemory writableMap(File file) throws IOException {
85-
return WritableMemoryImpl.wrapMap(file, 0, file.length(), ByteOrder.nativeOrder(), false, Arena.ofConfined());
86-
}
87-
88-
/**
89-
* Maps the specified portion of the given file into Memory for write operations with Arena.ofConfined().
90-
* Calling this method is equivalent to calling
91-
* {@link #writableMap(File, long, long, ByteOrder, Arena)
92-
* writableMap(file, fileOffsetBytes, capacityBytes, ByteOrder, Arena.ofConfined())}.
93-
* @param file the given file to map. It must be non-null with a non-negative length and writable.
94-
* @param fileOffsetBytes the position in the given file in bytes. It must not be negative.
95-
* @param capacityBytes the size of the mapped Memory. It must be &ge; 0.
96-
* @param byteOrder the byte order to be used. It must be non-null.
97-
* @return mapped WritableMemory.
98-
* @throws IllegalArgumentException -- if file is not readable or writable.
99-
* @throws IllegalArgumentException -- if file is not writable.
100-
* @throws IOException - if the specified path does not point to an existing file, or if some other I/O error occurs.
101-
* @throws SecurityException - If a security manager is installed and it denies an unspecified permission
102-
* required by the implementation.
103-
*/
104-
static WritableMemory writableMap(
105-
File file,
106-
long fileOffsetBytes,
107-
long capacityBytes,
108-
ByteOrder byteOrder) throws IOException {
109-
return WritableMemoryImpl.wrapMap(file, fileOffsetBytes, capacityBytes, byteOrder, false, Arena.ofConfined());
86+
static WritableMemory writableMap(File file, Arena arena) throws IOException {
87+
return WritableMemoryImpl.wrapMap(file, 0, file.length(), ByteOrder.nativeOrder(), false, arena);
11088
}
11189

11290
/**
@@ -115,8 +93,9 @@ static WritableMemory writableMap(
11593
* @param fileOffsetBytes the position in the given file in bytes. It must not be negative.
11694
* @param capacityBytes the size of the mapped Memory.
11795
* @param byteOrder the given <i>ByteOrder</i>. It must be non-null.
118-
* @param arena the given arena to map. It must be non-null.
96+
* @param arena the given arena to manage the new off-heap WritableMemory. It must be non-null.
11997
* Warning: This class is not thread-safe. Specifying an Arena that allows multiple threads is not recommended.
98+
*
12099
* @return a file-mapped WritableMemory.
121100
* @throws IllegalArgumentException if file is not readable or not writable.
122101
* @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 @@ static WritableMemory writableMap(
139118
* The allocated memory will be 8-byte aligned.
140119
* Native byte order is assumed.
141120
* A new DefaultMemoryRequestServer() is created.
142-
* A new Arena.ofConfined() is created.
143121
*
144122
* <p><b>NOTE:</b> Native/Direct memory acquired may have garbage in it.
145123
* It is the responsibility of the using application to clear this memory, if required,
146124
* and to call <i>close()</i> when done.</p>
147125
* @param capacityBytes the size of the desired memory in bytes.
148-
* Warning: This class is not thread-safe.
149-
*
150-
* @return WritableMemory for this off-heap, native resource.
151-
*/
152-
static WritableMemory allocateDirect(long capacityBytes) {
153-
return allocateDirect(capacityBytes, 8, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer(), Arena.ofConfined());
154-
}
155-
156-
/**
157-
* Allocates and provides access to capacityBytes directly in native (off-heap) memory.
158-
* The allocated memory will be 8-byte aligned.
159-
* Native byte order is assumed.
160-
* A new DefaultMemoryRequestServer() is created.
161-
*
162-
* <p><b>NOTE:</b> Native/Direct memory acquired may have garbage in it.
163-
* It is the responsibility of the using application to clear this memory, if required,
164-
* and to call <i>close()</i> when done.</p>
165-
* @param capacityBytes the size of the desired memory in bytes.
166-
* @param arena the given arena to use. It must be non-null.
126+
* @param arena the given arena to manage the new off-heap WritableMemory. It must be non-null.
167127
* Warning: This class is not thread-safe. Specifying an Arena that allows multiple threads is not recommended.
168128
*
169-
* @return WritableMemory for this off-heap, native resource.
129+
* @return a WritableMemory for this off-heap resource.
170130
*/
171131
static WritableMemory allocateDirect(long capacityBytes, Arena arena) {
172132
return allocateDirect(capacityBytes, 8, ByteOrder.nativeOrder(), new DefaultMemoryRequestServer(), arena);
@@ -184,7 +144,7 @@ static WritableMemory allocateDirect(long capacityBytes, Arena arena) {
184144
* @param byteOrder the given <i>ByteOrder</i>. It must be non-null.
185145
* @param memReqSvr A user-specified MemoryRequestServer, which may be null.
186146
* This is a callback mechanism for a user client of direct memory to request more memory.
187-
* @param arena the given arena to use. It must be non-null.
147+
* @param arena the given arena to manage the new off-heap WritableMemory. It must be non-null.
188148
* Warning: This class is not thread-safe. Specifying an Arena that allows multiple threads is not recommended.
189149
*
190150
* @return a WritableMemory for this off-heap resource.

0 commit comments

Comments
 (0)