mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
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:
parent
5212535a27
commit
9583e3657e
1133 changed files with 95935 additions and 8335 deletions
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue