8284161: Implementation of Virtual Threads (Preview)

Co-authored-by: Ron Pressler <rpressler@openjdk.org>
Co-authored-by: Alan Bateman <alanb@openjdk.org>
Co-authored-by: Erik Österlund <eosterlund@openjdk.org>
Co-authored-by: Andrew Haley <aph@openjdk.org>
Co-authored-by: Rickard Bäckman <rbackman@openjdk.org>
Co-authored-by: Markus Grönlund <mgronlun@openjdk.org>
Co-authored-by: Leonid Mesnik <lmesnik@openjdk.org>
Co-authored-by: Serguei Spitsyn <sspitsyn@openjdk.org>
Co-authored-by: Chris Plummer <cjplummer@openjdk.org>
Co-authored-by: Coleen Phillimore <coleenp@openjdk.org>
Co-authored-by: Robbin Ehn <rehn@openjdk.org>
Co-authored-by: Stefan Karlsson <stefank@openjdk.org>
Co-authored-by: Thomas Schatzl <tschatzl@openjdk.org>
Co-authored-by: Sergey Kuksenko <skuksenko@openjdk.org>
Reviewed-by: lancea, eosterlund, rehn, sspitsyn, stefank, tschatzl, dfuchs, lmesnik, dcubed, kevinw, amenkov, dlong, mchung, psandoz, bpb, coleenp, smarks, egahlin, mseledtsov, coffeys, darcy
This commit is contained in:
Alan Bateman 2022-05-07 08:06:16 +00:00
parent 5212535a27
commit 9583e3657e
1133 changed files with 95935 additions and 8335 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,10 +28,12 @@ package java.net;
import sun.security.util.SecurityConstants;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.SocketChannel;
import java.util.Objects;
import java.util.Set;
@ -570,6 +572,21 @@ public class Socket implements java.io.Closeable {
/**
* Connects this socket to the server.
*
* <p> This method is {@linkplain Thread#interrupt() interruptible} in the
* following circumstances:
* <ol>
* <li> The socket is {@linkplain SocketChannel#socket() associated} with
* a {@link SocketChannel SocketChannel}.
* In that case, interrupting a thread establishing a connection will
* close the underlying channel and cause this method to throw
* {@link ClosedByInterruptException} with the interrupt status set.
* <li> The socket uses the system-default socket implementation and a
* {@linkplain Thread#isVirtual() virtual thread} is establishing a
* connection. In that case, interrupting the virtual thread will
* cause it to wakeup and close the socket. This method will then throw
* {@code SocketException} with the interrupt status set.
* </ol>
*
* @param endpoint the {@code SocketAddress}
* @throws IOException if an error occurs during the connection
* @throws java.nio.channels.IllegalBlockingModeException
@ -588,6 +605,21 @@ public class Socket implements java.io.Closeable {
* A timeout of zero is interpreted as an infinite timeout. The connection
* will then block until established or an error occurs.
*
* <p> This method is {@linkplain Thread#interrupt() interruptible} in the
* following circumstances:
* <ol>
* <li> The socket is {@linkplain SocketChannel#socket() associated} with
* a {@link SocketChannel SocketChannel}.
* In that case, interrupting a thread establishing a connection will
* close the underlying channel and cause this method to throw
* {@link ClosedByInterruptException} with the interrupt status set.
* <li> The socket uses the system-default socket implementation and a
* {@linkplain Thread#isVirtual() virtual thread} is establishing a
* connection. In that case, interrupting the virtual thread will
* cause it to wakeup and close the socket. This method will then throw
* {@code SocketException} with the interrupt status set.
* </ol>
*
* @param endpoint the {@code SocketAddress}
* @param timeout the timeout value to be used in milliseconds.
* @throws IOException if an error occurs during the connection
@ -630,7 +662,18 @@ public class Socket implements java.io.Closeable {
}
if (!created)
createImpl(true);
impl.connect(epoint, timeout);
try {
impl.connect(epoint, timeout);
} catch (SocketTimeoutException e) {
throw e;
} catch (InterruptedIOException e) {
Thread thread = Thread.currentThread();
if (thread.isVirtual() && thread.isInterrupted()) {
close();
throw new SocketException("Closed by interrupt");
}
throw e;
}
connected = true;
/*
* If the socket was not bound before the connect, it is now because
@ -886,6 +929,22 @@ public class Socket implements java.io.Closeable {
* is in non-blocking mode then the input stream's {@code read} operations
* will throw an {@link java.nio.channels.IllegalBlockingModeException}.
*
* <p> Reading from the input stream is {@linkplain Thread#interrupt()
* interruptible} in the following circumstances:
* <ol>
* <li> The socket is {@linkplain SocketChannel#socket() associated} with
* a {@link SocketChannel SocketChannel}.
* In that case, interrupting a thread reading from the input stream
* will close the underlying channel and cause the read method to
* throw {@link ClosedByInterruptException} with the interrupt
* status set.
* <li> The socket uses the system-default socket implementation and a
* {@linkplain Thread#isVirtual() virtual thread} is reading from the
* input stream. In that case, interrupting the virtual thread will
* cause it to wakeup and close the socket. The read method will then
* throw {@code SocketException} with the interrupt status set.
* </ol>
*
* <p>Under abnormal conditions the underlying connection may be
* broken by the remote host or the network software (for example
* a connection reset in the case of TCP connections). When a
@ -950,7 +1009,6 @@ public class Socket implements java.io.Closeable {
private static class SocketInputStream extends InputStream {
private final Socket parent;
private final InputStream in;
SocketInputStream(Socket parent, InputStream in) {
this.parent = parent;
this.in = in;
@ -963,13 +1021,23 @@ public class Socket implements java.io.Closeable {
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return in.read(b, off, len);
try {
return in.read(b, off, len);
} catch (SocketTimeoutException e) {
throw e;
} catch (InterruptedIOException e) {
Thread thread = Thread.currentThread();
if (thread.isVirtual() && thread.isInterrupted()) {
close();
throw new SocketException("Closed by interrupt");
}
throw e;
}
}
@Override
public int available() throws IOException {
return in.available();
}
@Override
public void close() throws IOException {
parent.close();
@ -985,6 +1053,22 @@ public class Socket implements java.io.Closeable {
* operations will throw an {@link
* java.nio.channels.IllegalBlockingModeException}.
*
* <p> Writing to the output stream is {@linkplain Thread#interrupt()
* interruptible} in the following circumstances:
* <ol>
* <li> The socket is {@linkplain SocketChannel#socket() associated} with
* a {@link SocketChannel SocketChannel}.
* In that case, interrupting a thread writing to the output stream
* will close the underlying channel and cause the write method to
* throw {@link ClosedByInterruptException} with the interrupt status
* set.
* <li> The socket uses the system-default socket implementation and a
* {@linkplain Thread#isVirtual() virtual thread} is writing to the
* output stream. In that case, interrupting the virtual thread will
* cause it to wakeup and close the socket. The write method will then
* throw {@code SocketException} with the interrupt status set.
* </ol>
*
* <p> Closing the returned {@link java.io.OutputStream OutputStream}
* will close the associated socket.
*
@ -1032,9 +1116,17 @@ public class Socket implements java.io.Closeable {
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
try {
out.write(b, off, len);
} catch (InterruptedIOException e) {
Thread thread = Thread.currentThread();
if (thread.isVirtual() && thread.isInterrupted()) {
close();
throw new SocketException("Closed by interrupt");
}
throw e;
}
}
@Override
public void close() throws IOException {
parent.close();