8278433: Use snippets in jdk.incubator.foreign documentation

Reviewed-by: mcimadamore
This commit is contained in:
Julia Boes 2021-12-09 09:29:08 +00:00
parent 1ea766db55
commit 84baea753a
10 changed files with 289 additions and 290 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.
*

View File

@ -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.

View File

@ -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() {

View File

@ -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}.
*/

View File

@ -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

View File

@ -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);
}

View File

@ -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}