mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-28 19:20:33 +00:00
8278433: Use snippets in jdk.incubator.foreign documentation
Reviewed-by: mcimadamore
This commit is contained in:
parent
1ea766db55
commit
84baea753a
@ -181,9 +181,9 @@ public sealed interface CLinker extends SymbolLookup permits Windowsx64Linker, S
|
||||
* to allocate structs returned by-value.
|
||||
* <p>
|
||||
* Calling this method is equivalent to the following code:
|
||||
<blockquote><pre>{@code
|
||||
linker.downcallHandle(function).bindTo(symbol);
|
||||
}</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* linker.downcallHandle(function).bindTo(symbol);
|
||||
* }
|
||||
*
|
||||
* @param symbol downcall symbol.
|
||||
* @param function the function descriptor.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -46,17 +46,17 @@ import java.nio.ByteOrder;
|
||||
* Each dereference method takes a {@linkplain jdk.incubator.foreign.ValueLayout value layout}, which specifies the size,
|
||||
* alignment constraints, byte order as well as the Java type associated with the dereference operation, and an offset.
|
||||
* For instance, to read an int from a segment, using {@link ByteOrder#nativeOrder() default endianness}, the following code can be used:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryAddress address = ...
|
||||
int value = address.get(ValueLayout.JAVA_INT, 0);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryAddress address = ...
|
||||
* int value = address.get(ValueLayout.JAVA_INT, 0);
|
||||
* }
|
||||
*
|
||||
* If the value to be read is stored in memory using {@link ByteOrder#BIG_ENDIAN big-endian} encoding, the dereference operation
|
||||
* can be expressed as follows:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryAddress address = ...
|
||||
int value = address.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryAddress address = ...
|
||||
* int value = address.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0);
|
||||
* }
|
||||
*
|
||||
* All the dereference methods in this class are <a href="package-summary.html#restricted"><em>restricted</em></a>: since
|
||||
* a memory address does not feature temporal nor spatial bounds, the runtime has no way to check the correctness
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -47,17 +47,17 @@ import java.util.Objects;
|
||||
* to the segment, at which dereference should occur.
|
||||
* <p>
|
||||
* As an example, consider the memory layout expressed by a {@link GroupLayout} instance constructed as follows:
|
||||
* <blockquote><pre>{@code
|
||||
GroupLayout seq = MemoryLayout.structLayout(
|
||||
MemoryLayout.paddingLayout(32),
|
||||
ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value")
|
||||
);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* GroupLayout seq = MemoryLayout.structLayout(
|
||||
* MemoryLayout.paddingLayout(32),
|
||||
* ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value")
|
||||
* );
|
||||
* }
|
||||
* To access the member layout named {@code value}, we can construct a memory access var handle as follows:
|
||||
* <blockquote><pre>{@code
|
||||
VarHandle handle = MemoryHandles.varHandle(ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); //(MemorySegment, long) -> int
|
||||
handle = MemoryHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* VarHandle handle = MemoryHandles.varHandle(ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); //(MemorySegment, long) -> int
|
||||
* handle = MemoryHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int
|
||||
* }
|
||||
*
|
||||
* <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
|
||||
* elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
|
||||
@ -177,13 +177,13 @@ public final class MemoryHandles {
|
||||
* example, it is often convenient to model an <i>unsigned short</i> as a
|
||||
* Java {@code int} to avoid dealing with negative values, which would be
|
||||
* the case if modeled as a Java {@code short}. This is illustrated in the following example:
|
||||
* <blockquote><pre>{@code
|
||||
MemorySegment segment = MemorySegment.allocateNative(2, ResourceScope.newImplicitScope());
|
||||
VarHandle SHORT_VH = ValueLayout.JAVA_SHORT.varHandle();
|
||||
VarHandle INT_VH = MemoryHandles.asUnsigned(SHORT_VH, int.class);
|
||||
SHORT_VH.set(segment, (short)-1);
|
||||
INT_VH.get(segment); // returns 65535
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemorySegment segment = MemorySegment.allocateNative(2, ResourceScope.newImplicitScope());
|
||||
* VarHandle SHORT_VH = ValueLayout.JAVA_SHORT.varHandle();
|
||||
* VarHandle INT_VH = MemoryHandles.asUnsigned(SHORT_VH, int.class);
|
||||
* SHORT_VH.set(segment, (short)-1);
|
||||
* INT_VH.get(segment); // returns 65535
|
||||
* }
|
||||
* <p>
|
||||
* When calling e.g. {@link VarHandle#set(Object...)} on the resulting var
|
||||
* handle, the incoming value (of type {@code adaptedType}) is converted by a
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -58,24 +58,24 @@ import java.util.stream.Stream;
|
||||
* <p>
|
||||
* For instance, consider the following struct declaration in C:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
typedef struct {
|
||||
char kind;
|
||||
int value;
|
||||
} TaggedValues[5];
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=c :
|
||||
* typedef struct {
|
||||
* char kind;
|
||||
* int value;
|
||||
* } TaggedValues[5];
|
||||
* }
|
||||
*
|
||||
* The above declaration can be modelled using a layout object, as follows:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5,
|
||||
MemoryLayout.structLayout(
|
||||
ValueLayout.JAVA_BYTE.withName("kind"),
|
||||
MemoryLayout.paddingLayout(24),
|
||||
ValueLayout.JAVA_INT.withName("value")
|
||||
)
|
||||
).withName("TaggedValues");
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5,
|
||||
* MemoryLayout.structLayout(
|
||||
* ValueLayout.JAVA_BYTE.withName("kind"),
|
||||
* MemoryLayout.paddingLayout(24),
|
||||
* ValueLayout.JAVA_INT.withName("value")
|
||||
* )
|
||||
* ).withName("TaggedValues");
|
||||
* }
|
||||
* <p>
|
||||
* All implementations of this interface must be <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>;
|
||||
* programmers should treat instances that are {@linkplain #equals(Object) equal} as interchangeable and should not
|
||||
@ -129,42 +129,42 @@ SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5,
|
||||
* Such <em>layout paths</em> can be constructed programmatically using the methods in this class.
|
||||
* For instance, given the {@code taggedValues} layout instance constructed as above, we can obtain the offset,
|
||||
* in bits, of the member layout named <code>value</code> in the <em>first</em> sequence element, as follows:
|
||||
* <blockquote><pre>{@code
|
||||
long valueOffset = taggedValues.bitOffset(PathElement.sequenceElement(0),
|
||||
PathElement.groupElement("value")); // yields 32
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* long valueOffset = taggedValues.bitOffset(PathElement.sequenceElement(0),
|
||||
* PathElement.groupElement("value")); // yields 32
|
||||
* }
|
||||
*
|
||||
* Similarly, we can select the member layout named {@code value}, as follows:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout value = taggedValues.select(PathElement.sequenceElement(),
|
||||
PathElement.groupElement("value"));
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout value = taggedValues.select(PathElement.sequenceElement(),
|
||||
* PathElement.groupElement("value"));
|
||||
* }
|
||||
*
|
||||
* And, we can also replace the layout named {@code value} with another layout, as follows:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout taggedValuesWithHole = taggedValues.map(l -> MemoryLayout.paddingLayout(32),
|
||||
PathElement.sequenceElement(), PathElement.groupElement("value"));
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout taggedValuesWithHole = taggedValues.map(l -> MemoryLayout.paddingLayout(32),
|
||||
* PathElement.sequenceElement(), PathElement.groupElement("value"));
|
||||
* }
|
||||
*
|
||||
* That is, the above declaration is identical to the following, more verbose one:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout taggedValuesWithHole = MemoryLayout.sequenceLayout(5,
|
||||
MemoryLayout.structLayout(
|
||||
ValueLayout.JAVA_BYTE.withName("kind"),
|
||||
MemoryLayout.paddingLayout(32),
|
||||
MemoryLayout.paddingLayout(32)
|
||||
));
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout taggedValuesWithHole = MemoryLayout.sequenceLayout(5,
|
||||
* MemoryLayout.structLayout(
|
||||
* ValueLayout.JAVA_BYTE.withName("kind"),
|
||||
* MemoryLayout.paddingLayout(32),
|
||||
* MemoryLayout.paddingLayout(32)
|
||||
* ));
|
||||
* }
|
||||
*
|
||||
* Layout paths can feature one or more <em>free dimensions</em>. For instance, a layout path traversing
|
||||
* an unspecified sequence element (that is, where one of the path component was obtained with the
|
||||
* {@link PathElement#sequenceElement()} method) features an additional free dimension, which will have to be bound at runtime.
|
||||
* This is important when obtaining memory access var handle from layouts, as in the following code:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(),
|
||||
PathElement.groupElement("value"));
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(),
|
||||
* PathElement.groupElement("value"));
|
||||
* }
|
||||
*
|
||||
* Since the layout path constructed in the above example features exactly one free dimension (as it doesn't specify
|
||||
* <em>which</em> member layout named {@code value} should be selected from the enclosing sequence layout),
|
||||
@ -177,12 +177,12 @@ VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(),
|
||||
* offsets of elements of a sequence at different indices, by supplying these indices when invoking the method handle.
|
||||
* For instance:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(),
|
||||
PathElement.groupElement("kind"));
|
||||
long offset1 = (long) offsetHandle.invokeExact(1L); // 8
|
||||
long offset2 = (long) offsetHandle.invokeExact(2L); // 16
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(),
|
||||
* PathElement.groupElement("kind"));
|
||||
* long offset1 = (long) offsetHandle.invokeExact(1L); // 8
|
||||
* long offset2 = (long) offsetHandle.invokeExact(2L); // 16
|
||||
* }
|
||||
*
|
||||
* <h2>Layout attributes</h2>
|
||||
*
|
||||
@ -330,7 +330,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S
|
||||
* <p>The final offset returned by the method handle is computed as follows:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
|
||||
* offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* where {@code x_1}, {@code x_2}, ... {@code x_n} are <em>dynamic</em> values provided as {@code long}
|
||||
@ -381,8 +381,8 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S
|
||||
* <p>The final offset returned by the method handle is computed as follows:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
|
||||
offset = bitOffset / 8
|
||||
* bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
|
||||
* offset = bitOffset / 8
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* where {@code x_1}, {@code x_2}, ... {@code x_n} are <em>dynamic</em> values provided as {@code long}
|
||||
@ -413,7 +413,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S
|
||||
* The final memory location accessed by the returned memory access var handle can be computed as follows:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
address = base + offset
|
||||
* address = base + offset
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* where {@code base} denotes the base address expressed by the {@link MemorySegment} access coordinate
|
||||
@ -421,7 +421,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S
|
||||
* can be expressed in the following form:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
|
||||
* offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* where {@code x_1}, {@code x_2}, ... {@code x_n} are <em>dynamic</em> values provided as {@code long}
|
||||
@ -458,8 +458,8 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S
|
||||
* <p>The offset of the returned segment is computed as follows:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
|
||||
offset = bitOffset / 8
|
||||
* bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
|
||||
* offset = bitOffset / 8
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* where {@code x_1}, {@code x_2}, ... {@code x_n} are <em>dynamic</em> values provided as {@code long}
|
||||
@ -468,9 +468,9 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S
|
||||
* the layout path.
|
||||
*
|
||||
* <p>After the offset is computed, the returned segment is created as if by calling:
|
||||
* <blockquote><pre>{@code
|
||||
segment.asSlice(offset, layout.byteSize());
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* segment.asSlice(offset, layout.byteSize());
|
||||
* }
|
||||
*
|
||||
* where {@code segment} is the segment to be sliced, and where {@code layout} is the layout selected by the given
|
||||
* layout path, as per {@link MemoryLayout#select(PathElement...)}.
|
||||
@ -599,7 +599,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S
|
||||
* with this path is bound by an index {@code I}, the resulting accessed offset can be obtained with the following
|
||||
* formula:
|
||||
* <blockquote><pre>{@code
|
||||
E * (S + I * F)
|
||||
* E * (S + I * F)
|
||||
* }</pre></blockquote>
|
||||
* where {@code E} is the size (in bytes) of the sequence element layout.
|
||||
*
|
||||
|
||||
@ -119,17 +119,17 @@ import java.util.stream.Stream;
|
||||
* Each dereference method takes a {@linkplain jdk.incubator.foreign.ValueLayout value layout}, which specifies the size,
|
||||
* alignment constraints, byte order as well as the Java type associated with the dereference operation, and an offset.
|
||||
* For instance, to read an int from a segment, using {@link ByteOrder#nativeOrder() default endianness}, the following code can be used:
|
||||
* <blockquote><pre>{@code
|
||||
MemorySegment segment = ...
|
||||
int value = segment.get(ValueLayout.JAVA_INT, 0);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemorySegment segment = ...
|
||||
* int value = segment.get(ValueLayout.JAVA_INT, 0);
|
||||
* }
|
||||
*
|
||||
* If the value to be read is stored in memory using {@link ByteOrder#BIG_ENDIAN big-endian} encoding, the dereference operation
|
||||
* can be expressed as follows:
|
||||
* <blockquote><pre>{@code
|
||||
MemorySegment segment = ...
|
||||
int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemorySegment segment = ...
|
||||
* int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0);
|
||||
* }
|
||||
*
|
||||
* For more complex dereference operations (e.g. structured memory access), clients can obtain a <em>memory access var handle</em>,
|
||||
* that is, a var handle that accepts a segment and, optionally, one or more additional {@code long} coordinates. Memory
|
||||
@ -145,13 +145,13 @@ int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0);
|
||||
* the {@link #scope()} method. As for all resources associated with a resource scope, a segment cannot be
|
||||
* accessed after its corresponding scope has been closed. For instance, the following code will result in an
|
||||
* exception:
|
||||
* <blockquote><pre>{@code
|
||||
MemorySegment segment = null;
|
||||
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
|
||||
segment = MemorySegment.allocateNative(8, scope);
|
||||
}
|
||||
segment.get(ValueLayout.JAVA_LONG, 0); // already closed!
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemorySegment segment = null;
|
||||
* try (ResourceScope scope = ResourceScope.newConfinedScope()) {
|
||||
* segment = MemorySegment.allocateNative(8, scope);
|
||||
* }
|
||||
* segment.get(ValueLayout.JAVA_LONG, 0); // already closed!
|
||||
* }
|
||||
* Additionally, access to a memory segment is subject to the thread-confinement checks enforced by the owning scope; that is,
|
||||
* if the segment is associated with a shared scope, it can be accessed by multiple threads; if it is associated with a confined
|
||||
* scope, it can only be accessed by the thread which owns the scope.
|
||||
@ -162,10 +162,10 @@ segment.get(ValueLayout.JAVA_LONG, 0); // already closed!
|
||||
* <h2>Memory segment views</h2>
|
||||
*
|
||||
* Memory segments support <em>views</em>. For instance, it is possible to create an <em>immutable</em> view of a memory segment, as follows:
|
||||
* <blockquote><pre>{@code
|
||||
MemorySegment segment = ...
|
||||
MemorySegment roSegment = segment.asReadOnly();
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemorySegment segment = ...
|
||||
* MemorySegment roSegment = segment.asReadOnly();
|
||||
* }
|
||||
* It is also possible to create views whose spatial bounds are stricter than the ones of the original segment
|
||||
* (see {@link MemorySegment#asSlice(long, long)}).
|
||||
* <p>
|
||||
@ -184,15 +184,15 @@ MemorySegment roSegment = segment.asReadOnly();
|
||||
* (to do this, the segment has to be associated with a shared scope). The following code can be used to sum all int
|
||||
* values in a memory segment in parallel:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
try (ResourceScope scope = ResourceScope.newSharedScope()) {
|
||||
SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
|
||||
MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
|
||||
int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
|
||||
.mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
|
||||
.sum();
|
||||
}
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* try (ResourceScope scope = ResourceScope.newSharedScope()) {
|
||||
* SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
|
||||
* MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
|
||||
* int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
|
||||
* .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
|
||||
* .sum();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @implSpec
|
||||
* Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
|
||||
@ -233,9 +233,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
/**
|
||||
* Returns a sequential {@code Stream} over disjoint slices (whose size matches that of the specified layout)
|
||||
* in this segment. Calling this method is equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
StreamSupport.stream(segment.spliterator(elementLayout), false);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* StreamSupport.stream(segment.spliterator(elementLayout), false);
|
||||
* }
|
||||
*
|
||||
* @param elementLayout the layout to be used for splitting.
|
||||
* @return a sequential {@code Stream} over disjoint slices in this segment.
|
||||
@ -274,9 +274,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* and whose new size is computed by subtracting the specified offset from this segment size.
|
||||
* <p>
|
||||
* Equivalent to the following code:
|
||||
* <pre>{@code
|
||||
asSlice(offset, byteSize() - offset);
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* asSlice(offset, byteSize() - offset);
|
||||
* }
|
||||
*
|
||||
* @see #asSlice(long, long)
|
||||
*
|
||||
@ -343,9 +343,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* a negative or positive value. For instance, if both segments are native
|
||||
* segments, the resulting offset can be computed as follows:
|
||||
*
|
||||
* <pre>{@code
|
||||
* {@snippet lang=java :
|
||||
* other.baseAddress().toRawLongValue() - segment.baseAddress().toRawLongValue()
|
||||
* }</pre>
|
||||
* }
|
||||
*
|
||||
* If the segments share the same base address, {@code 0} is returned. If
|
||||
* {@code other} is a slice of this segment, the offset is always
|
||||
@ -362,13 +362,13 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* More specifically, the given value is filled into each address of this
|
||||
* segment. Equivalent to (but likely more efficient than) the following code:
|
||||
*
|
||||
* <pre>{@code
|
||||
byteHandle = MemoryLayout.ofSequence(ValueLayout.JAVA_BYTE)
|
||||
.varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
|
||||
for (long l = 0; l < segment.byteSize(); l++) {
|
||||
byteHandle.set(segment.address(), l, value);
|
||||
}
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* byteHandle = MemoryLayout.ofSequence(ValueLayout.JAVA_BYTE)
|
||||
* .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
|
||||
* for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* byteHandle.set(segment.address(), l, value);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* without any regard or guarantees on the ordering of particular memory
|
||||
* elements being set.
|
||||
@ -389,9 +389,9 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* at offset {@code 0} through {@code src.byteSize() - 1}.
|
||||
* <p>
|
||||
* Calling this method is equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemorySegment.copy(src, 0, this, 0, src.byteSize);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemorySegment.copy(src, 0, this, 0, src.byteSize);
|
||||
* }
|
||||
* @param src the source segment.
|
||||
* @throws IndexOutOfBoundsException if {@code src.byteSize() > this.byteSize()}.
|
||||
* @throws IllegalStateException if either the scope associated with the source segment or the scope associated
|
||||
@ -801,9 +801,9 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* when the segment is no longer in use. Failure to do so will result in off-heap memory leaks.
|
||||
* <p>
|
||||
* This is equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
allocateNative(layout.bytesSize(), layout.bytesAlignment(), scope);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* allocateNative(layout.bytesSize(), layout.bytesAlignment(), scope);
|
||||
* }
|
||||
* <p>
|
||||
* The block of off-heap memory associated with the returned native memory segment is initialized to zero.
|
||||
*
|
||||
@ -826,9 +826,9 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* when the segment is no longer in use. Failure to do so will result in off-heap memory leaks.
|
||||
* <p>
|
||||
* This is equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
allocateNative(bytesSize, 1, scope);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* allocateNative(bytesSize, 1, scope);
|
||||
* }
|
||||
* <p>
|
||||
* The block of off-heap memory associated with the returned native memory segment is initialized to zero.
|
||||
*
|
||||
@ -935,9 +935,9 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* For example, this may occur if the same file is {@linkplain MemorySegment#mapFile mapped} to two segments.
|
||||
* <p>
|
||||
* Calling this method is equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemorySegment.copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemorySegment.copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes);
|
||||
* }
|
||||
* @param srcSegment the source segment.
|
||||
* @param srcOffset the starting offset, in bytes, of the source segment.
|
||||
* @param dstSegment the destination segment.
|
||||
|
||||
@ -103,15 +103,15 @@ import java.util.Spliterator;
|
||||
* segment and allow multiple threads to work in parallel on disjoint segment slices. The following code can be used to sum
|
||||
* all int values in a memory segment in parallel:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
try (ResourceScope scope = ResourceScope.newSharedScope()) {
|
||||
SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
|
||||
MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
|
||||
int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
|
||||
.mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
|
||||
.sum();
|
||||
}
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* try (ResourceScope scope = ResourceScope.newSharedScope()) {
|
||||
* SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
|
||||
* MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
|
||||
* int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
|
||||
* .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
|
||||
* .sum();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* <p>
|
||||
* Shared resource scopes, while powerful, must be used with caution: if one or more threads accesses
|
||||
@ -131,13 +131,13 @@ try (ResourceScope scope = ResourceScope.newSharedScope()) {
|
||||
* This can be useful when clients need to perform a critical operation on a memory segment, during which they have
|
||||
* to ensure that the scope associated with that segment will not be closed; this can be done as follows:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
MemorySegment segment = ...
|
||||
try (ResourceScope criticalScope = ResourceScope.newConfinedScope()) {
|
||||
criticalScope.keepAlive(segment.scope());
|
||||
<critical operation on segment>
|
||||
}
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemorySegment segment = ...
|
||||
* try (ResourceScope criticalScope = ResourceScope.newConfinedScope()) {
|
||||
* criticalScope.keepAlive(segment.scope());
|
||||
* <critical operation on segment>
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Note that a resource scope does not become <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>
|
||||
* until all the scopes it depends on have been closed.
|
||||
@ -239,9 +239,9 @@ public sealed interface ResourceScope extends AutoCloseable permits ResourceScop
|
||||
/**
|
||||
* Creates a new shared scope, managed by a private {@link Cleaner} instance. Equivalent to (but likely more efficient than)
|
||||
* the following code:
|
||||
* <pre>{@code
|
||||
newSharedScope(Cleaner.create());
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* newSharedScope(Cleaner.create());
|
||||
* }
|
||||
* @return a shared scope, managed by a private {@link Cleaner} instance.
|
||||
*/
|
||||
static ResourceScope newImplicitScope() {
|
||||
|
||||
@ -339,9 +339,9 @@ public interface SegmentAllocator {
|
||||
/**
|
||||
* Returns a native unbounded arena-based allocator, with predefined block size and maximum arena size,
|
||||
* associated with the provided scope. Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
SegmentAllocator.newNativeArena(Long.MAX_VALUE, predefinedBlockSize, scope);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* SegmentAllocator.newNativeArena(Long.MAX_VALUE, predefinedBlockSize, scope);
|
||||
* }
|
||||
*
|
||||
* @param scope the scope associated with the segments returned by the arena-based allocator.
|
||||
* @return a new unbounded arena-based allocator
|
||||
@ -355,9 +355,9 @@ public interface SegmentAllocator {
|
||||
/**
|
||||
* Returns a native unbounded arena-based allocator, with block size set to the specified arena size, associated with
|
||||
* the provided scope, with given arena size. Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
SegmentAllocator.newNativeArena(arenaSize, arenaSize, scope);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* SegmentAllocator.newNativeArena(arenaSize, arenaSize, scope);
|
||||
* }
|
||||
*
|
||||
* @param arenaSize the size (in bytes) of the allocation arena.
|
||||
* @param scope the scope associated with the segments returned by the arena-based allocator.
|
||||
@ -416,10 +416,10 @@ public interface SegmentAllocator {
|
||||
* each new allocation request will return a new slice starting at the segment offset {@code 0} (alignment
|
||||
* constraints are ignored by this allocator), hence the name <em>prefix allocator</em>.
|
||||
* Equivalent to (but likely more efficient than) the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemorySegment segment = ...
|
||||
SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemorySegment segment = ...
|
||||
* SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size);
|
||||
* }
|
||||
* <p>
|
||||
* This allocator can be useful to limit allocation requests in case a client
|
||||
* knows that they have fully processed the contents of the allocated segment before the subsequent allocation request
|
||||
@ -439,10 +439,10 @@ public interface SegmentAllocator {
|
||||
/**
|
||||
* Returns a native allocator, associated with the provided scope. Equivalent to (but likely more efficient than)
|
||||
* the following code:
|
||||
* <blockquote><pre>{@code
|
||||
ResourceScope scope = ...
|
||||
SegmentAllocator nativeAllocator = (size, align) -> MemorySegment.allocateNative(size, align, scope);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* ResourceScope scope = ...
|
||||
* SegmentAllocator nativeAllocator = (size, align) -> MemorySegment.allocateNative(size, align, scope);
|
||||
* }
|
||||
*
|
||||
* @param scope the scope associated with the returned allocator.
|
||||
* @return a native allocator, associated with the provided scope.
|
||||
@ -455,10 +455,10 @@ public interface SegmentAllocator {
|
||||
/**
|
||||
* Returns a native allocator which allocates segments in independent {@linkplain ResourceScope#newImplicitScope() implicit scopes}.
|
||||
* Equivalent to (but likely more efficient than) the following code:
|
||||
* <blockquote><pre>{@code
|
||||
ResourceScope scope = ...
|
||||
SegmentAllocator implicitAllocator = (size, align) -> MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope());
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* ResourceScope scope = ...
|
||||
* SegmentAllocator implicitAllocator = (size, align) -> MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope());
|
||||
* }
|
||||
*
|
||||
* @return a native allocator which allocates segments in independent {@linkplain ResourceScope#newImplicitScope() implicit scopes}.
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,18 +37,18 @@ import java.util.OptionalLong;
|
||||
* A finite sequence layout can be thought of as a group layout where the sequence layout's element layout is repeated a number of times
|
||||
* that is equal to the sequence layout's element count. In other words this layout:
|
||||
*
|
||||
* <pre>{@code
|
||||
MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
|
||||
* }
|
||||
*
|
||||
* is equivalent to the following layout:
|
||||
*
|
||||
* <pre>{@code
|
||||
MemoryLayout.structLayout(
|
||||
ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.structLayout(
|
||||
* ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
* ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
* ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
|
||||
* }
|
||||
*
|
||||
* <p>
|
||||
* This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>
|
||||
@ -119,22 +119,22 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout
|
||||
* as the flattened projection of this sequence layout.
|
||||
* <p>
|
||||
* For instance, given a sequence layout of the kind:
|
||||
* <pre>{@code
|
||||
var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
|
||||
* }
|
||||
* calling {@code seq.reshape(2, 6)} will yield the following sequence layout:
|
||||
* <pre>{@code
|
||||
var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_INT));
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_INT));
|
||||
* }
|
||||
* <p>
|
||||
* If one of the provided element count is the special value {@code -1}, then the element
|
||||
* count in that position will be inferred from the remaining element counts and the
|
||||
* element count of the flattened projection of this layout. For instance, a layout equivalent to
|
||||
* the above {@code reshapeSeq} can also be computed in the following ways:
|
||||
* <pre>{@code
|
||||
var reshapeSeqImplicit1 = seq.reshape(-1, 6);
|
||||
var reshapeSeqImplicit2 = seq.reshape(2, -1);
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* var reshapeSeqImplicit1 = seq.reshape(-1, 6);
|
||||
* var reshapeSeqImplicit2 = seq.reshape(2, -1);
|
||||
* }
|
||||
* @param elementCounts an array of element counts, of which at most one can be {@code -1}.
|
||||
* @return a new sequence layout where element layouts in the flattened projection of this
|
||||
* sequence layout (see {@link #flatten()}) are re-arranged into one or more nested sequence layouts.
|
||||
@ -195,13 +195,13 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout
|
||||
* This transformation preserves the layout size; nested sequence layout in this sequence layout will
|
||||
* be dropped and their element counts will be incorporated into that of the returned sequence layout.
|
||||
* For instance, given a sequence layout of the kind:
|
||||
* <pre>{@code
|
||||
var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
|
||||
* }
|
||||
* calling {@code seq.flatten()} will yield the following sequence layout:
|
||||
* <pre>{@code
|
||||
var flattenedSeq = MemoryLayout.sequenceLayout(12, ValueLayout.JAVA_INT);
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* var flattenedSeq = MemoryLayout.sequenceLayout(12, ValueLayout.JAVA_INT);
|
||||
* }
|
||||
* @return a new sequence layout with the same size as this layout (but, possibly, with different
|
||||
* element count), whose element layout is not a sequence layout.
|
||||
* @throws UnsupportedOperationException if this sequence layout, or one of the nested sequence layouts being
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -516,9 +516,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout {
|
||||
* A value layout constant whose size is the same as that of a machine address (e.g. {@code size_t}),
|
||||
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout.valueLayout(MemoryAddress.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.valueLayout(MemoryAddress.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }
|
||||
*/
|
||||
public static final OfAddress ADDRESS = new OfAddress(ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
|
||||
@ -526,9 +526,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout {
|
||||
* A value layout constant whose size is the same as that of a Java {@code byte},
|
||||
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout.valueLayout(byte.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.valueLayout(byte.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }
|
||||
*/
|
||||
public static final OfByte JAVA_BYTE = new OfByte(ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
|
||||
@ -536,9 +536,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout {
|
||||
* A value layout constant whose size is the same as that of a Java {@code boolean},
|
||||
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout.valueLayout(boolean.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.valueLayout(boolean.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }
|
||||
*/
|
||||
public static final OfBoolean JAVA_BOOLEAN = new OfBoolean(ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
|
||||
@ -546,9 +546,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout {
|
||||
* A value layout constant whose size is the same as that of a Java {@code char},
|
||||
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }
|
||||
*/
|
||||
public static final OfChar JAVA_CHAR = new OfChar(ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
|
||||
@ -556,9 +556,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout {
|
||||
* A value layout constant whose size is the same as that of a Java {@code short},
|
||||
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout.valueLayout(short.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.valueLayout(short.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }
|
||||
*/
|
||||
public static final OfShort JAVA_SHORT = new OfShort(ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
|
||||
@ -566,9 +566,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout {
|
||||
* A value layout constant whose size is the same as that of a Java {@code int},
|
||||
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout.valueLayout(int.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.valueLayout(int.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }
|
||||
*/
|
||||
public static final OfInt JAVA_INT = new OfInt(ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
|
||||
@ -576,9 +576,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout {
|
||||
* A value layout constant whose size is the same as that of a Java {@code long},
|
||||
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout.valueLayout(long.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.valueLayout(long.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }
|
||||
*/
|
||||
public static final OfLong JAVA_LONG = new OfLong(ByteOrder.nativeOrder())
|
||||
.withBitAlignment(8);
|
||||
@ -587,9 +587,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout {
|
||||
* A value layout constant whose size is the same as that of a Java {@code float},
|
||||
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout.valueLayout(float.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.valueLayout(float.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }
|
||||
*/
|
||||
public static final OfFloat JAVA_FLOAT = new OfFloat(ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
|
||||
@ -597,9 +597,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout {
|
||||
* A value layout constant whose size is the same as that of a Java {@code double},
|
||||
* bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* <blockquote><pre>{@code
|
||||
MemoryLayout.valueLayout(double.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }</pre></blockquote>
|
||||
* {@snippet lang=java :
|
||||
* MemoryLayout.valueLayout(double.class, ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
* }
|
||||
*/
|
||||
public static final OfDouble JAVA_DOUBLE = new OfDouble(ByteOrder.nativeOrder()).withBitAlignment(8);
|
||||
}
|
||||
|
||||
@ -43,12 +43,12 @@
|
||||
* For example, to allocate an off-heap memory region big enough to hold 10 values of the primitive type {@code int}, and fill it with values
|
||||
* ranging from {@code 0} to {@code 9}, we can use the following code:
|
||||
*
|
||||
* <pre>{@code
|
||||
MemorySegment segment = MemorySegment.allocateNative(10 * 4, ResourceScope.newImplicitScope());
|
||||
for (int i = 0 ; i < 10 ; i++) {
|
||||
segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
|
||||
}
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* MemorySegment segment = MemorySegment.allocateNative(10 * 4, ResourceScope.newImplicitScope());
|
||||
* for (int i = 0 ; i < 10 ; i++) {
|
||||
* segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* This code creates a <em>native</em> memory segment, that is, a memory segment backed by
|
||||
* off-heap memory; the size of the segment is 40 bytes, enough to store 10 values of the primitive type {@code int}.
|
||||
@ -69,14 +69,14 @@ for (int i = 0 ; i < 10 ; i++) {
|
||||
* Clients that operate under these assumptions might want to programmatically release the memory associated
|
||||
* with a memory segment. This can be done, using the {@link jdk.incubator.foreign.ResourceScope} abstraction, as shown below:
|
||||
*
|
||||
* <pre>{@code
|
||||
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
|
||||
MemorySegment segment = MemorySegment.allocateNative(10 * 4, scope);
|
||||
for (int i = 0 ; i < 10 ; i++) {
|
||||
segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
|
||||
}
|
||||
}
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* try (ResourceScope scope = ResourceScope.newConfinedScope()) {
|
||||
* MemorySegment segment = MemorySegment.allocateNative(10 * 4, scope);
|
||||
* for (int i = 0 ; i < 10 ; i++) {
|
||||
* segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* This example is almost identical to the prior one; this time we first create a so called <em>resource scope</em>,
|
||||
* which is used to <em>bind</em> the life-cycle of the segment created immediately afterwards. Note the use of the
|
||||
@ -107,19 +107,19 @@ try (ResourceScope scope = ResourceScope.newConfinedScope()) {
|
||||
* For example, to compute the length of a string using the C standard library function {@code strlen} on a Linux x64 platform,
|
||||
* we can use the following code:
|
||||
*
|
||||
* <pre>{@code
|
||||
var linker = CLinker.systemCLinker();
|
||||
MethodHandle strlen = linker.downcallHandle(
|
||||
linker.lookup("strlen").get(),
|
||||
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
|
||||
);
|
||||
|
||||
try (var scope = ResourceScope.newConfinedScope()) {
|
||||
var cString = MemorySegment.allocateNative(5 + 1, scope);
|
||||
cString.setUtf8String("Hello");
|
||||
long len = (long)strlen.invoke(cString); // 5
|
||||
}
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* var linker = CLinker.systemCLinker();
|
||||
* MethodHandle strlen = linker.downcallHandle(
|
||||
* linker.lookup("strlen").get(),
|
||||
* FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
|
||||
* );
|
||||
*
|
||||
* try (var scope = ResourceScope.newConfinedScope()) {
|
||||
* var cString = MemorySegment.allocateNative(5 + 1, scope);
|
||||
* cString.setUtf8String("Hello");
|
||||
* long len = (long)strlen.invoke(cString); // 5
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Here, we obtain a {@linkplain jdk.incubator.foreign.CLinker#systemCLinker() linker instance} and we use it
|
||||
* to {@linkplain jdk.incubator.foreign.CLinker#lookup(java.lang.String) lookup} the {@code strlen} symbol in the
|
||||
@ -148,11 +148,10 @@ try (ResourceScope scope = ResourceScope.newConfinedScope()) {
|
||||
* {@linkplain jdk.incubator.foreign.MemoryAddress#get(jdk.incubator.foreign.ValueLayout.OfInt, long) dereference methods}
|
||||
* provided:
|
||||
*
|
||||
* <pre>{@code
|
||||
...
|
||||
MemoryAddress addr = ... //obtain address from native code
|
||||
int x = addr.get(ValueLayout.JAVA_INT, 0);
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* MemoryAddress addr = ... //obtain address from native code
|
||||
* int x = addr.get(ValueLayout.JAVA_INT, 0);
|
||||
* }
|
||||
*
|
||||
* Alternatively, the client can
|
||||
* {@linkplain jdk.incubator.foreign.MemorySegment#ofAddress(jdk.incubator.foreign.MemoryAddress, long, jdk.incubator.foreign.ResourceScope) create}
|
||||
@ -160,36 +159,36 @@ int x = addr.get(ValueLayout.JAVA_INT, 0);
|
||||
* for instance, be available in the documentation of the foreign function which produced the native address.
|
||||
* Here is how an unsafe segment can be created from a native address:
|
||||
*
|
||||
* <pre>{@code
|
||||
ResourceScope scope = ... // initialize a resource scope object
|
||||
MemoryAddress addr = ... //obtain address from native code
|
||||
MemorySegment segment = MemorySegment.ofAddress(addr, 4, scope); // segment is 4 bytes long
|
||||
int x = segment.get(ValueLayout.JAVA_INT, 0);
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* ResourceScope scope = ... // initialize a resource scope object
|
||||
* MemoryAddress addr = ... //obtain address from native code
|
||||
* MemorySegment segment = MemorySegment.ofAddress(addr, 4, scope); // segment is 4 bytes long
|
||||
* int x = segment.get(ValueLayout.JAVA_INT, 0);
|
||||
* }
|
||||
*
|
||||
* <h3>Upcalls</h3>
|
||||
* The {@link jdk.incubator.foreign.CLinker} interface also allows to turn an existing method handle (which might point
|
||||
* to a Java method) into a memory address, so that Java code can effectively be passed to other foreign functions.
|
||||
* For instance, we can write a method that compares two integer values, as follows:
|
||||
*
|
||||
* <pre>{@code
|
||||
class IntComparator {
|
||||
static int intCompare(MemoryAddress addr1, MemoryAddress addr2) {
|
||||
return addr1.get(ValueLayout.JAVA_INT, 0) - addr2.get(ValueLayout.JAVA_INT, 0);
|
||||
}
|
||||
}
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* class IntComparator {
|
||||
* static int intCompare(MemoryAddress addr1, MemoryAddress addr2) {
|
||||
* return addr1.get(ValueLayout.JAVA_INT, 0) - addr2.get(ValueLayout.JAVA_INT, 0);
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* The above method dereferences two memory addresses containing an integer value, and performs a simple comparison
|
||||
* by returning the difference between such values. We can then obtain a method handle which targets the above static
|
||||
* method, as follows:
|
||||
*
|
||||
* <pre>{@code
|
||||
FunctionDescriptor intCompareDescriptor = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS);
|
||||
MethodHandle intCompareHandle = MethodHandles.lookup().findStatic(IntComparator.class,
|
||||
"intCompare",
|
||||
CLinker.upcallType(comparFunction));
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* FunctionDescriptor intCompareDescriptor = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS);
|
||||
* MethodHandle intCompareHandle = MethodHandles.lookup().findStatic(IntComparator.class,
|
||||
* "intCompare",
|
||||
* CLinker.upcallType(comparFunction));
|
||||
* }
|
||||
*
|
||||
* As before, we need to create a {@link jdk.incubator.foreign.FunctionDescriptor} instance, this time describing the signature
|
||||
* of the function pointer we want to create. The descriptor can be used to
|
||||
@ -199,12 +198,12 @@ MethodHandle intCompareHandle = MethodHandles.lookup().findStatic(IntComparator.
|
||||
* Now that we have a method handle instance, we can turn it into a fresh function pointer,
|
||||
* using the {@link jdk.incubator.foreign.CLinker} interface, as follows:
|
||||
*
|
||||
* <pre>{@code
|
||||
ResourceScope scope = ...
|
||||
Addressable comparFunc = CLinker.systemCLinker().upcallStub(
|
||||
intCompareHandle, intCompareDescriptor, scope);
|
||||
);
|
||||
* }</pre>
|
||||
* {@snippet lang=java :
|
||||
* ResourceScope scope = ...
|
||||
* Addressable comparFunc = CLinker.systemCLinker().upcallStub(
|
||||
* intCompareHandle, intCompareDescriptor, scope);
|
||||
* );
|
||||
* }
|
||||
*
|
||||
* The {@link jdk.incubator.foreign.FunctionDescriptor} instance created in the previous step is then used to
|
||||
* {@linkplain jdk.incubator.foreign.CLinker#upcallStub(java.lang.invoke.MethodHandle, jdk.incubator.foreign.FunctionDescriptor, jdk.incubator.foreign.ResourceScope) create}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user