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

@ -30,6 +30,9 @@ import java.util.Locale;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import jdk.internal.access.JavaIOPrintStreamAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.InternalLock;
/**
* A {@code PrintStream} adds functionality to another output stream,
@ -64,6 +67,8 @@ import java.nio.charset.UnsupportedCharsetException;
public class PrintStream extends FilterOutputStream
implements Appendable, Closeable
{
// initialized to null when PrintStream is sub-classed
private final InternalLock lock;
private final boolean autoFlush;
private boolean trouble = false;
@ -112,6 +117,13 @@ public class PrintStream extends FilterOutputStream
this.charset = out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset();
this.charOut = new OutputStreamWriter(this, charset);
this.textOut = new BufferedWriter(charOut);
// use monitors when PrintStream is sub-classed
if (getClass() == PrintStream.class) {
lock = InternalLock.newLockOrNull();
} else {
lock = null;
}
}
/* Variant of the private constructor so that the given charset name
@ -206,6 +218,13 @@ public class PrintStream extends FilterOutputStream
this.charOut = new OutputStreamWriter(this, charset);
this.textOut = new BufferedWriter(charOut);
this.charset = charset;
// use monitors when PrintStream is sub-classed
if (getClass() == PrintStream.class) {
lock = InternalLock.newLockOrNull();
} else {
lock = null;
}
}
/**
@ -425,17 +444,30 @@ public class PrintStream extends FilterOutputStream
*/
@Override
public void flush() {
synchronized (this) {
if (lock != null) {
lock.lock();
try {
ensureOpen();
out.flush();
implFlush();
} finally {
lock.unlock();
}
catch (IOException x) {
trouble = true;
} else {
synchronized (this) {
implFlush();
}
}
}
private void implFlush() {
try {
ensureOpen();
out.flush();
}
catch (IOException x) {
trouble = true;
}
}
private boolean closing = false; /* To avoid recursive closing */
/**
@ -446,20 +478,33 @@ public class PrintStream extends FilterOutputStream
*/
@Override
public void close() {
synchronized (this) {
if (! closing) {
closing = true;
try {
textOut.close();
out.close();
}
catch (IOException x) {
trouble = true;
}
textOut = null;
charOut = null;
out = null;
if (lock != null) {
lock.lock();
try {
implClose();
} finally {
lock.unlock();
}
} else {
synchronized (this) {
implClose();
}
}
}
private void implClose() {
if (!closing) {
closing = true;
try {
textOut.close();
out.close();
}
catch (IOException x) {
trouble = true;
}
textOut = null;
charOut = null;
out = null;
}
}
@ -526,11 +571,17 @@ public class PrintStream extends FilterOutputStream
@Override
public void write(int b) {
try {
synchronized (this) {
ensureOpen();
out.write(b);
if ((b == '\n') && autoFlush)
out.flush();
if (lock != null) {
lock.lock();
try {
implWrite(b);
} finally {
lock.unlock();
}
} else {
synchronized (this) {
implWrite(b);
}
}
}
catch (InterruptedIOException x) {
@ -541,6 +592,13 @@ public class PrintStream extends FilterOutputStream
}
}
private void implWrite(int b) throws IOException {
ensureOpen();
out.write(b);
if ((b == '\n') && autoFlush)
out.flush();
}
/**
* Writes {@code len} bytes from the specified byte array starting at
* offset {@code off} to this stream. If automatic flushing is
@ -558,11 +616,17 @@ public class PrintStream extends FilterOutputStream
@Override
public void write(byte[] buf, int off, int len) {
try {
synchronized (this) {
ensureOpen();
out.write(buf, off, len);
if (autoFlush)
out.flush();
if (lock != null) {
lock.lock();
try {
implWrite(buf, off, len);
} finally {
lock.unlock();
}
} else {
synchronized (this) {
implWrite(buf, off, len);
}
}
}
catch (InterruptedIOException x) {
@ -573,6 +637,14 @@ public class PrintStream extends FilterOutputStream
}
}
private void implWrite(byte[] buf, int off, int len) throws IOException {
ensureOpen();
out.write(buf, off, len);
if (autoFlush)
out.flush();
}
/**
* Writes all bytes from the specified byte array to this stream. If
* automatic flushing is enabled then the {@code flush} method will be
@ -639,17 +711,16 @@ public class PrintStream extends FilterOutputStream
private void write(char[] buf) {
try {
synchronized (this) {
ensureOpen();
textOut.write(buf);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush) {
for (int i = 0; i < buf.length; i++)
if (buf[i] == '\n') {
out.flush();
break;
}
if (lock != null) {
lock.lock();
try {
implWrite(buf);
} finally {
lock.unlock();
}
} else {
synchronized (this) {
implWrite(buf);
}
}
} catch (InterruptedIOException x) {
@ -659,20 +730,37 @@ public class PrintStream extends FilterOutputStream
}
}
private void implWrite(char[] buf) throws IOException {
ensureOpen();
textOut.write(buf);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush) {
for (int i = 0; i < buf.length; i++)
if (buf[i] == '\n') {
out.flush();
break;
}
}
}
// Used to optimize away back-to-back flushing and synchronization when
// using println, but since subclasses could exist which depend on
// observing a call to print followed by newLine() we only use this if
// getClass() == PrintStream.class to avoid compatibility issues.
private void writeln(char[] buf) {
try {
synchronized (this) {
ensureOpen();
textOut.write(buf);
textOut.newLine();
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush)
out.flush();
if (lock != null) {
lock.lock();
try {
implWriteln(buf);
} finally {
lock.unlock();
}
} else {
synchronized (this) {
implWriteln(buf);
}
}
}
catch (InterruptedIOException x) {
@ -683,15 +771,29 @@ public class PrintStream extends FilterOutputStream
}
}
private void implWriteln(char[] buf) throws IOException {
ensureOpen();
textOut.write(buf);
textOut.newLine();
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush)
out.flush();
}
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
if (lock != null) {
lock.lock();
try {
implWrite(s);
} finally {
lock.unlock();
}
} else {
synchronized (this) {
implWrite(s);
}
}
}
catch (InterruptedIOException x) {
@ -702,20 +804,32 @@ public class PrintStream extends FilterOutputStream
}
}
private void implWrite(String s) throws IOException {
ensureOpen();
textOut.write(s);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
// Used to optimize away back-to-back flushing and synchronization when
// using println, but since subclasses could exist which depend on
// observing a call to print followed by newLine we only use this if
// getClass() == PrintStream.class to avoid compatibility issues.
private void writeln(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);
textOut.newLine();
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush)
out.flush();
if (lock != null) {
lock.lock();
try {
implWriteln(s);
} finally {
lock.unlock();
}
} else {
synchronized (this) {
implWriteln(s);
}
}
}
catch (InterruptedIOException x) {
@ -726,15 +840,29 @@ public class PrintStream extends FilterOutputStream
}
}
private void implWriteln(String s) throws IOException {
ensureOpen();
textOut.write(s);
textOut.newLine();
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush)
out.flush();
}
private void newLine() {
try {
synchronized (this) {
ensureOpen();
textOut.newLine();
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush)
out.flush();
if (lock != null) {
lock.lock();
try {
implNewLine();
} finally {
lock.unlock();
}
} else {
synchronized (this) {
implNewLine();
}
}
}
catch (InterruptedIOException x) {
@ -745,6 +873,15 @@ public class PrintStream extends FilterOutputStream
}
}
private void implNewLine() throws IOException {
ensureOpen();
textOut.newLine();
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush)
out.flush();
}
/* Methods that do not terminate lines */
/**
@ -1202,14 +1339,17 @@ public class PrintStream extends FilterOutputStream
*/
public PrintStream format(String format, Object ... args) {
try {
synchronized (this) {
ensureOpen();
if ((formatter == null)
|| (formatter.locale() !=
Locale.getDefault(Locale.Category.FORMAT)))
formatter = new Formatter((Appendable) this);
formatter.format(Locale.getDefault(Locale.Category.FORMAT),
format, args);
if (lock != null) {
lock.lock();
try {
implFormat(format, args);
} finally {
lock.unlock();
}
} else {
synchronized (this) {
implFormat(format, args);
}
}
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
@ -1219,6 +1359,13 @@ public class PrintStream extends FilterOutputStream
return this;
}
private void implFormat(String format, Object ... args) throws IOException {
ensureOpen();
if ((formatter == null) || (formatter.locale() != Locale.getDefault(Locale.Category.FORMAT)))
formatter = new Formatter((Appendable) this);
formatter.format(Locale.getDefault(Locale.Category.FORMAT), format, args);
}
/**
* Writes a formatted string to this output stream using the specified
* format string and arguments.
@ -1261,12 +1408,17 @@ public class PrintStream extends FilterOutputStream
*/
public PrintStream format(Locale l, String format, Object ... args) {
try {
synchronized (this) {
ensureOpen();
if ((formatter == null)
|| (formatter.locale() != l))
formatter = new Formatter(this, l);
formatter.format(l, format, args);
if (lock != null) {
lock.lock();
try {
implFormat(l, format, args);
} finally {
lock.unlock();
}
} else {
synchronized (this) {
implFormat(l, format, args);
}
}
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
@ -1276,6 +1428,13 @@ public class PrintStream extends FilterOutputStream
return this;
}
private void implFormat(Locale l, String format, Object ... args) throws IOException {
ensureOpen();
if ((formatter == null) || (formatter.locale() != l))
formatter = new Formatter(this, l);
formatter.format(l, format, args);
}
/**
* Appends the specified character sequence to this output stream.
*
@ -1376,4 +1535,13 @@ public class PrintStream extends FilterOutputStream
public Charset charset() {
return charset;
}
static {
SharedSecrets.setJavaIOCPrintStreamAccess(new JavaIOPrintStreamAccess() {
public Object lock(PrintStream ps) {
Object lock = ps.lock;
return (lock != null) ? lock : ps;
}
});
}
}