8287809: Revisit implementation of memory session
Reviewed-by: jvernee
This commit is contained in:
parent
cb6e9cb728
commit
fed3af8ae0
@ -37,7 +37,6 @@ import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.MemorySession;
|
||||
import java.util.Objects;
|
||||
import java.util.Spliterator;
|
||||
|
||||
@ -771,11 +770,7 @@ public abstract sealed class Buffer
|
||||
final void checkSession() {
|
||||
MemorySessionImpl session = session();
|
||||
if (session != null) {
|
||||
try {
|
||||
session.checkValidState();
|
||||
} catch (ScopedMemoryAccess.ScopedAccessError e) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
}
|
||||
session.checkValidState();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,11 +313,7 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
if (session.ownerThread() == null && session.isCloseable()) {
|
||||
throw new UnsupportedOperationException("ByteBuffer derived from closeable shared sessions not supported");
|
||||
}
|
||||
try {
|
||||
session.checkValidState();
|
||||
} catch (ScopedAccessError e) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
}
|
||||
session.checkValidState();
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
@ -70,40 +70,33 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
|
||||
|
||||
private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
|
||||
|
||||
static final int READ_ONLY = 1;
|
||||
static final long NONCE = new Random().nextLong();
|
||||
|
||||
static final int DEFAULT_MODES = 0;
|
||||
|
||||
static final JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess();
|
||||
|
||||
final long length;
|
||||
final int mask;
|
||||
final boolean readOnly;
|
||||
final MemorySession session;
|
||||
|
||||
@ForceInline
|
||||
AbstractMemorySegmentImpl(long length, int mask, MemorySession session) {
|
||||
AbstractMemorySegmentImpl(long length, boolean readOnly, MemorySession session) {
|
||||
this.length = length;
|
||||
this.mask = mask;
|
||||
this.readOnly = readOnly;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
abstract long min();
|
||||
|
||||
abstract Object base();
|
||||
|
||||
abstract AbstractMemorySegmentImpl dup(long offset, long size, int mask, MemorySession session);
|
||||
abstract AbstractMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session);
|
||||
|
||||
abstract ByteBuffer makeByteBuffer();
|
||||
|
||||
@Override
|
||||
public AbstractMemorySegmentImpl asReadOnly() {
|
||||
return dup(0, length, mask | READ_ONLY, session);
|
||||
return dup(0, length, true, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return isSet(READ_ONLY);
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -119,7 +112,7 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
|
||||
}
|
||||
|
||||
private AbstractMemorySegmentImpl asSliceNoCheck(long offset, long newSize) {
|
||||
return dup(offset, newSize, mask, session);
|
||||
return dup(offset, newSize, readOnly, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -147,7 +140,7 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
|
||||
@Override
|
||||
public final MemorySegment fill(byte value){
|
||||
checkAccess(0, length, false);
|
||||
SCOPED_MEMORY_ACCESS.setMemory(sessionImpl(), base(), min(), length, value);
|
||||
SCOPED_MEMORY_ACCESS.setMemory(sessionImpl(), unsafeGetBase(), unsafeGetOffset(), length, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -176,8 +169,8 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
|
||||
return 0;
|
||||
}
|
||||
i = vectorizedMismatchLargeForBytes(sessionImpl(), that.sessionImpl(),
|
||||
this.base(), this.min(),
|
||||
that.base(), that.min(),
|
||||
this.unsafeGetBase(), this.unsafeGetOffset(),
|
||||
that.unsafeGetBase(), that.unsafeGetOffset(),
|
||||
length);
|
||||
if (i >= 0) {
|
||||
return i;
|
||||
@ -235,7 +228,7 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
|
||||
public final ByteBuffer asByteBuffer() {
|
||||
checkArraySize("ByteBuffer", 1);
|
||||
ByteBuffer _bb = makeByteBuffer();
|
||||
if (isSet(READ_ONLY)) {
|
||||
if (readOnly) {
|
||||
//session is IMMUTABLE - obtain a RO byte buffer
|
||||
_bb = _bb.asReadOnlyBuffer();
|
||||
}
|
||||
@ -260,9 +253,9 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
|
||||
@Override
|
||||
public final Optional<MemorySegment> asOverlappingSlice(MemorySegment other) {
|
||||
AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other);
|
||||
if (base() == that.base()) { // both either native or heap
|
||||
final long thisStart = this.min();
|
||||
final long thatStart = that.min();
|
||||
if (unsafeGetBase() == that.unsafeGetBase()) { // both either native or heap
|
||||
final long thisStart = this.unsafeGetOffset();
|
||||
final long thatStart = that.unsafeGetOffset();
|
||||
final long thisEnd = thisStart + this.byteSize();
|
||||
final long thatEnd = thatStart + that.byteSize();
|
||||
|
||||
@ -278,8 +271,8 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
|
||||
@Override
|
||||
public final long segmentOffset(MemorySegment other) {
|
||||
AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl) Objects.requireNonNull(other);
|
||||
if (base() == that.base()) {
|
||||
return that.min() - this.min();
|
||||
if (unsafeGetBase() == that.unsafeGetBase()) {
|
||||
return that.unsafeGetOffset() - this.unsafeGetOffset();
|
||||
}
|
||||
throw new UnsupportedOperationException("Cannot compute offset from native to heap (or vice versa).");
|
||||
}
|
||||
@ -347,31 +340,24 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
|
||||
return arr;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public void checkAccess(long offset, long length, boolean readOnly) {
|
||||
if (!readOnly && isSet(READ_ONLY)) {
|
||||
if (!readOnly && this.readOnly) {
|
||||
throw new UnsupportedOperationException("Attempt to write a read-only segment");
|
||||
}
|
||||
checkBounds(offset, length);
|
||||
}
|
||||
|
||||
public void checkValidState() {
|
||||
sessionImpl().checkValidStateSlow();
|
||||
sessionImpl().checkValidState();
|
||||
}
|
||||
|
||||
public long unsafeGetOffset() {
|
||||
return min();
|
||||
}
|
||||
public abstract long unsafeGetOffset();
|
||||
|
||||
public Object unsafeGetBase() {
|
||||
return base();
|
||||
}
|
||||
public abstract Object unsafeGetBase();
|
||||
|
||||
// Helper methods
|
||||
|
||||
private boolean isSet(int mask) {
|
||||
return (this.mask & mask) != 0;
|
||||
}
|
||||
|
||||
public abstract long maxAlignMask();
|
||||
|
||||
@ForceInline
|
||||
@ -407,25 +393,19 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
|
||||
return outOfBoundException(offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ForceInline
|
||||
public MemorySessionImpl sessionImpl() {
|
||||
return MemorySessionImpl.toSessionImpl(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySession session() {
|
||||
return session;
|
||||
}
|
||||
|
||||
private IndexOutOfBoundsException outOfBoundException(long offset, long length) {
|
||||
return new IndexOutOfBoundsException(String.format("Out of bound access on segment %s; offset = %d; length = %d",
|
||||
return new IndexOutOfBoundsException(String.format("Out of bound access on segment %s; new offset = %d; new length = %d",
|
||||
this, offset, length));
|
||||
}
|
||||
|
||||
protected int id() {
|
||||
//compute a stable and random id for this memory segment
|
||||
return Math.abs(Objects.hash(base(), min(), NONCE));
|
||||
return Math.abs(Objects.hash(unsafeGetBase(), unsafeGetOffset(), NONCE));
|
||||
}
|
||||
|
||||
static class SegmentSplitter implements Spliterator<MemorySegment> {
|
||||
@ -541,42 +521,37 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
|
||||
int size = limit - pos;
|
||||
|
||||
AbstractMemorySegmentImpl bufferSegment = (AbstractMemorySegmentImpl)nioAccess.bufferSegment(bb);
|
||||
final MemorySessionImpl bufferSession;
|
||||
int modes;
|
||||
final MemorySession bufferSession;
|
||||
if (bufferSegment != null) {
|
||||
bufferSession = bufferSegment.sessionImpl();
|
||||
modes = bufferSegment.mask;
|
||||
bufferSession = bufferSegment.session;
|
||||
} else {
|
||||
bufferSession = MemorySessionImpl.heapSession(bb);
|
||||
modes = DEFAULT_MODES;
|
||||
}
|
||||
if (bb.isReadOnly()) {
|
||||
modes |= READ_ONLY;
|
||||
}
|
||||
boolean readOnly = bb.isReadOnly();
|
||||
int scaleFactor = getScaleFactor(bb);
|
||||
if (base != null) {
|
||||
if (base instanceof byte[]) {
|
||||
return new HeapMemorySegmentImpl.OfByte(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes);
|
||||
return new HeapMemorySegmentImpl.OfByte(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
|
||||
} else if (base instanceof short[]) {
|
||||
return new HeapMemorySegmentImpl.OfShort(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes);
|
||||
return new HeapMemorySegmentImpl.OfShort(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
|
||||
} else if (base instanceof char[]) {
|
||||
return new HeapMemorySegmentImpl.OfChar(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes);
|
||||
return new HeapMemorySegmentImpl.OfChar(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
|
||||
} else if (base instanceof int[]) {
|
||||
return new HeapMemorySegmentImpl.OfInt(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes);
|
||||
return new HeapMemorySegmentImpl.OfInt(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
|
||||
} else if (base instanceof float[]) {
|
||||
return new HeapMemorySegmentImpl.OfFloat(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes);
|
||||
return new HeapMemorySegmentImpl.OfFloat(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
|
||||
} else if (base instanceof long[]) {
|
||||
return new HeapMemorySegmentImpl.OfLong(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes);
|
||||
return new HeapMemorySegmentImpl.OfLong(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
|
||||
} else if (base instanceof double[]) {
|
||||
return new HeapMemorySegmentImpl.OfDouble(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes);
|
||||
return new HeapMemorySegmentImpl.OfDouble(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
|
||||
} else {
|
||||
throw new AssertionError("Cannot get here");
|
||||
}
|
||||
} else if (unmapper == null) {
|
||||
return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, modes, bufferSession);
|
||||
return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, readOnly, bufferSession);
|
||||
} else {
|
||||
// we can ignore scale factor here, a mapped buffer is always a byte buffer, so scaleFactor == 0.
|
||||
return new MappedMemorySegmentImpl(bbAddress + pos, unmapper, size, modes, bufferSession);
|
||||
return new MappedMemorySegmentImpl(bbAddress + pos, unmapper, size, readOnly, bufferSession);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,17 +55,12 @@ final class ConfinedSession extends MemorySessionImpl {
|
||||
super(owner, new ConfinedResourceList(), cleaner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return state != CLOSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ForceInline
|
||||
public void acquire0() {
|
||||
checkValidStateSlow();
|
||||
checkValidState();
|
||||
if (state == MAX_FORKS) {
|
||||
throw new IllegalStateException("Session keep alive limit exceeded");
|
||||
throw tooManyAcquires();
|
||||
}
|
||||
state++;
|
||||
}
|
||||
@ -85,11 +80,11 @@ final class ConfinedSession extends MemorySessionImpl {
|
||||
}
|
||||
|
||||
void justClose() {
|
||||
checkValidStateSlow();
|
||||
checkValidState();
|
||||
if (state == 0 || state - ((int)ASYNC_RELEASE_COUNT.getVolatile(this)) == 0) {
|
||||
state = CLOSED;
|
||||
} else {
|
||||
throw new IllegalStateException("Session is acquired by " + state + " clients");
|
||||
throw alreadyAcquired(state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +98,7 @@ final class ConfinedSession extends MemorySessionImpl {
|
||||
cleanup.next = fst;
|
||||
fst = cleanup;
|
||||
} else {
|
||||
throw new IllegalStateException("Already closed!");
|
||||
throw alreadyClosed();
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,7 +109,7 @@ final class ConfinedSession extends MemorySessionImpl {
|
||||
fst = ResourceCleanup.CLOSED_LIST;
|
||||
cleanup(prev);
|
||||
} else {
|
||||
throw new IllegalStateException("Attempt to cleanup an already closed resource list");
|
||||
throw alreadyClosed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ import jdk.internal.vm.annotation.ForceInline;
|
||||
* a base object (typically an array). To enhance performances, the access to the base object needs to feature
|
||||
* sharp type information, as well as sharp null-check information. For this reason, many concrete subclasses
|
||||
* of {@link HeapMemorySegmentImpl} are defined (e.g. {@link OfFloat}, so that each subclass can override the
|
||||
* {@link HeapMemorySegmentImpl#base()} method so that it returns an array of the correct (sharp) type. Note that
|
||||
* {@link HeapMemorySegmentImpl#unsafeGetBase()} method so that it returns an array of the correct (sharp) type. Note that
|
||||
* the field type storing the 'base' coordinate is just Object; similarly, all the constructor in the subclasses
|
||||
* accept an Object 'base' parameter instead of a sharper type (e.g. {@code byte[]}). This is deliberate, as
|
||||
* using sharper types would require use of type-conversions, which in turn would inhibit some C2 optimizations,
|
||||
@ -60,54 +60,51 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
final Object base;
|
||||
|
||||
@ForceInline
|
||||
HeapMemorySegmentImpl(long offset, Object base, long length, int mask) {
|
||||
super(length, mask, MemorySessionImpl.GLOBAL);
|
||||
HeapMemorySegmentImpl(long offset, Object base, long length, boolean readOnly) {
|
||||
super(length, readOnly, MemorySessionImpl.GLOBAL);
|
||||
this.offset = offset;
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
abstract Object base();
|
||||
|
||||
@Override
|
||||
long min() {
|
||||
public long unsafeGetOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
abstract HeapMemorySegmentImpl dup(long offset, long size, int mask, MemorySession session);
|
||||
abstract HeapMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session);
|
||||
|
||||
@Override
|
||||
ByteBuffer makeByteBuffer() {
|
||||
if (!(base() instanceof byte[])) {
|
||||
if (!(base instanceof byte[])) {
|
||||
throw new UnsupportedOperationException("Not an address to an heap-allocated byte array");
|
||||
}
|
||||
JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess();
|
||||
return nioAccess.newHeapByteBuffer((byte[]) base(), (int)min() - BYTE_ARR_BASE, (int) byteSize(), null);
|
||||
return nioAccess.newHeapByteBuffer((byte[])base, (int)offset - BYTE_ARR_BASE, (int) byteSize(), null);
|
||||
}
|
||||
|
||||
// factories
|
||||
|
||||
public static class OfByte extends HeapMemorySegmentImpl {
|
||||
|
||||
OfByte(long offset, Object base, long length, int mask) {
|
||||
super(offset, base, length, mask);
|
||||
OfByte(long offset, Object base, long length, boolean readOnly) {
|
||||
super(offset, base, length, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfByte dup(long offset, long size, int mask, MemorySession session) {
|
||||
return new OfByte(this.offset + offset, base, size, mask);
|
||||
OfByte dup(long offset, long size, boolean readOnly, MemorySession session) {
|
||||
return new OfByte(this.offset + offset, base, size, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
byte[] base() {
|
||||
public byte[] unsafeGetBase() {
|
||||
return (byte[])Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(byte[] arr) {
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_BYTE_INDEX_SCALE;
|
||||
return new OfByte(Unsafe.ARRAY_BYTE_BASE_OFFSET, arr, byteSize, DEFAULT_MODES);
|
||||
return new OfByte(Unsafe.ARRAY_BYTE_BASE_OFFSET, arr, byteSize, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -118,24 +115,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
public static class OfChar extends HeapMemorySegmentImpl {
|
||||
|
||||
OfChar(long offset, Object base, long length, int mask) {
|
||||
super(offset, base, length, mask);
|
||||
OfChar(long offset, Object base, long length, boolean readOnly) {
|
||||
super(offset, base, length, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfChar dup(long offset, long size, int mask, MemorySession session) {
|
||||
return new OfChar(this.offset + offset, base, size, mask);
|
||||
OfChar dup(long offset, long size, boolean readOnly, MemorySession session) {
|
||||
return new OfChar(this.offset + offset, base, size, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
char[] base() {
|
||||
public char[] unsafeGetBase() {
|
||||
return (char[])Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(char[] arr) {
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_CHAR_INDEX_SCALE;
|
||||
return new OfChar(Unsafe.ARRAY_CHAR_BASE_OFFSET, arr, byteSize, DEFAULT_MODES);
|
||||
return new OfChar(Unsafe.ARRAY_CHAR_BASE_OFFSET, arr, byteSize, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -146,24 +143,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
public static class OfShort extends HeapMemorySegmentImpl {
|
||||
|
||||
OfShort(long offset, Object base, long length, int mask) {
|
||||
super(offset, base, length, mask);
|
||||
OfShort(long offset, Object base, long length, boolean readOnly) {
|
||||
super(offset, base, length, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfShort dup(long offset, long size, int mask, MemorySession session) {
|
||||
return new OfShort(this.offset + offset, base, size, mask);
|
||||
OfShort dup(long offset, long size, boolean readOnly, MemorySession session) {
|
||||
return new OfShort(this.offset + offset, base, size, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
short[] base() {
|
||||
public short[] unsafeGetBase() {
|
||||
return (short[])Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(short[] arr) {
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_SHORT_INDEX_SCALE;
|
||||
return new OfShort(Unsafe.ARRAY_SHORT_BASE_OFFSET, arr, byteSize, DEFAULT_MODES);
|
||||
return new OfShort(Unsafe.ARRAY_SHORT_BASE_OFFSET, arr, byteSize, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -174,24 +171,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
public static class OfInt extends HeapMemorySegmentImpl {
|
||||
|
||||
OfInt(long offset, Object base, long length, int mask) {
|
||||
super(offset, base, length, mask);
|
||||
OfInt(long offset, Object base, long length, boolean readOnly) {
|
||||
super(offset, base, length, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfInt dup(long offset, long size, int mask, MemorySession session) {
|
||||
return new OfInt(this.offset + offset, base, size, mask);
|
||||
OfInt dup(long offset, long size, boolean readOnly, MemorySession session) {
|
||||
return new OfInt(this.offset + offset, base, size, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
int[] base() {
|
||||
public int[] unsafeGetBase() {
|
||||
return (int[])Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(int[] arr) {
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_INT_INDEX_SCALE;
|
||||
return new OfInt(Unsafe.ARRAY_INT_BASE_OFFSET, arr, byteSize, DEFAULT_MODES);
|
||||
return new OfInt(Unsafe.ARRAY_INT_BASE_OFFSET, arr, byteSize, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -202,24 +199,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
public static class OfLong extends HeapMemorySegmentImpl {
|
||||
|
||||
OfLong(long offset, Object base, long length, int mask) {
|
||||
super(offset, base, length, mask);
|
||||
OfLong(long offset, Object base, long length, boolean readOnly) {
|
||||
super(offset, base, length, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfLong dup(long offset, long size, int mask, MemorySession session) {
|
||||
return new OfLong(this.offset + offset, base, size, mask);
|
||||
OfLong dup(long offset, long size, boolean readOnly, MemorySession session) {
|
||||
return new OfLong(this.offset + offset, base, size, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
long[] base() {
|
||||
public long[] unsafeGetBase() {
|
||||
return (long[])Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(long[] arr) {
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_LONG_INDEX_SCALE;
|
||||
return new OfLong(Unsafe.ARRAY_LONG_BASE_OFFSET, arr, byteSize, DEFAULT_MODES);
|
||||
return new OfLong(Unsafe.ARRAY_LONG_BASE_OFFSET, arr, byteSize, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -230,24 +227,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
public static class OfFloat extends HeapMemorySegmentImpl {
|
||||
|
||||
OfFloat(long offset, Object base, long length, int mask) {
|
||||
super(offset, base, length, mask);
|
||||
OfFloat(long offset, Object base, long length, boolean readOnly) {
|
||||
super(offset, base, length, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfFloat dup(long offset, long size, int mask, MemorySession session) {
|
||||
return new OfFloat(this.offset + offset, base, size, mask);
|
||||
OfFloat dup(long offset, long size, boolean readOnly, MemorySession session) {
|
||||
return new OfFloat(this.offset + offset, base, size, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
float[] base() {
|
||||
public float[] unsafeGetBase() {
|
||||
return (float[])Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(float[] arr) {
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_FLOAT_INDEX_SCALE;
|
||||
return new OfFloat(Unsafe.ARRAY_FLOAT_BASE_OFFSET, arr, byteSize, DEFAULT_MODES);
|
||||
return new OfFloat(Unsafe.ARRAY_FLOAT_BASE_OFFSET, arr, byteSize, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -258,24 +255,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
public static class OfDouble extends HeapMemorySegmentImpl {
|
||||
|
||||
OfDouble(long offset, Object base, long length, int mask) {
|
||||
super(offset, base, length, mask);
|
||||
OfDouble(long offset, Object base, long length, boolean readOnly) {
|
||||
super(offset, base, length, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfDouble dup(long offset, long size, int mask, MemorySession session) {
|
||||
return new OfDouble(this.offset + offset, base, size, mask);
|
||||
OfDouble dup(long offset, long size, boolean readOnly, MemorySession session) {
|
||||
return new OfDouble(this.offset + offset, base, size, readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
double[] base() {
|
||||
public double[] unsafeGetBase() {
|
||||
return (double[])Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(double[] arr) {
|
||||
Objects.requireNonNull(arr);
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
|
||||
return new OfDouble(Unsafe.ARRAY_DOUBLE_BASE_OFFSET, arr, byteSize, DEFAULT_MODES);
|
||||
return new OfDouble(Unsafe.ARRAY_DOUBLE_BASE_OFFSET, arr, byteSize, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,8 +43,8 @@ public class MappedMemorySegmentImpl extends NativeMemorySegmentImpl {
|
||||
|
||||
static ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
|
||||
|
||||
public MappedMemorySegmentImpl(long min, UnmapperProxy unmapper, long length, int mask, MemorySession session) {
|
||||
super(min, length, mask, session);
|
||||
public MappedMemorySegmentImpl(long min, UnmapperProxy unmapper, long length, boolean readOnly, MemorySession session) {
|
||||
super(min, length, readOnly, session);
|
||||
this.unmapper = unmapper;
|
||||
}
|
||||
|
||||
@ -55,8 +55,8 @@ public class MappedMemorySegmentImpl extends NativeMemorySegmentImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
MappedMemorySegmentImpl dup(long offset, long size, int mask, MemorySession session) {
|
||||
return new MappedMemorySegmentImpl(min + offset, unmapper, size, mask, session);
|
||||
MappedMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session) {
|
||||
return new MappedMemorySegmentImpl(min + offset, unmapper, size, readOnly, session);
|
||||
}
|
||||
|
||||
// mapped segment methods
|
||||
@ -95,8 +95,8 @@ public class MappedMemorySegmentImpl extends NativeMemorySegmentImpl {
|
||||
|
||||
public static class EmptyMappedMemorySegmentImpl extends MappedMemorySegmentImpl {
|
||||
|
||||
public EmptyMappedMemorySegmentImpl(int modes, MemorySession session) {
|
||||
super(0, null, 0, modes, session);
|
||||
public EmptyMappedMemorySegmentImpl(boolean readOnly, MemorySessionImpl session) {
|
||||
super(0, null, 0, readOnly, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -95,7 +95,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySessionImpl sessionImpl() {
|
||||
public MemorySessionImpl session() {
|
||||
return MemorySessionImpl.GLOBAL;
|
||||
}
|
||||
|
||||
|
@ -43,16 +43,16 @@ import sun.nio.ch.DirectBuffer;
|
||||
* This class manages the temporal bounds associated with a memory segment as well
|
||||
* as thread confinement. A session has a liveness bit, which is updated when the session is closed
|
||||
* (this operation is triggered by {@link MemorySession#close()}). This bit is consulted prior
|
||||
* to memory access (see {@link #checkValidState()}).
|
||||
* to memory access (see {@link #checkValidStateRaw()}).
|
||||
* There are two kinds of memory session: confined memory session and shared memory session.
|
||||
* A confined memory session has an associated owner thread that confines some operations to
|
||||
* associated owner thread such as {@link #close()} or {@link #checkValidState()}.
|
||||
* associated owner thread such as {@link #close()} or {@link #checkValidStateRaw()}.
|
||||
* Shared sessions do not feature an owner thread - meaning their operations can be called, in a racy
|
||||
* manner, by multiple threads. To guarantee temporal safety in the presence of concurrent thread,
|
||||
* shared sessions use a more sophisticated synchronization mechanism, which guarantees that no concurrent
|
||||
* access is possible when a session is being closed (see {@link jdk.internal.misc.ScopedMemoryAccess}).
|
||||
*/
|
||||
public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySession, SegmentAllocator {
|
||||
public abstract non-sealed class MemorySessionImpl implements MemorySession, SegmentAllocator {
|
||||
final ResourceList resourceList;
|
||||
final Cleaner.Cleanable cleanable;
|
||||
final Thread owner;
|
||||
@ -78,8 +78,7 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
|
||||
@Override
|
||||
public void addCloseAction(Runnable runnable) {
|
||||
Objects.requireNonNull(runnable);
|
||||
addInternal(runnable instanceof ResourceList.ResourceCleanup cleanup ?
|
||||
cleanup : ResourceList.ResourceCleanup.ofRunnable(runnable));
|
||||
addInternal(ResourceList.ResourceCleanup.ofRunnable(runnable));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,7 +101,7 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
|
||||
}
|
||||
|
||||
void addInternal(ResourceList.ResourceCleanup resource) {
|
||||
checkValidStateSlow();
|
||||
checkValidState();
|
||||
// Note: from here on we no longer check the session state. Two cases are possible: either the resource cleanup
|
||||
// is added to the list when the session is still open, in which case everything works ok; or the resource
|
||||
// cleanup is added while the session is being closed. In this latter case, what matters is whether we have already
|
||||
@ -141,13 +140,13 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
|
||||
public abstract void acquire0();
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public final boolean equals(Object o) {
|
||||
return (o instanceof MemorySession other) &&
|
||||
toSessionImpl(other) == this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
public final int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@ -174,7 +173,9 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
|
||||
* Returns true, if this session is still open. This method may be called in any thread.
|
||||
* @return {@code true} if this session is not closed yet.
|
||||
*/
|
||||
public abstract boolean isAlive();
|
||||
public boolean isAlive() {
|
||||
return state >= OPEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySession asNonCloseable() {
|
||||
@ -182,30 +183,27 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
|
||||
new NonCloseableView(this) : this;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static MemorySessionImpl toSessionImpl(MemorySession session) {
|
||||
return ((Scoped)session).sessionImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySessionImpl sessionImpl() {
|
||||
return this;
|
||||
return session instanceof MemorySessionImpl sessionImpl ?
|
||||
sessionImpl : ((NonCloseableView)session).session;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a faster version of {@link #checkValidStateSlow()}, which is called upon memory access, and which
|
||||
* This is a faster version of {@link #checkValidState()}, which is called upon memory access, and which
|
||||
* relies on invariants associated with the memory session implementations (volatile access
|
||||
* to the closed state bit is replaced with plain access). This method should be monomorphic,
|
||||
* to avoid virtual calls in the memory access hot path. This method is not intended as general purpose method
|
||||
* and should only be used in the memory access handle hot path; for liveness checks triggered by other API methods,
|
||||
* please use {@link #checkValidStateSlow()}.
|
||||
* please use {@link #checkValidState()}.
|
||||
*/
|
||||
@ForceInline
|
||||
public final void checkValidState() {
|
||||
public void checkValidStateRaw() {
|
||||
if (owner != null && owner != Thread.currentThread()) {
|
||||
throw new WrongThreadException("Attempted access outside owning thread");
|
||||
throw WRONG_THREAD;
|
||||
}
|
||||
if (state < OPEN) {
|
||||
throw ScopedMemoryAccess.ScopedAccessError.INSTANCE;
|
||||
throw ALREADY_CLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,11 +212,11 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
|
||||
* @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 final void checkValidStateSlow() {
|
||||
if (owner != null && Thread.currentThread() != owner) {
|
||||
throw new WrongThreadException("Attempted access outside owning thread");
|
||||
} else if (!isAlive()) {
|
||||
throw new IllegalStateException("Already closed");
|
||||
public void checkValidState() {
|
||||
try {
|
||||
checkValidStateRaw();
|
||||
} catch (ScopedMemoryAccess.ScopedAccessError error) {
|
||||
throw error.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,14 +287,9 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void justClose() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw nonCloseable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,19 +328,9 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySession asNonCloseable() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void justClose() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw nonCloseable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,17 +341,13 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
|
||||
* a strong reference to the original session, so even if the original session is dropped by the client
|
||||
* it would still be reachable by the GC, which is important if the session is implicitly closed.
|
||||
*/
|
||||
public final static class NonCloseableView implements MemorySession, Scoped {
|
||||
public final static class NonCloseableView implements MemorySession {
|
||||
final MemorySessionImpl session;
|
||||
|
||||
public NonCloseableView(MemorySessionImpl session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public MemorySessionImpl sessionImpl() {
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return session.isAlive();
|
||||
@ -461,6 +440,31 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// helper functions to centralize error handling
|
||||
|
||||
static IllegalStateException tooManyAcquires() {
|
||||
return new IllegalStateException("Session acquire limit exceeded");
|
||||
}
|
||||
|
||||
static IllegalStateException alreadyAcquired(int acquires) {
|
||||
return new IllegalStateException(String.format("Session is acquired by %d clients", acquires));
|
||||
}
|
||||
|
||||
static IllegalStateException alreadyClosed() {
|
||||
return new IllegalStateException("Already closed");
|
||||
}
|
||||
|
||||
static WrongThreadException wrongThread() {
|
||||
return new WrongThreadException("Attempted access outside owning thread");
|
||||
}
|
||||
|
||||
static UnsupportedOperationException nonCloseable() {
|
||||
return new UnsupportedOperationException("Attempted to close a non-closeable session");
|
||||
}
|
||||
|
||||
static final ScopedMemoryAccess.ScopedAccessError ALREADY_CLOSED = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::alreadyClosed);
|
||||
|
||||
static final ScopedMemoryAccess.ScopedAccessError WRONG_THREAD = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::wrongThread);
|
||||
}
|
||||
|
@ -41,14 +41,14 @@ import sun.security.action.GetBooleanAction;
|
||||
*/
|
||||
public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
public static final MemorySegment EVERYTHING = new NativeMemorySegmentImpl(0, Long.MAX_VALUE, 0, MemorySessionImpl.GLOBAL) {
|
||||
public static final MemorySegment EVERYTHING = new NativeMemorySegmentImpl(0, Long.MAX_VALUE, false, MemorySessionImpl.GLOBAL) {
|
||||
@Override
|
||||
void checkBounds(long offset, long length) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
NativeMemorySegmentImpl dup(long offset, long size, int mask, MemorySession scope) {
|
||||
NativeMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
};
|
||||
@ -64,8 +64,8 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
final long min;
|
||||
|
||||
@ForceInline
|
||||
NativeMemorySegmentImpl(long min, long length, int mask, MemorySession session) {
|
||||
super(length, mask, session);
|
||||
NativeMemorySegmentImpl(long min, long length, boolean readOnly, MemorySession session) {
|
||||
super(length, readOnly, session);
|
||||
this.min = min;
|
||||
}
|
||||
|
||||
@ -77,13 +77,13 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
NativeMemorySegmentImpl dup(long offset, long size, int mask, MemorySession session) {
|
||||
return new NativeMemorySegmentImpl(min + offset, size, mask, session);
|
||||
NativeMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session) {
|
||||
return new NativeMemorySegmentImpl(min + offset, size, readOnly, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
ByteBuffer makeByteBuffer() {
|
||||
return nioAccess.newDirectByteBuffer(min(), (int) this.length, null,
|
||||
return nioAccess.newDirectByteBuffer(min, (int) this.length, null,
|
||||
session == MemorySessionImpl.GLOBAL ? null : this);
|
||||
}
|
||||
|
||||
@ -93,12 +93,12 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
long min() {
|
||||
public long unsafeGetOffset() {
|
||||
return min;
|
||||
}
|
||||
|
||||
@Override
|
||||
Object base() {
|
||||
public Object unsafeGetBase() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
|
||||
public static MemorySegment makeNativeSegment(long bytesSize, long alignmentBytes, MemorySession session) {
|
||||
MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(session);
|
||||
sessionImpl.checkValidStateSlow();
|
||||
sessionImpl.checkValidState();
|
||||
if (VM.isDirectMemoryPageAligned()) {
|
||||
alignmentBytes = Math.max(alignmentBytes, nioAccess.pageSize());
|
||||
}
|
||||
@ -127,7 +127,7 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
}
|
||||
long alignedBuf = Utils.alignUp(buf, alignmentBytes);
|
||||
AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(buf, alignedSize,
|
||||
DEFAULT_MODES, session);
|
||||
false, session);
|
||||
sessionImpl.addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() {
|
||||
@Override
|
||||
public void cleanup() {
|
||||
@ -143,9 +143,8 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
}
|
||||
|
||||
public static MemorySegment makeNativeSegmentUnchecked(MemoryAddress min, long bytesSize, MemorySession session) {
|
||||
MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(session);
|
||||
sessionImpl.checkValidStateSlow();
|
||||
AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(min.toRawLongValue(), bytesSize, DEFAULT_MODES, session);
|
||||
MemorySessionImpl.toSessionImpl(session).checkValidState();
|
||||
AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(min.toRawLongValue(), bytesSize, false, session);
|
||||
return segment;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,14 @@
|
||||
|
||||
package jdk.internal.foreign;
|
||||
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
import java.lang.foreign.MemorySession;
|
||||
|
||||
public interface Scoped {
|
||||
MemorySessionImpl sessionImpl();
|
||||
@ForceInline
|
||||
default MemorySessionImpl sessionImpl() {
|
||||
return MemorySessionImpl.toSessionImpl(session());
|
||||
}
|
||||
MemorySession session();
|
||||
}
|
||||
|
@ -56,10 +56,10 @@ class SharedSession extends MemorySessionImpl {
|
||||
value = (int) STATE.getVolatile(this);
|
||||
if (value < OPEN) {
|
||||
//segment is not open!
|
||||
throw new IllegalStateException("Already closed");
|
||||
throw alreadyClosed();
|
||||
} else if (value == MAX_FORKS) {
|
||||
//overflow
|
||||
throw new IllegalStateException("Session acquire limit exceeded");
|
||||
throw tooManyAcquires();
|
||||
}
|
||||
} while (!STATE.compareAndSet(this, value, value + 1));
|
||||
}
|
||||
@ -72,7 +72,7 @@ class SharedSession extends MemorySessionImpl {
|
||||
value = (int) STATE.getVolatile(this);
|
||||
if (value <= OPEN) {
|
||||
//cannot get here - we can't close segment twice
|
||||
throw new IllegalStateException("Already closed");
|
||||
throw alreadyClosed();
|
||||
}
|
||||
} while (!STATE.compareAndSet(this, value, value - 1));
|
||||
}
|
||||
@ -80,22 +80,17 @@ class SharedSession extends MemorySessionImpl {
|
||||
void justClose() {
|
||||
int prevState = (int) STATE.compareAndExchange(this, OPEN, CLOSING);
|
||||
if (prevState < 0) {
|
||||
throw new IllegalStateException("Already closed");
|
||||
throw alreadyClosed();
|
||||
} else if (prevState != OPEN) {
|
||||
throw new IllegalStateException("Session is acquired by " + prevState + " clients");
|
||||
throw alreadyAcquired(prevState);
|
||||
}
|
||||
boolean success = SCOPED_MEMORY_ACCESS.closeScope(this);
|
||||
STATE.setVolatile(this, success ? CLOSED : OPEN);
|
||||
if (!success) {
|
||||
throw new IllegalStateException("Session is acquired by 1 client");
|
||||
throw alreadyAcquired(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return (int) STATE.getVolatile(this) != CLOSED;
|
||||
}
|
||||
|
||||
/**
|
||||
* A shared resource list; this implementation has to handle add vs. add races, as well as add vs. cleanup races.
|
||||
*/
|
||||
@ -117,7 +112,7 @@ class SharedSession extends MemorySessionImpl {
|
||||
ResourceCleanup prev = (ResourceCleanup) FST.getVolatile(this);
|
||||
if (prev == ResourceCleanup.CLOSED_LIST) {
|
||||
// too late
|
||||
throw new IllegalStateException("Already closed");
|
||||
throw alreadyClosed();
|
||||
}
|
||||
cleanup.next = prev;
|
||||
if (FST.compareAndSet(this, prev, cleanup)) {
|
||||
@ -144,7 +139,7 @@ class SharedSession extends MemorySessionImpl {
|
||||
}
|
||||
cleanup(prev);
|
||||
} else {
|
||||
throw new IllegalStateException("Attempt to cleanup an already closed resource list");
|
||||
throw alreadyClosed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -445,11 +445,6 @@ public class SharedUtils {
|
||||
return MemorySessionImpl.GLOBAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySessionImpl sessionImpl() {
|
||||
return MemorySessionImpl.GLOBAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaList copy() {
|
||||
return this;
|
||||
|
@ -320,7 +320,7 @@ public non-sealed class LinuxAArch64VaList implements VaList, Scoped {
|
||||
@Override
|
||||
public void skip(MemoryLayout... layouts) {
|
||||
Objects.requireNonNull(layouts);
|
||||
MemorySessionImpl.toSessionImpl(session()).checkValidStateSlow();
|
||||
sessionImpl().checkValidState();
|
||||
for (MemoryLayout layout : layouts) {
|
||||
Objects.requireNonNull(layout);
|
||||
TypeClass typeClass = TypeClass.classifyLayout(layout);
|
||||
@ -350,11 +350,6 @@ public non-sealed class LinuxAArch64VaList implements VaList, Scoped {
|
||||
return segment.session();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySessionImpl sessionImpl() {
|
||||
return MemorySessionImpl.toSessionImpl(session());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaList copy() {
|
||||
MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.session());
|
||||
|
@ -127,7 +127,7 @@ public non-sealed class MacOsAArch64VaList implements VaList, Scoped {
|
||||
@Override
|
||||
public void skip(MemoryLayout... layouts) {
|
||||
Objects.requireNonNull(layouts);
|
||||
MemorySessionImpl.toSessionImpl(session()).checkValidStateSlow();
|
||||
sessionImpl().checkValidState();
|
||||
|
||||
for (MemoryLayout layout : layouts) {
|
||||
Objects.requireNonNull(layout);
|
||||
@ -152,14 +152,9 @@ public non-sealed class MacOsAArch64VaList implements VaList, Scoped {
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySessionImpl sessionImpl() {
|
||||
return MemorySessionImpl.toSessionImpl(session());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaList copy() {
|
||||
MemorySessionImpl.toSessionImpl(session()).checkValidStateSlow();
|
||||
sessionImpl().checkValidState();
|
||||
return new MacOsAArch64VaList(segment, session);
|
||||
}
|
||||
|
||||
@ -174,7 +169,7 @@ public non-sealed class MacOsAArch64VaList implements VaList, Scoped {
|
||||
private final List<SimpleVaArg> args = new ArrayList<>();
|
||||
|
||||
public Builder(MemorySession session) {
|
||||
MemorySessionImpl.toSessionImpl(session).checkValidStateSlow();
|
||||
MemorySessionImpl.toSessionImpl(session).checkValidState();
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,7 @@ public non-sealed class SysVVaList implements VaList, Scoped {
|
||||
@Override
|
||||
public void skip(MemoryLayout... layouts) {
|
||||
Objects.requireNonNull(layouts);
|
||||
MemorySessionImpl.toSessionImpl(session()).checkValidStateSlow();
|
||||
sessionImpl().checkValidState();
|
||||
for (MemoryLayout layout : layouts) {
|
||||
Objects.requireNonNull(layout);
|
||||
TypeClass typeClass = TypeClass.classifyLayout(layout);
|
||||
@ -304,11 +304,6 @@ public non-sealed class SysVVaList implements VaList, Scoped {
|
||||
return segment.session();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySessionImpl sessionImpl() {
|
||||
return MemorySessionImpl.toSessionImpl(session());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaList copy() {
|
||||
MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.session());
|
||||
|
@ -133,7 +133,7 @@ public non-sealed class WinVaList implements VaList, Scoped {
|
||||
@Override
|
||||
public void skip(MemoryLayout... layouts) {
|
||||
Objects.requireNonNull(layouts);
|
||||
MemorySessionImpl.toSessionImpl(session()).checkValidStateSlow();
|
||||
sessionImpl().checkValidState();
|
||||
Stream.of(layouts).forEach(Objects::requireNonNull);
|
||||
segment = segment.asSlice(layouts.length * VA_SLOT_SIZE_BYTES);
|
||||
}
|
||||
@ -152,14 +152,9 @@ public non-sealed class WinVaList implements VaList, Scoped {
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySessionImpl sessionImpl() {
|
||||
return MemorySessionImpl.toSessionImpl(session());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaList copy() {
|
||||
MemorySessionImpl.toSessionImpl(session).checkValidStateSlow();
|
||||
sessionImpl().checkValidState();
|
||||
return new WinVaList(segment, session);
|
||||
}
|
||||
|
||||
@ -174,7 +169,7 @@ public non-sealed class WinVaList implements VaList, Scoped {
|
||||
private final List<SimpleVaArg> args = new ArrayList<>();
|
||||
|
||||
public Builder(MemorySession session) {
|
||||
MemorySessionImpl.toSessionImpl(session).checkValidStateSlow();
|
||||
MemorySessionImpl.toSessionImpl(session).checkValidState();
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
try {
|
||||
return get$Type$Internal(session, base, offset);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
private $type$ get$Type$Internal(MemorySessionImpl session, Object base, long offset) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.get$Type$(base, offset);
|
||||
} finally {
|
||||
@ -24,7 +24,7 @@
|
||||
try {
|
||||
put$Type$Internal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
private void put$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
UNSAFE.put$Type$(base, offset, value);
|
||||
} finally {
|
||||
@ -46,7 +46,7 @@
|
||||
try {
|
||||
return get$Type$UnalignedInternal(session, base, offset, be);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
private $type$ get$Type$UnalignedInternal(MemorySessionImpl session, Object base, long offset, boolean be) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.get$Type$Unaligned(base, offset, be);
|
||||
} finally {
|
||||
@ -67,7 +67,7 @@
|
||||
try {
|
||||
put$Type$UnalignedInternal(session, base, offset, value, be);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@
|
||||
private void put$Type$UnalignedInternal(MemorySessionImpl session, Object base, long offset, $type$ value, boolean be) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
UNSAFE.put$Type$Unaligned(base, offset, value, be);
|
||||
} finally {
|
||||
@ -89,7 +89,7 @@
|
||||
try {
|
||||
return get$Type$VolatileInternal(session, base, offset);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@
|
||||
private $type$ get$Type$VolatileInternal(MemorySessionImpl session, Object base, long offset) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.get$Type$Volatile(base, offset);
|
||||
} finally {
|
||||
@ -110,7 +110,7 @@
|
||||
try {
|
||||
put$Type$VolatileInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@
|
||||
private void put$Type$VolatileInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
UNSAFE.put$Type$Volatile(base, offset, value);
|
||||
} finally {
|
||||
@ -131,7 +131,7 @@
|
||||
try {
|
||||
return get$Type$AcquireInternal(session, base, offset);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@
|
||||
private $type$ get$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.get$Type$Acquire(base, offset);
|
||||
} finally {
|
||||
@ -152,7 +152,7 @@
|
||||
try {
|
||||
put$Type$ReleaseInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@
|
||||
private void put$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
UNSAFE.put$Type$Release(base, offset, value);
|
||||
} finally {
|
||||
@ -173,7 +173,7 @@
|
||||
try {
|
||||
return get$Type$OpaqueInternal(session, base, offset);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@
|
||||
private $type$ get$Type$OpaqueInternal(MemorySessionImpl session, Object base, long offset) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.get$Type$Opaque(base, offset);
|
||||
} finally {
|
||||
@ -193,7 +193,7 @@
|
||||
try {
|
||||
put$Type$OpaqueInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,7 +201,7 @@
|
||||
private void put$Type$OpaqueInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
UNSAFE.put$Type$Opaque(base, offset, value);
|
||||
} finally {
|
||||
@ -214,7 +214,7 @@
|
||||
try {
|
||||
return compareAndSet$Type$Internal(session, base, offset, expected, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,7 +222,7 @@
|
||||
private boolean compareAndSet$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.compareAndSet$Type$(base, offset, expected, value);
|
||||
} finally {
|
||||
@ -235,7 +235,7 @@
|
||||
try {
|
||||
return compareAndExchange$Type$Internal(session, base, offset, expected, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,7 +243,7 @@
|
||||
private $type$ compareAndExchange$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.compareAndExchange$Type$(base, offset, expected, value);
|
||||
} finally {
|
||||
@ -256,7 +256,7 @@
|
||||
try {
|
||||
return compareAndExchange$Type$AcquireInternal(session, base, offset, expected, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,7 +264,7 @@
|
||||
private $type$ compareAndExchange$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.compareAndExchange$Type$Acquire(base, offset, expected, value);
|
||||
} finally {
|
||||
@ -277,7 +277,7 @@
|
||||
try {
|
||||
return compareAndExchange$Type$ReleaseInternal(session, base, offset, expected, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,7 +285,7 @@
|
||||
private $type$ compareAndExchange$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.compareAndExchange$Type$Release(base, offset, expected, value);
|
||||
} finally {
|
||||
@ -298,7 +298,7 @@
|
||||
try {
|
||||
return weakCompareAndSet$Type$PlainInternal(session, base, offset, expected, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,7 +306,7 @@
|
||||
private boolean weakCompareAndSet$Type$PlainInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.weakCompareAndSet$Type$Plain(base, offset, expected, value);
|
||||
} finally {
|
||||
@ -319,7 +319,7 @@
|
||||
try {
|
||||
return weakCompareAndSet$Type$Internal(session, base, offset, expected, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,7 +327,7 @@
|
||||
private boolean weakCompareAndSet$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.weakCompareAndSet$Type$(base, offset, expected, value);
|
||||
} finally {
|
||||
@ -340,7 +340,7 @@
|
||||
try {
|
||||
return weakCompareAndSet$Type$AcquireInternal(session, base, offset, expected, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,7 +348,7 @@
|
||||
private boolean weakCompareAndSet$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.weakCompareAndSet$Type$Acquire(base, offset, expected, value);
|
||||
} finally {
|
||||
@ -361,7 +361,7 @@
|
||||
try {
|
||||
return weakCompareAndSet$Type$ReleaseInternal(session, base, offset, expected, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,7 +369,7 @@
|
||||
private boolean weakCompareAndSet$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.weakCompareAndSet$Type$Release(base, offset, expected, value);
|
||||
} finally {
|
||||
@ -382,7 +382,7 @@
|
||||
try {
|
||||
return getAndSet$Type$Internal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -390,7 +390,7 @@
|
||||
private $type$ getAndSet$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndSet$Type$(base, offset, value);
|
||||
} finally {
|
||||
@ -403,7 +403,7 @@
|
||||
try {
|
||||
return getAndSet$Type$AcquireInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -411,7 +411,7 @@
|
||||
private $type$ getAndSet$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndSet$Type$Acquire(base, offset, value);
|
||||
} finally {
|
||||
@ -424,7 +424,7 @@
|
||||
try {
|
||||
return getAndSet$Type$ReleaseInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,7 +432,7 @@
|
||||
private $type$ getAndSet$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndSet$Type$Release(base, offset, value);
|
||||
} finally {
|
||||
@ -447,7 +447,7 @@
|
||||
try {
|
||||
return getAndAdd$Type$Internal(session, base, offset, delta);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,7 +455,7 @@
|
||||
private $type$ getAndAdd$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ delta) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndAdd$Type$(base, offset, delta);
|
||||
} finally {
|
||||
@ -468,7 +468,7 @@
|
||||
try {
|
||||
return getAndAdd$Type$AcquireInternal(session, base, offset, delta);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@
|
||||
private $type$ getAndAdd$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ delta) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndAdd$Type$Acquire(base, offset, delta);
|
||||
} finally {
|
||||
@ -489,7 +489,7 @@
|
||||
try {
|
||||
return getAndAdd$Type$ReleaseInternal(session, base, offset, delta);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,7 +497,7 @@
|
||||
private $type$ getAndAdd$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ delta) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndAdd$Type$Release(base, offset, delta);
|
||||
} finally {
|
||||
@ -512,7 +512,7 @@
|
||||
try {
|
||||
return getAndBitwiseOr$Type$Internal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -520,7 +520,7 @@
|
||||
private $type$ getAndBitwiseOr$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndBitwiseOr$Type$(base, offset, value);
|
||||
} finally {
|
||||
@ -533,7 +533,7 @@
|
||||
try {
|
||||
return getAndBitwiseOr$Type$AcquireInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,7 +541,7 @@
|
||||
private $type$ getAndBitwiseOr$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndBitwiseOr$Type$Acquire(base, offset, value);
|
||||
} finally {
|
||||
@ -554,7 +554,7 @@
|
||||
try {
|
||||
return getAndBitwiseOr$Type$ReleaseInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,7 +562,7 @@
|
||||
private $type$ getAndBitwiseOr$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndBitwiseOr$Type$Release(base, offset, value);
|
||||
} finally {
|
||||
@ -575,7 +575,7 @@
|
||||
try {
|
||||
return getAndBitwiseAnd$Type$Internal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -583,7 +583,7 @@
|
||||
private $type$ getAndBitwiseAnd$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndBitwiseAnd$Type$(base, offset, value);
|
||||
} finally {
|
||||
@ -596,7 +596,7 @@
|
||||
try {
|
||||
return getAndBitwiseAnd$Type$AcquireInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -604,7 +604,7 @@
|
||||
private $type$ getAndBitwiseAnd$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndBitwiseAnd$Type$Acquire(base, offset, value);
|
||||
} finally {
|
||||
@ -617,7 +617,7 @@
|
||||
try {
|
||||
return getAndBitwiseAnd$Type$ReleaseInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -625,7 +625,7 @@
|
||||
private $type$ getAndBitwiseAnd$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndBitwiseAnd$Type$Release(base, offset, value);
|
||||
} finally {
|
||||
@ -638,7 +638,7 @@
|
||||
try {
|
||||
return getAndBitwiseXor$Type$Internal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -646,7 +646,7 @@
|
||||
private $type$ getAndBitwiseXor$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndBitwiseXor$Type$(base, offset, value);
|
||||
} finally {
|
||||
@ -659,7 +659,7 @@
|
||||
try {
|
||||
return getAndBitwiseXor$Type$AcquireInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -667,7 +667,7 @@
|
||||
private $type$ getAndBitwiseXor$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndBitwiseXor$Type$Acquire(base, offset, value);
|
||||
} finally {
|
||||
@ -680,7 +680,7 @@
|
||||
try {
|
||||
return getAndBitwiseXor$Type$ReleaseInternal(session, base, offset, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,7 +688,7 @@
|
||||
private $type$ getAndBitwiseXor$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return UNSAFE.getAndBitwiseXor$Type$Release(base, offset, value);
|
||||
} finally {
|
||||
|
@ -32,6 +32,7 @@ import java.lang.annotation.Target;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.ref.Reference;
|
||||
import java.io.FileDescriptor;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jdk.internal.access.JavaNioAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
@ -55,10 +56,10 @@ import jdk.internal.vm.vector.VectorSupport;
|
||||
* a memory region while another thread is releasing it.
|
||||
* <p>
|
||||
* This class provides tools to manage races when multiple threads are accessing and/or releasing the same memory
|
||||
* region concurrently. More specifically, when a thread wants to release a memory region, it should call the
|
||||
* {@link MemorySessionImpl#close()} method. This method initiates thread-local handshakes with all the other VM threads,
|
||||
* session concurrently. More specifically, when a thread wants to release a memory session, it should call the
|
||||
* {@link ScopedMemoryAccess#closeScope(MemorySessionImpl)} method. This method initiates thread-local handshakes with all the other VM threads,
|
||||
* which are then stopped one by one. If any thread is found accessing a resource associated to the very memory session
|
||||
* being closed, the handshake fails, and the session cannot be closed.
|
||||
* being closed, the handshake fails, and the session will not be closed.
|
||||
* <p>
|
||||
* This synchronization strategy relies on the idea that accessing memory is atomic with respect to checking the
|
||||
* validity of the session associated with that memory region - that is, a thread that wants to perform memory access will be
|
||||
@ -97,12 +98,20 @@ public class ScopedMemoryAccess {
|
||||
}
|
||||
|
||||
public static final class ScopedAccessError extends Error {
|
||||
private ScopedAccessError() {
|
||||
super("Attempt to access an already released memory resource", null, false, false);
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private final Supplier<RuntimeException> runtimeExceptionSupplier;
|
||||
|
||||
public ScopedAccessError(Supplier<RuntimeException> runtimeExceptionSupplier) {
|
||||
super("Invalid memory access", null, false, false);
|
||||
this.runtimeExceptionSupplier = runtimeExceptionSupplier;
|
||||
}
|
||||
|
||||
static final long serialVersionUID = 1L;
|
||||
|
||||
public static final ScopedAccessError INSTANCE = new ScopedAccessError();
|
||||
public final RuntimeException newRuntimeException() {
|
||||
return runtimeExceptionSupplier.get();
|
||||
}
|
||||
}
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
|
||||
@ -112,64 +121,64 @@ public class ScopedMemoryAccess {
|
||||
// bulk ops
|
||||
|
||||
@ForceInline
|
||||
public void copyMemory(MemorySessionImpl srcScope, MemorySessionImpl dstScope,
|
||||
public void copyMemory(MemorySessionImpl srcSession, MemorySessionImpl dstSession,
|
||||
Object srcBase, long srcOffset,
|
||||
Object destBase, long destOffset,
|
||||
long bytes) {
|
||||
try {
|
||||
copyMemoryInternal(srcScope, dstScope, srcBase, srcOffset, destBase, destOffset, bytes);
|
||||
copyMemoryInternal(srcSession, dstSession, srcBase, srcOffset, destBase, destOffset, bytes);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ForceInline @Scoped
|
||||
private void copyMemoryInternal(MemorySessionImpl srcScope, MemorySessionImpl dstScope,
|
||||
private void copyMemoryInternal(MemorySessionImpl srcSession, MemorySessionImpl dstSession,
|
||||
Object srcBase, long srcOffset,
|
||||
Object destBase, long destOffset,
|
||||
long bytes) {
|
||||
try {
|
||||
if (srcScope != null) {
|
||||
srcScope.checkValidState();
|
||||
if (srcSession != null) {
|
||||
srcSession.checkValidStateRaw();
|
||||
}
|
||||
if (dstScope != null) {
|
||||
dstScope.checkValidState();
|
||||
if (dstSession != null) {
|
||||
dstSession.checkValidStateRaw();
|
||||
}
|
||||
UNSAFE.copyMemory(srcBase, srcOffset, destBase, destOffset, bytes);
|
||||
} finally {
|
||||
Reference.reachabilityFence(srcScope);
|
||||
Reference.reachabilityFence(dstScope);
|
||||
Reference.reachabilityFence(srcSession);
|
||||
Reference.reachabilityFence(dstSession);
|
||||
}
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public void copySwapMemory(MemorySessionImpl srcScope, MemorySessionImpl dstScope,
|
||||
public void copySwapMemory(MemorySessionImpl srcSession, MemorySessionImpl dstSession,
|
||||
Object srcBase, long srcOffset,
|
||||
Object destBase, long destOffset,
|
||||
long bytes, long elemSize) {
|
||||
try {
|
||||
copySwapMemoryInternal(srcScope, dstScope, srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
|
||||
copySwapMemoryInternal(srcSession, dstSession, srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ForceInline @Scoped
|
||||
private void copySwapMemoryInternal(MemorySessionImpl srcScope, MemorySessionImpl dstScope,
|
||||
private void copySwapMemoryInternal(MemorySessionImpl srcSession, MemorySessionImpl dstSession,
|
||||
Object srcBase, long srcOffset,
|
||||
Object destBase, long destOffset,
|
||||
long bytes, long elemSize) {
|
||||
try {
|
||||
if (srcScope != null) {
|
||||
srcScope.checkValidState();
|
||||
if (srcSession != null) {
|
||||
srcSession.checkValidStateRaw();
|
||||
}
|
||||
if (dstScope != null) {
|
||||
dstScope.checkValidState();
|
||||
if (dstSession != null) {
|
||||
dstSession.checkValidStateRaw();
|
||||
}
|
||||
UNSAFE.copySwapMemory(srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
|
||||
} finally {
|
||||
Reference.reachabilityFence(srcScope);
|
||||
Reference.reachabilityFence(dstScope);
|
||||
Reference.reachabilityFence(srcSession);
|
||||
Reference.reachabilityFence(dstSession);
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +187,7 @@ public class ScopedMemoryAccess {
|
||||
try {
|
||||
setMemoryInternal(session, o, offset, bytes, value);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,7 +195,7 @@ public class ScopedMemoryAccess {
|
||||
private void setMemoryInternal(MemorySessionImpl session, Object o, long offset, long bytes, byte value) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
UNSAFE.setMemory(o, offset, bytes, value);
|
||||
} finally {
|
||||
@ -195,35 +204,35 @@ public class ScopedMemoryAccess {
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public int vectorizedMismatch(MemorySessionImpl aScope, MemorySessionImpl bScope,
|
||||
public int vectorizedMismatch(MemorySessionImpl aSession, MemorySessionImpl bSession,
|
||||
Object a, long aOffset,
|
||||
Object b, long bOffset,
|
||||
int length,
|
||||
int log2ArrayIndexScale) {
|
||||
try {
|
||||
return vectorizedMismatchInternal(aScope, bScope, a, aOffset, b, bOffset, length, log2ArrayIndexScale);
|
||||
return vectorizedMismatchInternal(aSession, bSession, a, aOffset, b, bOffset, length, log2ArrayIndexScale);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ForceInline @Scoped
|
||||
private int vectorizedMismatchInternal(MemorySessionImpl aScope, MemorySessionImpl bScope,
|
||||
private int vectorizedMismatchInternal(MemorySessionImpl aSession, MemorySessionImpl bSession,
|
||||
Object a, long aOffset,
|
||||
Object b, long bOffset,
|
||||
int length,
|
||||
int log2ArrayIndexScale) {
|
||||
try {
|
||||
if (aScope != null) {
|
||||
aScope.checkValidState();
|
||||
if (aSession != null) {
|
||||
aSession.checkValidStateRaw();
|
||||
}
|
||||
if (bScope != null) {
|
||||
bScope.checkValidState();
|
||||
if (bSession != null) {
|
||||
bSession.checkValidStateRaw();
|
||||
}
|
||||
return ArraysSupport.vectorizedMismatch(a, aOffset, b, bOffset, length, log2ArrayIndexScale);
|
||||
} finally {
|
||||
Reference.reachabilityFence(aScope);
|
||||
Reference.reachabilityFence(bScope);
|
||||
Reference.reachabilityFence(aSession);
|
||||
Reference.reachabilityFence(bSession);
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,7 +241,7 @@ public class ScopedMemoryAccess {
|
||||
try {
|
||||
return isLoadedInternal(session, address, isSync, size);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,7 +249,7 @@ public class ScopedMemoryAccess {
|
||||
public boolean isLoadedInternal(MemorySessionImpl session, long address, boolean isSync, long size) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
return SharedSecrets.getJavaNioAccess().isLoaded(address, isSync, size);
|
||||
} finally {
|
||||
@ -253,7 +262,7 @@ public class ScopedMemoryAccess {
|
||||
try {
|
||||
loadInternal(session, address, isSync, size);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,7 +270,7 @@ public class ScopedMemoryAccess {
|
||||
public void loadInternal(MemorySessionImpl session, long address, boolean isSync, long size) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
SharedSecrets.getJavaNioAccess().load(address, isSync, size);
|
||||
} finally {
|
||||
@ -274,7 +283,7 @@ public class ScopedMemoryAccess {
|
||||
try {
|
||||
unloadInternal(session, address, isSync, size);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,7 +291,7 @@ public class ScopedMemoryAccess {
|
||||
public void unloadInternal(MemorySessionImpl session, long address, boolean isSync, long size) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
SharedSecrets.getJavaNioAccess().unload(address, isSync, size);
|
||||
} finally {
|
||||
@ -295,7 +304,7 @@ public class ScopedMemoryAccess {
|
||||
try {
|
||||
forceInternal(session, fd, address, isSync, index, length);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,7 +312,7 @@ public class ScopedMemoryAccess {
|
||||
public void forceInternal(MemorySessionImpl session, FileDescriptor fd, long address, boolean isSync, long index, long length) {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
}
|
||||
SharedSecrets.getJavaNioAccess().force(fd, address, isSync, index, length);
|
||||
} finally {
|
||||
@ -333,7 +342,7 @@ public class ScopedMemoryAccess {
|
||||
s,
|
||||
defaultImpl);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,7 +356,7 @@ public class ScopedMemoryAccess {
|
||||
S s,
|
||||
VectorSupport.LoadOperation<AbstractMemorySegmentImpl, V, S> defaultImpl) {
|
||||
try {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
|
||||
return VectorSupport.load(vmClass, e, length,
|
||||
msp.unsafeGetBase(), msp.unsafeGetOffset() + offset,
|
||||
@ -378,7 +387,7 @@ public class ScopedMemoryAccess {
|
||||
s, offsetInRange,
|
||||
defaultImpl);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -393,7 +402,7 @@ public class ScopedMemoryAccess {
|
||||
S s, int offsetInRange,
|
||||
VectorSupport.LoadVectorMaskedOperation<AbstractMemorySegmentImpl, V, S, M> defaultImpl) {
|
||||
try {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
|
||||
return VectorSupport.loadMasked(vmClass, maskClass, e, length,
|
||||
msp.unsafeGetBase(), msp.unsafeGetOffset() + offset, m, offsetInRange,
|
||||
@ -424,7 +433,7 @@ public class ScopedMemoryAccess {
|
||||
msp, offset,
|
||||
defaultImpl);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -438,7 +447,7 @@ public class ScopedMemoryAccess {
|
||||
AbstractMemorySegmentImpl msp, long offset,
|
||||
VectorSupport.StoreVectorOperation<AbstractMemorySegmentImpl, V> defaultImpl) {
|
||||
try {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
|
||||
VectorSupport.store(vmClass, e, length,
|
||||
msp.unsafeGetBase(), msp.unsafeGetOffset() + offset,
|
||||
@ -470,7 +479,7 @@ public class ScopedMemoryAccess {
|
||||
msp, offset,
|
||||
defaultImpl);
|
||||
} catch (ScopedAccessError ex) {
|
||||
throw new IllegalStateException("This segment is already closed");
|
||||
throw ex.newRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -484,7 +493,7 @@ public class ScopedMemoryAccess {
|
||||
AbstractMemorySegmentImpl msp, long offset,
|
||||
VectorSupport.StoreVectorMaskedOperation<AbstractMemorySegmentImpl, V, M> defaultImpl) {
|
||||
try {
|
||||
session.checkValidState();
|
||||
session.checkValidStateRaw();
|
||||
|
||||
VectorSupport.storeMasked(vmClass, maskClass, e, length,
|
||||
msp.unsafeGetBase(), msp.unsafeGetOffset() + offset,
|
||||
|
@ -1199,9 +1199,6 @@ public class FileChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
private static final int MAP_MEM_SEG_DEFAULT_MODES = 0;
|
||||
private static final int MAP_MEM_SEG_READ_ONLY = 1;
|
||||
|
||||
@Override
|
||||
public MemorySegment map(MapMode mode, long offset, long size,
|
||||
MemorySession session)
|
||||
@ -1210,7 +1207,7 @@ public class FileChannelImpl
|
||||
Objects.requireNonNull(mode,"Mode is null");
|
||||
Objects.requireNonNull(session, "Session is null");
|
||||
MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(session);
|
||||
sessionImpl.checkValidStateSlow();
|
||||
sessionImpl.checkValidState();
|
||||
if (offset < 0)
|
||||
throw new IllegalArgumentException("Requested bytes offset must be >= 0.");
|
||||
if (size < 0)
|
||||
@ -1219,14 +1216,14 @@ public class FileChannelImpl
|
||||
boolean isSync = isSync(mode);
|
||||
int prot = toProt(mode);
|
||||
Unmapper unmapper = mapInternal(mode, offset, size, prot, isSync);
|
||||
int modes = MAP_MEM_SEG_DEFAULT_MODES;
|
||||
boolean readOnly = false;
|
||||
if (mode == MapMode.READ_ONLY) {
|
||||
modes |= MAP_MEM_SEG_READ_ONLY;
|
||||
readOnly = true;
|
||||
}
|
||||
if (unmapper != null) {
|
||||
AbstractMemorySegmentImpl segment =
|
||||
new MappedMemorySegmentImpl(unmapper.address(), unmapper, size,
|
||||
modes, session);
|
||||
readOnly, session);
|
||||
MemorySessionImpl.ResourceList.ResourceCleanup resource =
|
||||
new MemorySessionImpl.ResourceList.ResourceCleanup() {
|
||||
@Override
|
||||
@ -1237,7 +1234,7 @@ public class FileChannelImpl
|
||||
sessionImpl.addOrCleanupIfFail(resource);
|
||||
return segment;
|
||||
} else {
|
||||
return new MappedMemorySegmentImpl.EmptyMappedMemorySegmentImpl(modes, session);
|
||||
return new MappedMemorySegmentImpl.EmptyMappedMemorySegmentImpl(readOnly, sessionImpl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,7 +373,7 @@ public class TestByteBuffer {
|
||||
Throwable cause = ex.getCause();
|
||||
if (cause instanceof IllegalStateException) {
|
||||
//all get/set buffer operation should fail because of the session check
|
||||
assertTrue(ex.getCause().getMessage().contains("already closed"));
|
||||
assertTrue(ex.getCause().getMessage().contains("Already closed"));
|
||||
} else {
|
||||
//all other exceptions were unexpected - fail
|
||||
fail("Unexpected exception", cause);
|
||||
@ -410,7 +410,7 @@ public class TestByteBuffer {
|
||||
handle.invoke(e.getValue());
|
||||
fail();
|
||||
} catch (IllegalStateException ex) {
|
||||
assertTrue(ex.getMessage().contains("already closed"));
|
||||
assertTrue(ex.getMessage().contains("Already closed"));
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
//skip
|
||||
} catch (Throwable ex) {
|
||||
|
@ -370,8 +370,8 @@ public class TestMemorySession {
|
||||
}
|
||||
|
||||
private void keepAlive(MemorySession child, MemorySession parent) {
|
||||
MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(parent);
|
||||
sessionImpl.acquire0();
|
||||
child.addCloseAction(sessionImpl::release0);
|
||||
MemorySessionImpl parentImpl = MemorySessionImpl.toSessionImpl(parent);
|
||||
parentImpl.acquire0();
|
||||
child.addCloseAction(parentImpl::release0);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user