< prev index next > src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java
Print this page
import java.lang.foreign.MemorySegment.Scope;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.ref.Cleaner;
import java.util.Objects;
+
+ import jdk.internal.foreign.GlobalSession.HeapSession;
import jdk.internal.misc.ScopedMemoryAccess;
import jdk.internal.vm.annotation.ForceInline;
/**
* This class manages the temporal bounds associated with a memory segment as well
static final int CLOSED = -2;
static final VarHandle STATE;
static final int MAX_FORKS = Integer.MAX_VALUE;
- public static final MemorySessionImpl GLOBAL = new GlobalSession(null);
-
static final ScopedMemoryAccess.ScopedAccessError ALREADY_CLOSED = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::alreadyClosed);
static final ScopedMemoryAccess.ScopedAccessError WRONG_THREAD = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::wrongThread);
final ResourceList resourceList;
final Thread owner;
int state = OPEN;
static final int CLOSED = -2;
static final VarHandle STATE;
static final int MAX_FORKS = Integer.MAX_VALUE;
static final ScopedMemoryAccess.ScopedAccessError ALREADY_CLOSED = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::alreadyClosed);
static final ScopedMemoryAccess.ScopedAccessError WRONG_THREAD = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::wrongThread);
+ // This is the session of all zero-length memory segments
+ static final GlobalSession NATIVE_SESSION = new GlobalSession();
final ResourceList resourceList;
final Thread owner;
int state = OPEN;
throw new ExceptionInInitializerError(ex);
}
}
public Arena asArena() {
! return new Arena() {
- @Override
- public Scope scope() {
- return MemorySessionImpl.this;
- }
-
- @Override
- public void close() {
- MemorySessionImpl.this.close();
- }
- };
}
@ForceInline
! public static final MemorySessionImpl toMemorySession(Arena arena) {
return (MemorySessionImpl) arena.scope();
}
public final boolean isCloseableBy(Thread thread) {
Objects.requireNonNull(thread);
throw new ExceptionInInitializerError(ex);
}
}
public Arena asArena() {
! return new ArenaImpl(this);
}
@ForceInline
! public static MemorySessionImpl toMemorySession(Arena arena) {
return (MemorySessionImpl) arena.scope();
}
public final boolean isCloseableBy(Thread thread) {
Objects.requireNonNull(thread);
Objects.requireNonNull(runnable);
addInternal(ResourceList.ResourceCleanup.ofRunnable(runnable));
}
/**
! * Add a cleanup action. If a failure occurred (because of a add vs. close race), call the cleanup action.
* This semantics is useful when allocating new memory segments, since we first do a malloc/mmap and _then_
* we register the cleanup (free/munmap) against the session; so, if registration fails, we still have to
! * cleanup memory. From the perspective of the client, such a failure would manifest as a factory
* returning a segment that is already "closed" - which is always possible anyway (e.g. if the session
* is closed _after_ the cleanup for the segment is registered but _before_ the factory returns the
* new segment to the client). For this reason, it's not worth adding extra complexity to the segment
* initialization logic here - and using an optimistic logic works well in practice.
*/
Objects.requireNonNull(runnable);
addInternal(ResourceList.ResourceCleanup.ofRunnable(runnable));
}
/**
! * Add a cleanup action. If a failure occurred (because of an add vs. close race), call the cleanup action.
* This semantics is useful when allocating new memory segments, since we first do a malloc/mmap and _then_
* we register the cleanup (free/munmap) against the session; so, if registration fails, we still have to
! * clean up memory. From the perspective of the client, such a failure would manifest as a factory
* returning a segment that is already "closed" - which is always possible anyway (e.g. if the session
* is closed _after_ the cleanup for the segment is registered but _before_ the factory returns the
* new segment to the client). For this reason, it's not worth adding extra complexity to the segment
* initialization logic here - and using an optimistic logic works well in practice.
*/
public static MemorySessionImpl createImplicit(Cleaner cleaner) {
return new ImplicitSession(cleaner);
}
! public MemorySegment allocate(long byteSize, long byteAlignment) {
! Utils.checkAllocationSizeAndAlign(byteSize, byteAlignment);
! return NativeMemorySegmentImpl.makeNativeSegment(byteSize, byteAlignment, this);
}
public abstract void release0();
public abstract void acquire0();
public static MemorySessionImpl createImplicit(Cleaner cleaner) {
return new ImplicitSession(cleaner);
}
! public static MemorySessionImpl createGlobal() {
! return new GlobalSession();
! }
+
+ public static MemorySessionImpl createHeap(Object ref) {
+ return new HeapSession(ref);
}
public abstract void release0();
public abstract void acquire0();
}
/**
* Checks that this session is still alive (see {@link #isAlive()}).
* @throws IllegalStateException if this session is already closed or if this is
! * a confined session and this method is called outside of the owner thread.
*/
public void checkValidState() {
try {
checkValidStateRaw();
} catch (ScopedMemoryAccess.ScopedAccessError error) {
throw error.newRuntimeException();
}
}
! public static final void checkValidState(MemorySegment segment) {
((AbstractMemorySegmentImpl)segment).sessionImpl().checkValidState();
}
@Override
protected Object clone() throws CloneNotSupportedException {
}
/**
* Checks that this session is still alive (see {@link #isAlive()}).
* @throws IllegalStateException if this session is already closed or if this is
! * a confined session and this method is called outside the owner thread.
*/
public void checkValidState() {
try {
checkValidStateRaw();
} catch (ScopedMemoryAccess.ScopedAccessError error) {
throw error.newRuntimeException();
}
}
! public static void checkValidState(MemorySegment segment) {
((AbstractMemorySegmentImpl)segment).sessionImpl().checkValidState();
}
@Override
protected Object clone() throws CloneNotSupportedException {
}
/**
* Closes this session, executing any cleanup action (where provided).
* @throws IllegalStateException if this session is already closed or if this is
! * a confined session and this method is called outside of the owner thread.
*/
public void close() {
justClose();
resourceList.cleanup();
}
abstract void justClose();
- public static MemorySessionImpl heapSession(Object ref) {
- return new GlobalSession(ref);
- }
-
/**
* A list of all cleanup actions associated with a memory session. Cleanup actions are modelled as instances
* of the {@link ResourceCleanup} class, and, together, form a linked list. Depending on whether a session
* is shared or confined, different implementations of this class will be used, see {@link ConfinedSession.ConfinedResourceList}
* and {@link SharedSession.SharedResourceList}.
}
/**
* Closes this session, executing any cleanup action (where provided).
* @throws IllegalStateException if this session is already closed or if this is
! * a confined session and this method is called outside the owner thread.
*/
public void close() {
justClose();
resourceList.cleanup();
}
abstract void justClose();
/**
* A list of all cleanup actions associated with a memory session. Cleanup actions are modelled as instances
* of the {@link ResourceCleanup} class, and, together, form a linked list. Depending on whether a session
* is shared or confined, different implementations of this class will be used, see {@link ConfinedSession.ConfinedResourceList}
* and {@link SharedSession.SharedResourceList}.
< prev index next >