8319324: FFM: Reformat javadocs

Reviewed-by: mcimadamore
This commit is contained in:
Per Minborg 2023-11-09 15:18:43 +00:00
parent a3f1b33b9b
commit f939542104
16 changed files with 3001 additions and 2166 deletions

View file

@ -31,47 +31,53 @@ import jdk.internal.ref.CleanerFactory;
import java.lang.foreign.MemorySegment.Scope;
/**
* An arena controls the lifecycle of native memory segments, providing both flexible allocation and timely deallocation.
* An arena controls the lifecycle of native memory segments, providing both flexible
* allocation and timely deallocation.
* <p>
* An arena has a {@linkplain MemorySegment.Scope scope} - the <em>arena scope</em>. All the segments allocated
* by the arena are associated with the arena scope. As such, the arena determines the temporal bounds
* of all the memory segments allocated by it.
* An arena has a {@linkplain MemorySegment.Scope scope} - the <em>arena scope</em>.
* All the segments allocated by the arena are associated with the arena scope. As such,
* the arena determines the temporal bounds of all the memory segments allocated by it.
* <p>
* Moreover, an arena also determines whether access to memory segments allocated by it should be
* {@linkplain MemorySegment#isAccessibleBy(Thread) restricted} to specific threads.
* An arena is a {@link SegmentAllocator} and features several allocation methods that can be used by clients
* to obtain native segments.
* Moreover, an arena also determines whether access to memory segments allocated by it
* should be {@linkplain MemorySegment#isAccessibleBy(Thread) restricted} to specific
* threads. An arena is a {@link SegmentAllocator} and features several allocation
* methods that can be used by clients to obtain native segments.
* <p>
* The simplest arena is the {@linkplain Arena#global() global arena}. The global arena
* features an <em>unbounded lifetime</em>. The scope of the global arena is the global scope.
* As such, native segments allocated with the global arena are always accessible and their backing regions
* of memory are never deallocated.
* Moreover, memory segments allocated with the global arena can be {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} from any thread.
* features an <em>unbounded lifetime</em>. The scope of the global arena is the global
* scope. As such, native segments allocated with the global arena are always accessible
* and their backing regions of memory are never deallocated. Moreover, memory segments
* allocated with the global arena can be {@linkplain MemorySegment#isAccessibleBy(Thread) accessed}
* from any thread.
* {@snippet lang = java:
* MemorySegment segment = Arena.global().allocate(100, 1); // @highlight regex='global()'
* ...
* // segment is never deallocated!
*}
* <p>
* Alternatively, clients can obtain an {@linkplain Arena#ofAuto() automatic arena}, that is an arena
* which features a <em>bounded lifetime</em> that is managed, automatically, by the garbage collector. The scope
* of an automatic arena is an automatic scope. As such, the regions
* of memory backing memory segments allocated with the automatic arena are deallocated at some unspecified time
* <em>after</em> the automatic arena (and all the segments allocated by it) becomes
* <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>, as shown below:
* Alternatively, clients can obtain an {@linkplain Arena#ofAuto() automatic arena}, that
* is an arena which features a <em>bounded lifetime</em> that is managed, automatically,
* by the garbage collector. The scope of an automatic arena is an automatic scope. As
* such, the regions of memory backing memory segments allocated with the automatic arena
* are deallocated at some unspecified time <em>after</em> the automatic arena (and all
* the segments allocated by it) becomes <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>,
* as shown below:
* {@snippet lang = java:
* MemorySegment segment = Arena.ofAuto().allocate(100, 1); // @highlight regex='ofAuto()'
* ...
* segment = null; // the segment region becomes available for deallocation after this point
*}
* Memory segments allocated with an automatic arena can also be {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} from any thread.
* Memory segments allocated with an automatic arena can also be
* {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} from any thread.
* <p>
* Rather than leaving deallocation in the hands of the Java runtime, clients will often wish to exercise control over
* the timing of deallocation for regions of memory that back memory segments. Two kinds of arenas support this,
* namely {@linkplain #ofConfined() confined} and {@linkplain #ofShared() shared} arenas. They both feature
* bounded lifetimes that are managed manually. For instance, when a confined arena is {@linkplain #close() closed}
* successfully, its scope is {@linkplain Scope#isAlive() invalidated}. As a result, all the memory segments allocated
* by the arena can no longer be accessed, and their regions of memory are deallocated:
* Rather than leaving deallocation in the hands of the Java runtime, clients will often
* wish to exercise control over the timing of deallocation for regions of memory that
* back memory segments. Two kinds of arenas support this, namely {@linkplain #ofConfined() confined}
* and {@linkplain #ofShared() shared} arenas. They both feature bounded lifetimes that
* are managed manually. For instance, when a confined arena is {@linkplain #close() closed}
* successfully, its scope is {@linkplain Scope#isAlive() invalidated}. As a result, all
* the memory segments allocated by the arena can no longer be accessed, and their
* regions of memory are deallocated:
*
* {@snippet lang = java:
* MemorySegment segment = null;
@ -82,9 +88,10 @@ import java.lang.foreign.MemorySegment.Scope;
* segment.get(ValueLayout.JAVA_BYTE, 0); // throws IllegalStateException
*}
*
* Memory segments allocated with a {@linkplain #ofConfined() confined arena} can only be accessed (and closed) by the
* thread that created the arena. If access to a memory segment from multiple threads is required, clients can allocate
* segments in a {@linkplain #ofShared() shared arena} instead.
* Memory segments allocated with a {@linkplain #ofConfined() confined arena} can only be
* accessed (and closed) by the thread that created the arena. If access to a memory
* segment from multiple threads is required, clients can allocate segments in a
* {@linkplain #ofShared() shared arena} instead.
* <p>
* The characteristics of the various arenas are summarized in the following table:
*
@ -120,38 +127,45 @@ import java.lang.foreign.MemorySegment.Scope;
*
* <h2 id = "thread-confinement">Safety and thread-confinement</h2>
*
* Arenas provide strong temporal safety guarantees: a memory segment allocated by an arena cannot be accessed
* <em>after</em> the arena has been closed. The cost of providing this guarantee varies based on the
* number of threads that have access to the memory segments allocated by the arena. For instance, if an arena
* is always created and closed by one thread, and the memory segments allocated by the arena are always
* Arenas provide strong temporal safety guarantees: a memory segment allocated by an
* arena cannot be accessed <em>after</em> the arena has been closed. The cost of
* providing this guarantee varies based on the number of threads that have access to the
* memory segments allocated by the arena. For instance, if an arena is always created
* and closed by one thread, and the memory segments allocated by the arena are always
* accessed by that same thread, then ensuring correctness is trivial.
* <p>
* Conversely, if an arena allocates segments that can be accessed by multiple threads, or if the arena can be closed
* by a thread other than the accessing thread, then ensuring correctness is much more complex. For example, a segment
* allocated with the arena might be accessed <em>while</em> another thread attempts, concurrently, to close the arena.
* To provide the strong temporal safety guarantee without forcing every client, even simple ones, to incur a performance
* impact, arenas are divided into <em>thread-confined</em> arenas, and <em>shared</em> arenas.
* Conversely, if an arena allocates segments that can be accessed by multiple threads,
* or if the arena can be closed by a thread other than the accessing thread, then
* ensuring correctness is much more complex. For example, a segment allocated with the
* arena might be accessed <em>while</em> another thread attempts, concurrently, to close
* the arena. To provide the strong temporal safety guarantee without forcing every
* client, even simple ones, to incur a performance impact, arenas are divided into
* <em>thread-confined</em> arenas, and <em>shared</em> arenas.
* <p>
* Confined arenas, support strong thread-confinement guarantees. Upon creation, they are assigned an
* <em>owner thread</em>, typically the thread which initiated the creation operation.
* The segments created by a confined arena can only be {@linkplain MemorySegment#isAccessibleBy(Thread) accessed}
* by the owner thread. Moreover, any attempt to close the confined arena from a thread other than the owner thread will
* fail with {@link WrongThreadException}.
* Confined arenas, support strong thread-confinement guarantees. Upon creation, they are
* assigned an <em>owner thread</em>, typically the thread which initiated the creation
* operation. The segments created by a confined arena can only be
* {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} by the owner thread.
* Moreover, any attempt to close the confined arena from a thread other than the owner
* thread will fail with a {@link WrongThreadException}.
* <p>
* Shared arenas, on the other hand, have no owner thread. The segments created by a shared arena
* can be {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} by any thread. This might be useful when
* multiple threads need to access the same memory segment concurrently (e.g. in the case of parallel processing).
* Moreover, a shared arena can be closed by any thread.
* Shared arenas, on the other hand, have no owner thread. The segments created by a
* shared arena can be {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} by
* any thread. This might be useful when multiple threads need to access the same memory
* segment concurrently (e.g. in the case of parallel processing). Moreover, a shared
* arena can be closed by any thread.
*
* <h2 id = "custom-arenas">Custom arenas</h2>
*
* Clients can define custom arenas to implement more efficient allocation strategies, or to have better control over
* when (and by whom) an arena can be closed. As an example, the following code defines a <em>slicing arena</em> that behaves
* like a confined arena (i.e., single-threaded access), but internally uses a
* {@linkplain SegmentAllocator#slicingAllocator(MemorySegment) slicing allocator} to respond to allocation requests.
* When the slicing arena is closed, the underlying confined arena is also closed; this will invalidate all segments
* allocated with the slicing arena (since the scope of the slicing arena is the same as that of the underlying
* confined arena):
* Clients can define custom arenas to implement more efficient allocation strategies,
* or to have better control over when (and by whom) an arena can be closed. As an
* example, the following code defines a <em>slicing arena</em> that behaves like a
* confined arena (i.e., single-threaded access), but internally uses a
* {@linkplain SegmentAllocator#slicingAllocator(MemorySegment) slicing allocator} to
* respond to allocation requests.
* When the slicing arena is closed, the underlying confined arena is also closed; this
* will invalidate all segments allocated with the slicing arena (since the scope of the
* slicing arena is the same as that of the underlying confined arena):
*
* {@snippet lang = java:
* class SlicingArena implements Arena {
@ -177,8 +191,9 @@ import java.lang.foreign.MemorySegment.Scope;
* }
* }
*
* In other words, a slicing arena provides a vastly more efficient and scalable allocation strategy, while still retaining
* the timely deallocation guarantee provided by the underlying confined arena:
* In other words, a slicing arena provides a vastly more efficient and scalable
* allocation strategy, while still retaining the timely deallocation guarantee provided
* by the underlying confined arena:
*
* {@snippet lang = java:
* try (Arena slicingArena = new SlicingArena(1000)) {
@ -204,18 +219,17 @@ public interface Arena extends SegmentAllocator, AutoCloseable {
* {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} by any thread.
* Calling {@link #close()} on the returned arena will result in an {@link UnsupportedOperationException}.
*
* @return a new arena that is managed, automatically, by the garbage collector.
* @return a new arena that is managed, automatically, by the garbage collector
*/
static Arena ofAuto() {
return MemorySessionImpl.createImplicit(CleanerFactory.cleaner()).asArena();
}
/**
* Obtains the global arena. Segments allocated with the global arena can be
* {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} by any thread.
* Calling {@link #close()} on the returned arena will result in an {@link UnsupportedOperationException}.
*
* @return the global arena.
* {@return the global arena} Segments allocated with the global arena can be
* {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} by any thread.
* Calling {@link #close()} on the returned arena will result in
* an {@link UnsupportedOperationException}.
*/
static Arena global() {
class Holder {
@ -226,8 +240,8 @@ public interface Arena extends SegmentAllocator, AutoCloseable {
/**
* {@return a new confined arena} Segments allocated with the confined arena can be
* {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} by the thread that created the arena,
* the arena's <em>owner thread</em>.
* {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} by the thread
* that created the arena, the arena's <em>owner thread</em>.
*/
static Arena ofConfined() {
return MemorySessionImpl.createConfined(Thread.currentThread()).asArena();
@ -235,36 +249,40 @@ public interface Arena extends SegmentAllocator, AutoCloseable {
/**
* {@return a new shared arena} Segments allocated with the global arena can be
* {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} by any thread.
* {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} by any thread.
*/
static Arena ofShared() {
return MemorySessionImpl.createShared().asArena();
}
/**
* Returns a native memory segment with the given size (in bytes) and alignment constraint (in bytes).
* Returns a native memory segment with the given size (in bytes) and alignment
* constraint (in bytes).
* The returned segment is associated with this {@linkplain #scope() arena scope}.
* The segment's {@link MemorySegment#address() address} is the starting address of the
* allocated off-heap region of memory backing the segment, and the address is
* aligned according to the provided alignment constraint.
* The segment's {@link MemorySegment#address() address} is the starting address of
* the allocated off-heap region of memory backing the segment, and the address is
* aligned according the provided alignment constraint.
*
* @implSpec
* Implementations of this method must return a native segment featuring the requested size,
* and that is compatible with the provided alignment constraint. Furthermore, for any two segments
* {@code S1, S2} returned by this method, the following invariant must hold:
* Implementations of this method must return a native segment featuring the
* requested size, and that is compatible with the provided alignment constraint.
* Furthermore, for any two segments {@code S1, S2} returned by this method, the
* following invariant must hold:
*
* {@snippet lang = java:
* S1.asOverlappingSlice(S2).isEmpty() == true
* }
*
* @param byteSize the size (in bytes) of the off-heap region of memory backing the native memory segment.
* @param byteAlignment the alignment constraint (in bytes) of the off-heap region of memory backing the native memory segment.
* @return a new native memory segment.
* @param byteSize the size (in bytes) of the off-heap region of memory backing
* the native memory segment
* @param byteAlignment the alignment constraint (in bytes) of the off-heap region
* of memory backing the native memory segment
* @return a new native memory segment
* @throws IllegalArgumentException if {@code bytesSize < 0}, {@code byteAlignment <= 0},
* or if {@code byteAlignment} is not a power of 2
* @throws IllegalStateException if this arena has already been {@linkplain #close() closed}
* @throws WrongThreadException if this arena is confined, and this method is called from a thread
* other than the arena's owner thread
* @throws WrongThreadException if this arena is confined, and this method is called
* from a thread other than the arena's owner thread
*/
@Override
MemorySegment allocate(long byteSize, long byteAlignment);
@ -275,25 +293,29 @@ public interface Arena extends SegmentAllocator, AutoCloseable {
Scope scope();
/**
* Closes this arena. If this method completes normally, the arena scope is no longer {@linkplain Scope#isAlive() alive},
* and all the memory segments associated with it can no longer be accessed. Furthermore, any off-heap region of memory backing the
* Closes this arena. If this method completes normally, the arena scope is no longer
* {@linkplain Scope#isAlive() alive}, and all the memory segments associated with it
* can no longer be accessed. Furthermore, any off-heap region of memory backing the
* segments obtained from this arena are also released.
*
* @apiNote This operation is not idempotent; that is, closing an already closed arena <em>always</em> results in an
* exception being thrown. This reflects a deliberate design choice: failure to close an arena might reveal a bug
* in the underlying application logic.
* @apiNote This operation is not idempotent; that is, closing an already closed arena
* <em>always</em> results in an exception being thrown. This reflects a
* deliberate design choice: failure to close an arena might reveal a bug
* in the underlying application logic.
*
* @implSpec If this method completes normally, then {@code this.scope().isAlive() == false}.
* Implementations are allowed to throw {@link UnsupportedOperationException} if an explicit close operation is
* not supported.
* @implSpec If this method completes normally, then
* {@code this.scope().isAlive() == false}.
* Implementations are allowed to throw {@link UnsupportedOperationException}
* if an explicit close operation is not supported.
*
* @see Scope#isAlive()
*
* @throws IllegalStateException if the arena has already been closed
* @throws IllegalStateException if a segment associated with this arena is being accessed concurrently, e.g.
* by a {@linkplain Linker#downcallHandle(FunctionDescriptor, Linker.Option...) downcall method handle}
* @throws WrongThreadException if this arena is confined, and this method is called from a thread
* other than the arena's owner thread
* @throws IllegalStateException if a segment associated with this arena is being
* accessed concurrently, e.g. by a
* {@linkplain Linker#downcallHandle(FunctionDescriptor, Linker.Option...) downcall method handle}
* @throws WrongThreadException if this arena is confined, and this method is called
* from a thread other than the arena's owner thread
* @throws UnsupportedOperationException if this arena cannot be closed explicitly
*/
@Override