--- a/jdk/src/share/classes/java/io/DataInput.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/io/DataInput.java Tue Jul 09 15:26:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2013, 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
@@ -66,10 +66,10 @@
* summary="Bit values and bytes">
* <tr>
* <td></td>
- * <th id="bit">Bit Values</th>
+ * <th id="bit_a">Bit Values</th>
* </tr>
* <tr>
- * <th id="byte1">Byte 1</th>
+ * <th id="byte1_a">Byte 1</th>
* <td>
* <table border="1" cellspacing="0" width="100%">
* <tr>
@@ -92,10 +92,10 @@
* summary="Bit values and bytes">
* <tr>
* <td></td>
- * <th id="bit">Bit Values</th>
+ * <th id="bit_b">Bit Values</th>
* </tr>
* <tr>
- * <th id="byte1">Byte 1</th>
+ * <th id="byte1_b">Byte 1</th>
* <td>
* <table border="1" cellspacing="0" width="100%">
* <tr>
@@ -108,7 +108,7 @@
* </td>
* </tr>
* <tr>
- * <th id="byte2">Byte 2</th>
+ * <th id="byte2_a">Byte 2</th>
* <td>
* <table border="1" cellspacing="0" width="100%">
* <tr>
@@ -131,10 +131,10 @@
* summary="Bit values and bytes">
* <tr>
* <td></td>
- * <th id="bit">Bit Values</th>
+ * <th id="bit_c">Bit Values</th>
* </tr>
* <tr>
- * <th id="byte1">Byte 1</th>
+ * <th id="byte1_c">Byte 1</th>
* <td>
* <table border="1" cellspacing="0" width="100%">
* <tr>
@@ -148,7 +148,7 @@
* </td>
* </tr>
* <tr>
- * <th id="byte2">Byte 2</th>
+ * <th id="byte2_b">Byte 2</th>
* <td>
* <table border="1" cellspacing="0" width="100%">
* <tr>
--- a/jdk/src/share/classes/java/io/FileInputStream.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/io/FileInputStream.java Tue Jul 09 15:26:20 2013 -0700
@@ -331,7 +331,7 @@
* object associated with this file input stream.
*
* <p> The initial {@link java.nio.channels.FileChannel#position()
- * </code>position<code>} of the returned channel will be equal to the
+ * position} of the returned channel will be equal to the
* number of bytes read from the file so far. Reading bytes from this
* stream will increment the channel's position. Changing the channel's
* position, either explicitly or by reading, will change this stream's
--- a/jdk/src/share/classes/java/io/FileOutputStream.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/io/FileOutputStream.java Tue Jul 09 15:26:20 2013 -0700
@@ -358,10 +358,10 @@
/**
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
- * object associated with this file output stream. </p>
+ * object associated with this file output stream.
*
* <p> The initial {@link java.nio.channels.FileChannel#position()
- * </code>position<code>} of the returned channel will be equal to the
+ * position} of the returned channel will be equal to the
* number of bytes written to the file so far unless this stream is in
* append mode, in which case it will be equal to the size of the file.
* Writing bytes to this stream will increment the channel's position
--- a/jdk/src/share/classes/java/io/InputStreamReader.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/io/InputStreamReader.java Tue Jul 09 15:26:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, 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
@@ -33,7 +33,7 @@
/**
* An InputStreamReader is a bridge from byte streams to character streams: It
* reads bytes and decodes them into characters using a specified {@link
- * java.nio.charset.Charset <code>charset</code>}. The charset that it uses
+ * java.nio.charset.Charset charset}. The charset that it uses
* may be specified by name or may be given explicitly, or the platform's
* default charset may be accepted.
*
@@ -101,7 +101,7 @@
}
/**
- * Creates an InputStreamReader that uses the given charset. </p>
+ * Creates an InputStreamReader that uses the given charset.
*
* @param in An InputStream
* @param cs A charset
@@ -117,7 +117,7 @@
}
/**
- * Creates an InputStreamReader that uses the given charset decoder. </p>
+ * Creates an InputStreamReader that uses the given charset decoder.
*
* @param in An InputStream
* @param dec A charset decoder
--- a/jdk/src/share/classes/java/io/OutputStreamWriter.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/io/OutputStreamWriter.java Tue Jul 09 15:26:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, 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
@@ -33,7 +33,7 @@
/**
* An OutputStreamWriter is a bridge from character streams to byte streams:
* Characters written to it are encoded into bytes using a specified {@link
- * java.nio.charset.Charset <code>charset</code>}. The charset that it uses
+ * java.nio.charset.Charset charset}. The charset that it uses
* may be specified by name or may be given explicitly, or the platform's
* default charset may be accepted.
*
@@ -86,7 +86,7 @@
*
* @param charsetName
* The name of a supported
- * {@link java.nio.charset.Charset </code>charset<code>}
+ * {@link java.nio.charset.Charset charset}
*
* @exception UnsupportedEncodingException
* If the named encoding is not supported
@@ -115,7 +115,7 @@
}
/**
- * Creates an OutputStreamWriter that uses the given charset. </p>
+ * Creates an OutputStreamWriter that uses the given charset.
*
* @param out
* An OutputStream
@@ -134,7 +134,7 @@
}
/**
- * Creates an OutputStreamWriter that uses the given charset encoder. </p>
+ * Creates an OutputStreamWriter that uses the given charset encoder.
*
* @param out
* An OutputStream
--- a/jdk/src/share/classes/java/io/PipedInputStream.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/io/PipedInputStream.java Tue Jul 09 15:26:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2013, 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
@@ -39,7 +39,7 @@
* The piped input stream contains a buffer,
* decoupling read operations from write operations,
* within limits.
- * A pipe is said to be <a name=BROKEN> <i>broken</i> </a> if a
+ * A pipe is said to be <a name="BROKEN"> <i>broken</i> </a> if a
* thread that was providing data bytes to the connected
* piped output stream is no longer alive.
*
@@ -193,7 +193,7 @@
* Receives a byte of data. This method will block if no input is
* available.
* @param b the byte being received
- * @exception IOException If the pipe is <a href=#BROKEN> <code>broken</code></a>,
+ * @exception IOException If the pipe is <a href="#BROKEN"> <code>broken</code></a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed, or if an I/O error occurs.
* @since JDK1.1
@@ -219,7 +219,7 @@
* @param b the buffer into which the data is received
* @param off the start offset of the data
* @param len the maximum number of bytes received
- * @exception IOException If the pipe is <a href=#BROKEN> broken</a>,
+ * @exception IOException If the pipe is <a href="#BROKEN"> broken</a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed,or if an I/O error occurs.
*/
@@ -298,7 +298,7 @@
* stream is reached.
* @exception IOException if the pipe is
* {@link #connect(java.io.PipedOutputStream) unconnected},
- * <a href=#BROKEN> <code>broken</code></a>, closed,
+ * <a href="#BROKEN"> <code>broken</code></a>, closed,
* or if an I/O error occurs.
*/
public synchronized int read() throws IOException {
@@ -361,7 +361,7 @@
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
* <code>len</code> is negative, or <code>len</code> is greater than
* <code>b.length - off</code>
- * @exception IOException if the pipe is <a href=#BROKEN> <code>broken</code></a>,
+ * @exception IOException if the pipe is <a href="#BROKEN"> <code>broken</code></a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed, or if an I/O error occurs.
*/
@@ -419,7 +419,7 @@
* without blocking, or {@code 0} if this input stream has been
* closed by invoking its {@link #close()} method, or if the pipe
* is {@link #connect(java.io.PipedOutputStream) unconnected}, or
- * <a href=#BROKEN> <code>broken</code></a>.
+ * <a href="#BROKEN"> <code>broken</code></a>.
*
* @exception IOException if an I/O error occurs.
* @since JDK1.0.2
--- a/jdk/src/share/classes/java/io/RandomAccessFile.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/io/RandomAccessFile.java Tue Jul 09 15:26:20 2013 -0700
@@ -123,11 +123,11 @@
* write to, the file specified by the {@link File} argument. A new {@link
* FileDescriptor} object is created to represent this file connection.
*
- * <a name="mode"><p> The <tt>mode</tt> argument specifies the access mode
+ * <p>The <a name="mode"><tt>mode</tt></a> argument specifies the access mode
* in which the file is to be opened. The permitted values and their
* meanings are:
*
- * <blockquote><table summary="Access mode permitted values and meanings">
+ * <table summary="Access mode permitted values and meanings">
* <tr><th><p align="left">Value</p></th><th><p align="left">Meaning</p></th></tr>
* <tr><td valign="top"><tt>"r"</tt></td>
* <td> Open for reading only. Invoking any of the <tt>write</tt>
@@ -144,7 +144,7 @@
* <td> Open for reading and writing, as with <tt>"rw"</tt>, and also
* require that every update to the file's content be written
* synchronously to the underlying storage device. </td></tr>
- * </table></blockquote>
+ * </table>
*
* The <tt>"rws"</tt> and <tt>"rwd"</tt> modes work much like the {@link
* java.nio.channels.FileChannel#force(boolean) force(boolean)} method of
@@ -158,13 +158,13 @@
* event of a system crash. If the file does not reside on a local device
* then no such guarantee is made.
*
- * <p> The <tt>"rwd"</tt> mode can be used to reduce the number of I/O
+ * <p>The <tt>"rwd"</tt> mode can be used to reduce the number of I/O
* operations performed. Using <tt>"rwd"</tt> only requires updates to the
* file's content to be written to storage; using <tt>"rws"</tt> requires
* updates to both the file's content and its metadata to be written, which
* generally requires at least one more low-level I/O operation.
*
- * <p> If there is a security manager, its {@code checkRead} method is
+ * <p>If there is a security manager, its {@code checkRead} method is
* called with the pathname of the {@code file} argument as its
* argument to see if read access to the file is allowed. If the mode
* allows writing, the security manager's {@code checkWrite} method is
@@ -238,7 +238,7 @@
/**
* Returns the opaque file descriptor object associated with this
- * stream. </p>
+ * stream.
*
* @return the file descriptor object associated with this stream.
* @exception IOException if an I/O error occurs.
--- a/jdk/src/share/classes/java/util/LinkedList.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/LinkedList.java Tue Jul 09 15:26:20 2013 -0700
@@ -1195,12 +1195,7 @@
n = s;
if (n > MAX_BATCH)
n = MAX_BATCH;
- Object[] a;
- try {
- a = new Object[n];
- } catch (OutOfMemoryError oome) {
- return null;
- }
+ Object[] a = new Object[n];
int j = 0;
do { a[j++] = p.item; } while ((p = p.next) != null && j < n);
current = p;
--- a/jdk/src/share/classes/java/util/Spliterators.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/Spliterators.java Tue Jul 09 15:26:20 2013 -0700
@@ -1314,12 +1314,7 @@
n = (int) s;
if (n > MAX_BATCH)
n = MAX_BATCH;
- Object[] a;
- try {
- a = new Object[n];
- } catch (OutOfMemoryError oome) {
- return null;
- }
+ Object[] a = new Object[n];
int j = 0;
do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
batch = j;
@@ -1429,12 +1424,7 @@
n = (int) s;
if (n > MAX_BATCH)
n = MAX_BATCH;
- int[] a;
- try {
- a = new int[n];
- } catch (OutOfMemoryError oome) {
- return null;
- }
+ int[] a = new int[n];
int j = 0;
do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
batch = j;
@@ -1544,12 +1534,7 @@
n = (int) s;
if (n > MAX_BATCH)
n = MAX_BATCH;
- long[] a;
- try {
- a = new long[n];
- } catch (OutOfMemoryError oome) {
- return null;
- }
+ long[] a = new long[n];
int j = 0;
do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
batch = j;
@@ -1659,12 +1644,7 @@
n = (int) s;
if (n > MAX_BATCH)
n = MAX_BATCH;
- double[] a;
- try {
- a = new double[n];
- } catch (OutOfMemoryError oome) {
- return null;
- }
+ double[] a = new double[n];
int j = 0;
do { a[j] = holder.value; } while (++j < n && tryAdvance(holder));
batch = j;
@@ -1795,12 +1775,7 @@
n = (int) s;
if (n > MAX_BATCH)
n = MAX_BATCH;
- Object[] a;
- try {
- a = new Object[n];
- } catch (OutOfMemoryError oome) {
- return null;
- }
+ Object[] a = new Object[n];
int j = 0;
do { a[j] = i.next(); } while (++j < n && i.hasNext());
batch = j;
@@ -1910,12 +1885,7 @@
n = (int) s;
if (n > MAX_BATCH)
n = MAX_BATCH;
- int[] a;
- try {
- a = new int[n];
- } catch (OutOfMemoryError oome) {
- return null;
- }
+ int[] a = new int[n];
int j = 0;
do { a[j] = i.nextInt(); } while (++j < n && i.hasNext());
batch = j;
@@ -2007,12 +1977,7 @@
n = (int) s;
if (n > MAX_BATCH)
n = MAX_BATCH;
- long[] a;
- try {
- a = new long[n];
- } catch (OutOfMemoryError oome) {
- return null;
- }
+ long[] a = new long[n];
int j = 0;
do { a[j] = i.nextLong(); } while (++j < n && i.hasNext());
batch = j;
@@ -2104,12 +2069,7 @@
n = (int) s;
if (n > MAX_BATCH)
n = MAX_BATCH;
- double[] a;
- try {
- a = new double[n];
- } catch (OutOfMemoryError oome) {
- return null;
- }
+ double[] a = new double[n];
int j = 0;
do { a[j] = i.nextDouble(); } while (++j < n && i.hasNext());
batch = j;
--- a/jdk/src/share/classes/java/util/concurrent/AbstractExecutorService.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/AbstractExecutorService.java Tue Jul 09 15:26:20 2013 -0700
@@ -38,19 +38,19 @@
/**
* Provides default implementations of {@link ExecutorService}
- * execution methods. This class implements the <tt>submit</tt>,
- * <tt>invokeAny</tt> and <tt>invokeAll</tt> methods using a
- * {@link RunnableFuture} returned by <tt>newTaskFor</tt>, which defaults
+ * execution methods. This class implements the {@code submit},
+ * {@code invokeAny} and {@code invokeAll} methods using a
+ * {@link RunnableFuture} returned by {@code newTaskFor}, which defaults
* to the {@link FutureTask} class provided in this package. For example,
- * the implementation of <tt>submit(Runnable)</tt> creates an
- * associated <tt>RunnableFuture</tt> that is executed and
- * returned. Subclasses may override the <tt>newTaskFor</tt> methods
- * to return <tt>RunnableFuture</tt> implementations other than
- * <tt>FutureTask</tt>.
+ * the implementation of {@code submit(Runnable)} creates an
+ * associated {@code RunnableFuture} that is executed and
+ * returned. Subclasses may override the {@code newTaskFor} methods
+ * to return {@code RunnableFuture} implementations other than
+ * {@code FutureTask}.
*
- * <p> <b>Extension example</b>. Here is a sketch of a class
+ * <p><b>Extension example</b>. Here is a sketch of a class
* that customizes {@link ThreadPoolExecutor} to use
- * a <tt>CustomTask</tt> class instead of the default <tt>FutureTask</tt>:
+ * a {@code CustomTask} class instead of the default {@code FutureTask}:
* <pre> {@code
* public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
*
@@ -71,15 +71,15 @@
public abstract class AbstractExecutorService implements ExecutorService {
/**
- * Returns a <tt>RunnableFuture</tt> for the given runnable and default
+ * Returns a {@code RunnableFuture} for the given runnable and default
* value.
*
* @param runnable the runnable task being wrapped
* @param value the default value for the returned future
- * @return a <tt>RunnableFuture</tt> which when run will run the
- * underlying runnable and which, as a <tt>Future</tt>, will yield
+ * @return a {@code RunnableFuture} which, when run, will run the
+ * underlying runnable and which, as a {@code Future}, will yield
* the given value as its result and provide for cancellation of
- * the underlying task.
+ * the underlying task
* @since 1.6
*/
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
@@ -87,13 +87,13 @@
}
/**
- * Returns a <tt>RunnableFuture</tt> for the given callable task.
+ * Returns a {@code RunnableFuture} for the given callable task.
*
* @param callable the callable task being wrapped
- * @return a <tt>RunnableFuture</tt> which when run will call the
- * underlying callable and which, as a <tt>Future</tt>, will yield
+ * @return a {@code RunnableFuture} which, when run, will call the
+ * underlying callable and which, as a {@code Future}, will yield
* the callable's result as its result and provide for
- * cancellation of the underlying task.
+ * cancellation of the underlying task
* @since 1.6
*/
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
@@ -144,7 +144,7 @@
int ntasks = tasks.size();
if (ntasks == 0)
throw new IllegalArgumentException();
- List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
+ ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
ExecutorCompletionService<T> ecs =
new ExecutorCompletionService<T>(this);
@@ -202,8 +202,8 @@
throw ee;
} finally {
- for (Future<T> f : futures)
- f.cancel(true);
+ for (int i = 0, size = futures.size(); i < size; i++)
+ futures.get(i).cancel(true);
}
}
@@ -227,7 +227,7 @@
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
- List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+ ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) {
@@ -235,7 +235,8 @@
futures.add(f);
execute(f);
}
- for (Future<T> f : futures) {
+ for (int i = 0, size = futures.size(); i < size; i++) {
+ Future<T> f = futures.get(i);
if (!f.isDone()) {
try {
f.get();
@@ -248,8 +249,8 @@
return futures;
} finally {
if (!done)
- for (Future<T> f : futures)
- f.cancel(true);
+ for (int i = 0, size = futures.size(); i < size; i++)
+ futures.get(i).cancel(true);
}
}
@@ -259,25 +260,26 @@
if (tasks == null)
throw new NullPointerException();
long nanos = unit.toNanos(timeout);
- List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+ ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks)
futures.add(newTaskFor(t));
final long deadline = System.nanoTime() + nanos;
+ final int size = futures.size();
// Interleave time checks and calls to execute in case
// executor doesn't have any/much parallelism.
- Iterator<Future<T>> it = futures.iterator();
- while (it.hasNext()) {
- execute((Runnable)(it.next()));
+ for (int i = 0; i < size; i++) {
+ execute((Runnable)futures.get(i));
nanos = deadline - System.nanoTime();
if (nanos <= 0L)
return futures;
}
- for (Future<T> f : futures) {
+ for (int i = 0; i < size; i++) {
+ Future<T> f = futures.get(i);
if (!f.isDone()) {
if (nanos <= 0L)
return futures;
@@ -295,8 +297,8 @@
return futures;
} finally {
if (!done)
- for (Future<T> f : futures)
- f.cancel(true);
+ for (int i = 0, size = futures.size(); i < size; i++)
+ futures.get(i).cancel(true);
}
}
--- a/jdk/src/share/classes/java/util/concurrent/Callable.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/Callable.java Tue Jul 09 15:26:20 2013 -0700
@@ -38,21 +38,21 @@
/**
* A task that returns a result and may throw an exception.
* Implementors define a single method with no arguments called
- * <tt>call</tt>.
+ * {@code call}.
*
- * <p>The <tt>Callable</tt> interface is similar to {@link
+ * <p>The {@code Callable} interface is similar to {@link
* java.lang.Runnable}, in that both are designed for classes whose
* instances are potentially executed by another thread. A
- * <tt>Runnable</tt>, however, does not return a result and cannot
+ * {@code Runnable}, however, does not return a result and cannot
* throw a checked exception.
*
- * <p> The {@link Executors} class contains utility methods to
- * convert from other common forms to <tt>Callable</tt> classes.
+ * <p>The {@link Executors} class contains utility methods to
+ * convert from other common forms to {@code Callable} classes.
*
* @see Executor
* @since 1.5
* @author Doug Lea
- * @param <V> the result type of method <tt>call</tt>
+ * @param <V> the result type of method {@code call}
*/
public interface Callable<V> {
/**
--- a/jdk/src/share/classes/java/util/concurrent/CancellationException.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/CancellationException.java Tue Jul 09 15:26:20 2013 -0700
@@ -47,12 +47,12 @@
private static final long serialVersionUID = -9202173006928992231L;
/**
- * Constructs a <tt>CancellationException</tt> with no detail message.
+ * Constructs a {@code CancellationException} with no detail message.
*/
public CancellationException() {}
/**
- * Constructs a <tt>CancellationException</tt> with the specified detail
+ * Constructs a {@code CancellationException} with the specified detail
* message.
*
* @param message the detail message
--- a/jdk/src/share/classes/java/util/concurrent/CompletableFuture.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/CompletableFuture.java Tue Jul 09 15:26:20 2013 -0700
@@ -1209,7 +1209,7 @@
(r = a.result) != null &&
compareAndSet(0, 1)) {
if ((r instanceof AltResult) &&
- (ex = ((AltResult)r).ex) != null) {
+ (ex = ((AltResult)r).ex) != null) {
try {
t = fn.apply(ex);
} catch (Throwable rex) {
@@ -2892,7 +2892,7 @@
if (r != null && (d == null || d.compareAndSet(0, 1))) {
T t = null; Throwable ex, dx = null;
if (r instanceof AltResult) {
- if ((ex = ((AltResult)r).ex) != null) {
+ if ((ex = ((AltResult)r).ex) != null) {
try {
t = fn.apply(ex);
} catch (Throwable rex) {
--- a/jdk/src/share/classes/java/util/concurrent/CompletionService.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/CompletionService.java Tue Jul 09 15:26:20 2013 -0700
@@ -38,17 +38,17 @@
/**
* A service that decouples the production of new asynchronous tasks
* from the consumption of the results of completed tasks. Producers
- * <tt>submit</tt> tasks for execution. Consumers <tt>take</tt>
+ * {@code submit} tasks for execution. Consumers {@code take}
* completed tasks and process their results in the order they
- * complete. A <tt>CompletionService</tt> can for example be used to
- * manage asynchronous IO, in which tasks that perform reads are
+ * complete. A {@code CompletionService} can for example be used to
+ * manage asynchronous I/O, in which tasks that perform reads are
* submitted in one part of a program or system, and then acted upon
* in a different part of the program when the reads complete,
* possibly in a different order than they were requested.
*
- * <p>Typically, a <tt>CompletionService</tt> relies on a separate
+ * <p>Typically, a {@code CompletionService} relies on a separate
* {@link Executor} to actually execute the tasks, in which case the
- * <tt>CompletionService</tt> only manages an internal completion
+ * {@code CompletionService} only manages an internal completion
* queue. The {@link ExecutorCompletionService} class provides an
* implementation of this approach.
*
@@ -80,7 +80,7 @@
* @param task the task to submit
* @param result the result to return upon successful completion
* @return a Future representing pending completion of the task,
- * and whose <tt>get()</tt> method will return the given
+ * and whose {@code get()} method will return the given
* result value upon completion
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
@@ -99,10 +99,10 @@
/**
* Retrieves and removes the Future representing the next
- * completed task or <tt>null</tt> if none are present.
+ * completed task, or {@code null} if none are present.
*
* @return the Future representing the next completed task, or
- * <tt>null</tt> if none are present
+ * {@code null} if none are present
*/
Future<V> poll();
@@ -112,11 +112,11 @@
* time if none are yet present.
*
* @param timeout how long to wait before giving up, in units of
- * <tt>unit</tt>
- * @param unit a <tt>TimeUnit</tt> determining how to interpret the
- * <tt>timeout</tt> parameter
+ * {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
* @return the Future representing the next completed task or
- * <tt>null</tt> if the specified waiting time elapses
+ * {@code null} if the specified waiting time elapses
* before one is present
* @throws InterruptedException if interrupted while waiting
*/
--- a/jdk/src/share/classes/java/util/concurrent/CountedCompleter.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/CountedCompleter.java Tue Jul 09 15:26:20 2013 -0700
@@ -37,14 +37,15 @@
/**
* A {@link ForkJoinTask} with a completion action performed when
- * triggered and there are no remaining pending
- * actions. CountedCompleters are in general more robust in the
+ * triggered and there are no remaining pending actions.
+ * CountedCompleters are in general more robust in the
* presence of subtask stalls and blockage than are other forms of
* ForkJoinTasks, but are less intuitive to program. Uses of
* CountedCompleter are similar to those of other completion based
* components (such as {@link java.nio.channels.CompletionHandler})
* except that multiple <em>pending</em> completions may be necessary
- * to trigger the completion action {@link #onCompletion}, not just one.
+ * to trigger the completion action {@link #onCompletion(CountedCompleter)},
+ * not just one.
* Unless initialized otherwise, the {@linkplain #getPendingCount pending
* count} starts at zero, but may be (atomically) changed using
* methods {@link #setPendingCount}, {@link #addToPendingCount}, and
@@ -69,9 +70,10 @@
* <p>A concrete CountedCompleter class must define method {@link
* #compute}, that should in most cases (as illustrated below), invoke
* {@code tryComplete()} once before returning. The class may also
- * optionally override method {@link #onCompletion} to perform an
- * action upon normal completion, and method {@link
- * #onExceptionalCompletion} to perform an action upon any exception.
+ * optionally override method {@link #onCompletion(CountedCompleter)}
+ * to perform an action upon normal completion, and method
+ * {@link #onExceptionalCompletion(Throwable, CountedCompleter)} to
+ * perform an action upon any exception.
*
* <p>CountedCompleters most often do not bear results, in which case
* they are normally declared as {@code CountedCompleter<Void>}, and
@@ -92,13 +94,14 @@
* only as an internal helper for other computations, so its own task
* status (as reported in methods such as {@link ForkJoinTask#isDone})
* is arbitrary; this status changes only upon explicit invocations of
- * {@link #complete}, {@link ForkJoinTask#cancel}, {@link
- * ForkJoinTask#completeExceptionally} or upon exceptional completion
- * of method {@code compute}. Upon any exceptional completion, the
- * exception may be relayed to a task's completer (and its completer,
- * and so on), if one exists and it has not otherwise already
- * completed. Similarly, cancelling an internal CountedCompleter has
- * only a local effect on that completer, so is not often useful.
+ * {@link #complete}, {@link ForkJoinTask#cancel},
+ * {@link ForkJoinTask#completeExceptionally(Throwable)} or upon
+ * exceptional completion of method {@code compute}. Upon any
+ * exceptional completion, the exception may be relayed to a task's
+ * completer (and its completer, and so on), if one exists and it has
+ * not otherwise already completed. Similarly, cancelling an internal
+ * CountedCompleter has only a local effect on that completer, so is
+ * not often useful.
*
* <p><b>Sample Usages.</b>
*
@@ -125,8 +128,8 @@
* improve load balancing. In the recursive case, the second of each
* pair of subtasks to finish triggers completion of its parent
* (because no result combination is performed, the default no-op
- * implementation of method {@code onCompletion} is not overridden). A
- * static utility method sets up the base task and invokes it
+ * implementation of method {@code onCompletion} is not overridden).
+ * A static utility method sets up the base task and invokes it
* (here, implicitly using the {@link ForkJoinPool#commonPool()}).
*
* <pre> {@code
@@ -181,12 +184,11 @@
* }
* }</pre>
*
- * As a further improvement, notice that the left task need not even
- * exist. Instead of creating a new one, we can iterate using the
- * original task, and add a pending count for each fork. Additionally,
- * because no task in this tree implements an {@link #onCompletion}
- * method, {@code tryComplete()} can be replaced with {@link
- * #propagateCompletion}.
+ * As a further improvement, notice that the left task need not even exist.
+ * Instead of creating a new one, we can iterate using the original task,
+ * and add a pending count for each fork. Additionally, because no task
+ * in this tree implements an {@link #onCompletion(CountedCompleter)} method,
+ * {@code tryComplete()} can be replaced with {@link #propagateCompletion}.
*
* <pre> {@code
* class ForEach<E> ...
@@ -253,7 +255,7 @@
* public static <E> E search(E[] array) {
* return new Searcher<E>(null, array, new AtomicReference<E>(), 0, array.length).invoke();
* }
- *}}</pre>
+ * }}</pre>
*
* In this example, as well as others in which tasks have no other
* effects except to compareAndSet a common result, the trailing
@@ -264,7 +266,7 @@
*
* <p><b>Recording subtasks.</b> CountedCompleter tasks that combine
* results of multiple subtasks usually need to access these results
- * in method {@link #onCompletion}. As illustrated in the following
+ * in method {@link #onCompletion(CountedCompleter)}. As illustrated in the following
* class (that performs a simplified form of map-reduce where mappings
* and reductions are all of type {@code E}), one way to do this in
* divide and conquer designs is to have each subtask record its
@@ -365,7 +367,7 @@
* while (h - l >= 2) {
* int mid = (l + h) >>> 1;
* addToPendingCount(1);
- * (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork;
+ * (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork();
* h = mid;
* }
* if (h > l)
@@ -386,7 +388,7 @@
*
* <p><b>Triggers.</b> Some CountedCompleters are themselves never
* forked, but instead serve as bits of plumbing in other designs;
- * including those in which the completion of one of more async tasks
+ * including those in which the completion of one or more async tasks
* triggers another async task. For example:
*
* <pre> {@code
@@ -460,27 +462,28 @@
* (and/or links to other results) to combine.
*
* @param caller the task invoking this method (which may
- * be this task itself).
+ * be this task itself)
*/
public void onCompletion(CountedCompleter<?> caller) {
}
/**
- * Performs an action when method {@link #completeExceptionally}
- * is invoked or method {@link #compute} throws an exception, and
- * this task has not otherwise already completed normally. On
- * entry to this method, this task {@link
- * ForkJoinTask#isCompletedAbnormally}. The return value of this
- * method controls further propagation: If {@code true} and this
- * task has a completer, then this completer is also completed
- * exceptionally. The default implementation of this method does
- * nothing except return {@code true}.
+ * Performs an action when method {@link
+ * #completeExceptionally(Throwable)} is invoked or method {@link
+ * #compute} throws an exception, and this task has not already
+ * otherwise completed normally. On entry to this method, this task
+ * {@link ForkJoinTask#isCompletedAbnormally}. The return value
+ * of this method controls further propagation: If {@code true}
+ * and this task has a completer that has not completed, then that
+ * completer is also completed exceptionally, with the same
+ * exception as this completer. The default implementation of
+ * this method does nothing except return {@code true}.
*
* @param ex the exception
* @param caller the task invoking this method (which may
- * be this task itself).
- * @return true if this exception should be propagated to this
- * task's completer, if one exists.
+ * be this task itself)
+ * @return {@code true} if this exception should be propagated to this
+ * task's completer, if one exists
*/
public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller) {
return true;
@@ -520,8 +523,7 @@
* @param delta the value to add
*/
public final void addToPendingCount(int delta) {
- int c; // note: can replace with intrinsic in jdk8
- do {} while (!U.compareAndSwapInt(this, PENDING, c = pending, c+delta));
+ U.getAndAddInt(this, PENDING, delta);
}
/**
@@ -530,7 +532,7 @@
*
* @param expected the expected value
* @param count the new value
- * @return true if successful
+ * @return {@code true} if successful
*/
public final boolean compareAndSetPendingCount(int expected, int count) {
return U.compareAndSwapInt(this, PENDING, expected, count);
@@ -564,9 +566,9 @@
/**
* If the pending count is nonzero, decrements the count;
- * otherwise invokes {@link #onCompletion} and then similarly
- * tries to complete this task's completer, if one exists,
- * else marks this task as complete.
+ * otherwise invokes {@link #onCompletion(CountedCompleter)}
+ * and then similarly tries to complete this task's completer,
+ * if one exists, else marks this task as complete.
*/
public final void tryComplete() {
CountedCompleter<?> a = this, s = a;
@@ -585,12 +587,12 @@
/**
* Equivalent to {@link #tryComplete} but does not invoke {@link
- * #onCompletion} along the completion path: If the pending count
- * is nonzero, decrements the count; otherwise, similarly tries to
- * complete this task's completer, if one exists, else marks this
- * task as complete. This method may be useful in cases where
- * {@code onCompletion} should not, or need not, be invoked for
- * each completer in a computation.
+ * #onCompletion(CountedCompleter)} along the completion path:
+ * If the pending count is nonzero, decrements the count;
+ * otherwise, similarly tries to complete this task's completer, if
+ * one exists, else marks this task as complete. This method may be
+ * useful in cases where {@code onCompletion} should not, or need
+ * not, be invoked for each completer in a computation.
*/
public final void propagateCompletion() {
CountedCompleter<?> a = this, s = a;
@@ -607,13 +609,15 @@
}
/**
- * Regardless of pending count, invokes {@link #onCompletion},
- * marks this task as complete and further triggers {@link
- * #tryComplete} on this task's completer, if one exists. The
- * given rawResult is used as an argument to {@link #setRawResult}
- * before invoking {@link #onCompletion} or marking this task as
- * complete; its value is meaningful only for classes overriding
- * {@code setRawResult}.
+ * Regardless of pending count, invokes
+ * {@link #onCompletion(CountedCompleter)}, marks this task as
+ * complete and further triggers {@link #tryComplete} on this
+ * task's completer, if one exists. The given rawResult is
+ * used as an argument to {@link #setRawResult} before invoking
+ * {@link #onCompletion(CountedCompleter)} or marking this task
+ * as complete; its value is meaningful only for classes
+ * overriding {@code setRawResult}. This method does not modify
+ * the pending count.
*
* <p>This method may be useful when forcing completion as soon as
* any one (versus all) of several subtask results are obtained.
@@ -632,7 +636,6 @@
p.tryComplete();
}
-
/**
* If this task's pending count is zero, returns this task;
* otherwise decrements its pending count and returns {@code
@@ -653,8 +656,8 @@
/**
* If this task does not have a completer, invokes {@link
* ForkJoinTask#quietlyComplete} and returns {@code null}. Or, if
- * this task's pending count is non-zero, decrements its pending
- * count and returns {@code null}. Otherwise, returns the
+ * the completer's pending count is non-zero, decrements that
+ * pending count and returns {@code null}. Otherwise, returns the
* completer. This method can be used as part of a completion
* traversal loop for homogeneous task hierarchies:
*
@@ -691,13 +694,34 @@
}
/**
+ * If this task has not completed, attempts to process at most the
+ * given number of other unprocessed tasks for which this task is
+ * on the completion path, if any are known to exist.
+ *
+ * @param maxTasks the maximum number of tasks to process. If
+ * less than or equal to zero, then no tasks are
+ * processed.
+ */
+ public final void helpComplete(int maxTasks) {
+ Thread t; ForkJoinWorkerThread wt;
+ if (maxTasks > 0 && status >= 0) {
+ if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
+ (wt = (ForkJoinWorkerThread)t).pool.
+ helpComplete(wt.workQueue, this, maxTasks);
+ else
+ ForkJoinPool.common.externalHelpComplete(this, maxTasks);
+ }
+ }
+
+ /**
* Supports ForkJoinTask exception propagation.
*/
void internalPropagateException(Throwable ex) {
CountedCompleter<?> a = this, s = a;
while (a.onExceptionalCompletion(ex, s) &&
- (a = (s = a).completer) != null && a.status >= 0)
- a.recordExceptionalCompletion(ex);
+ (a = (s = a).completer) != null && a.status >= 0 &&
+ a.recordExceptionalCompletion(ex) == EXCEPTIONAL)
+ ;
}
/**
--- a/jdk/src/share/classes/java/util/concurrent/ExecutionException.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ExecutionException.java Tue Jul 09 15:26:20 2013 -0700
@@ -48,14 +48,14 @@
private static final long serialVersionUID = 7830266012832686185L;
/**
- * Constructs an <tt>ExecutionException</tt> with no detail message.
+ * Constructs an {@code ExecutionException} with no detail message.
* The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause(Throwable) initCause}.
*/
protected ExecutionException() { }
/**
- * Constructs an <tt>ExecutionException</tt> with the specified detail
+ * Constructs an {@code ExecutionException} with the specified detail
* message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause(Throwable) initCause}.
*
@@ -66,7 +66,7 @@
}
/**
- * Constructs an <tt>ExecutionException</tt> with the specified detail
+ * Constructs an {@code ExecutionException} with the specified detail
* message and cause.
*
* @param message the detail message
@@ -78,7 +78,7 @@
}
/**
- * Constructs an <tt>ExecutionException</tt> with the specified cause.
+ * Constructs an {@code ExecutionException} with the specified cause.
* The detail message is set to {@code (cause == null ? null :
* cause.toString())} (which typically contains the class and
* detail message of {@code cause}).
--- a/jdk/src/share/classes/java/util/concurrent/Executor.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/Executor.java Tue Jul 09 15:26:20 2013 -0700
@@ -39,9 +39,9 @@
* An object that executes submitted {@link Runnable} tasks. This
* interface provides a way of decoupling task submission from the
* mechanics of how each task will be run, including details of thread
- * use, scheduling, etc. An <tt>Executor</tt> is normally used
+ * use, scheduling, etc. An {@code Executor} is normally used
* instead of explicitly creating threads. For example, rather than
- * invoking <tt>new Thread(new(RunnableTask())).start()</tt> for each
+ * invoking {@code new Thread(new(RunnableTask())).start()} for each
* of a set of tasks, you might use:
*
* <pre>
@@ -51,7 +51,7 @@
* ...
* </pre>
*
- * However, the <tt>Executor</tt> interface does not strictly
+ * However, the {@code Executor} interface does not strictly
* require that execution be asynchronous. In the simplest case, an
* executor can run the submitted task immediately in the caller's
* thread:
@@ -74,7 +74,7 @@
* }
* }}</pre>
*
- * Many <tt>Executor</tt> implementations impose some sort of
+ * Many {@code Executor} implementations impose some sort of
* limitation on how and when tasks are scheduled. The executor below
* serializes the submission of tasks to a second executor,
* illustrating a composite executor.
@@ -111,7 +111,7 @@
* }
* }}</pre>
*
- * The <tt>Executor</tt> implementations provided in this package
+ * The {@code Executor} implementations provided in this package
* implement {@link ExecutorService}, which is a more extensive
* interface. The {@link ThreadPoolExecutor} class provides an
* extensible thread pool implementation. The {@link Executors} class
@@ -130,11 +130,11 @@
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
- * thread, at the discretion of the <tt>Executor</tt> implementation.
+ * thread, at the discretion of the {@code Executor} implementation.
*
* @param command the runnable task
* @throws RejectedExecutionException if this task cannot be
- * accepted for execution.
+ * accepted for execution
* @throws NullPointerException if command is null
*/
void execute(Runnable command);
--- a/jdk/src/share/classes/java/util/concurrent/ExecutorService.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ExecutorService.java Tue Jul 09 15:26:20 2013 -0700
@@ -42,21 +42,21 @@
* methods that can produce a {@link Future} for tracking progress of
* one or more asynchronous tasks.
*
- * <p> An <tt>ExecutorService</tt> can be shut down, which will cause
+ * <p>An {@code ExecutorService} can be shut down, which will cause
* it to reject new tasks. Two different methods are provided for
- * shutting down an <tt>ExecutorService</tt>. The {@link #shutdown}
+ * shutting down an {@code ExecutorService}. The {@link #shutdown}
* method will allow previously submitted tasks to execute before
* terminating, while the {@link #shutdownNow} method prevents waiting
* tasks from starting and attempts to stop currently executing tasks.
* Upon termination, an executor has no tasks actively executing, no
* tasks awaiting execution, and no new tasks can be submitted. An
- * unused <tt>ExecutorService</tt> should be shut down to allow
+ * unused {@code ExecutorService} should be shut down to allow
* reclamation of its resources.
*
- * <p> Method <tt>submit</tt> extends base method {@link
- * Executor#execute} by creating and returning a {@link Future} that
- * can be used to cancel execution and/or wait for completion.
- * Methods <tt>invokeAny</tt> and <tt>invokeAll</tt> perform the most
+ * <p>Method {@code submit} extends base method {@link
+ * Executor#execute(Runnable)} by creating and returning a {@link Future}
+ * that can be used to cancel execution and/or wait for completion.
+ * Methods {@code invokeAny} and {@code invokeAll} perform the most
* commonly useful forms of bulk execution, executing a collection of
* tasks and then waiting for at least one, or all, to
* complete. (Class {@link ExecutorCompletionService} can be used to
@@ -101,9 +101,9 @@
* }
* }}</pre>
*
- * The following method shuts down an <tt>ExecutorService</tt> in two phases,
- * first by calling <tt>shutdown</tt> to reject incoming tasks, and then
- * calling <tt>shutdownNow</tt>, if necessary, to cancel any lingering tasks:
+ * The following method shuts down an {@code ExecutorService} in two phases,
+ * first by calling {@code shutdown} to reject incoming tasks, and then
+ * calling {@code shutdownNow}, if necessary, to cancel any lingering tasks:
*
* <pre> {@code
* void shutdownAndAwaitTermination(ExecutorService pool) {
@@ -149,8 +149,8 @@
* shutting down this ExecutorService may manipulate
* threads that the caller is not permitted to modify
* because it does not hold {@link
- * java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
- * or the security manager's <tt>checkAccess</tt> method
+ * java.lang.RuntimePermission}{@code ("modifyThread")},
+ * or the security manager's {@code checkAccess} method
* denies access.
*/
void shutdown();
@@ -174,25 +174,25 @@
* shutting down this ExecutorService may manipulate
* threads that the caller is not permitted to modify
* because it does not hold {@link
- * java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
- * or the security manager's <tt>checkAccess</tt> method
+ * java.lang.RuntimePermission}{@code ("modifyThread")},
+ * or the security manager's {@code checkAccess} method
* denies access.
*/
List<Runnable> shutdownNow();
/**
- * Returns <tt>true</tt> if this executor has been shut down.
+ * Returns {@code true} if this executor has been shut down.
*
- * @return <tt>true</tt> if this executor has been shut down
+ * @return {@code true} if this executor has been shut down
*/
boolean isShutdown();
/**
- * Returns <tt>true</tt> if all tasks have completed following shut down.
- * Note that <tt>isTerminated</tt> is never <tt>true</tt> unless
- * either <tt>shutdown</tt> or <tt>shutdownNow</tt> was called first.
+ * Returns {@code true} if all tasks have completed following shut down.
+ * Note that {@code isTerminated} is never {@code true} unless
+ * either {@code shutdown} or {@code shutdownNow} was called first.
*
- * @return <tt>true</tt> if all tasks have completed following shut down
+ * @return {@code true} if all tasks have completed following shut down
*/
boolean isTerminated();
@@ -203,8 +203,8 @@
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
- * @return <tt>true</tt> if this executor terminated and
- * <tt>false</tt> if the timeout elapsed before termination
+ * @return {@code true} if this executor terminated and
+ * {@code false} if the timeout elapsed before termination
* @throws InterruptedException if interrupted while waiting
*/
boolean awaitTermination(long timeout, TimeUnit unit)
@@ -213,15 +213,15 @@
/**
* Submits a value-returning task for execution and returns a
* Future representing the pending results of the task. The
- * Future's <tt>get</tt> method will return the task's result upon
+ * Future's {@code get} method will return the task's result upon
* successful completion.
*
* <p>
* If you would like to immediately block waiting
* for a task, you can use constructions of the form
- * <tt>result = exec.submit(aCallable).get();</tt>
+ * {@code result = exec.submit(aCallable).get();}
*
- * <p> Note: The {@link Executors} class includes a set of methods
+ * <p>Note: The {@link Executors} class includes a set of methods
* that can convert some other common closure-like objects,
* for example, {@link java.security.PrivilegedAction} to
* {@link Callable} form so they can be submitted.
@@ -236,7 +236,7 @@
/**
* Submits a Runnable task for execution and returns a Future
- * representing that task. The Future's <tt>get</tt> method will
+ * representing that task. The Future's {@code get} method will
* return the given result upon successful completion.
*
* @param task the task to submit
@@ -250,8 +250,8 @@
/**
* Submits a Runnable task for execution and returns a Future
- * representing that task. The Future's <tt>get</tt> method will
- * return <tt>null</tt> upon <em>successful</em> completion.
+ * representing that task. The Future's {@code get} method will
+ * return {@code null} upon <em>successful</em> completion.
*
* @param task the task to submit
* @return a Future representing pending completion of the task
@@ -264,7 +264,7 @@
/**
* Executes the given tasks, returning a list of Futures holding
* their status and results when all complete.
- * {@link Future#isDone} is <tt>true</tt> for each
+ * {@link Future#isDone} is {@code true} for each
* element of the returned list.
* Note that a <em>completed</em> task could have
* terminated either normally or by throwing an exception.
@@ -272,12 +272,12 @@
* collection is modified while this operation is in progress.
*
* @param tasks the collection of tasks
- * @return A list of Futures representing the tasks, in the same
+ * @return a list of Futures representing the tasks, in the same
* sequential order as produced by the iterator for the
- * given task list, each of which has completed.
+ * given task list, each of which has completed
* @throws InterruptedException if interrupted while waiting, in
- * which case unfinished tasks are cancelled.
- * @throws NullPointerException if tasks or any of its elements are <tt>null</tt>
+ * which case unfinished tasks are cancelled
+ * @throws NullPointerException if tasks or any of its elements are {@code null}
* @throws RejectedExecutionException if any task cannot be
* scheduled for execution
*/
@@ -288,7 +288,7 @@
* Executes the given tasks, returning a list of Futures holding
* their status and results
* when all complete or the timeout expires, whichever happens first.
- * {@link Future#isDone} is <tt>true</tt> for each
+ * {@link Future#isDone} is {@code true} for each
* element of the returned list.
* Upon return, tasks that have not completed are cancelled.
* Note that a <em>completed</em> task could have
@@ -307,7 +307,7 @@
* @throws InterruptedException if interrupted while waiting, in
* which case unfinished tasks are cancelled
* @throws NullPointerException if tasks, any of its elements, or
- * unit are <tt>null</tt>
+ * unit are {@code null}
* @throws RejectedExecutionException if any task cannot be scheduled
* for execution
*/
@@ -327,7 +327,7 @@
* @return the result returned by one of the tasks
* @throws InterruptedException if interrupted while waiting
* @throws NullPointerException if tasks or any element task
- * subject to execution is <tt>null</tt>
+ * subject to execution is {@code null}
* @throws IllegalArgumentException if tasks is empty
* @throws ExecutionException if no task successfully completes
* @throws RejectedExecutionException if tasks cannot be scheduled
@@ -348,10 +348,10 @@
* @param tasks the collection of tasks
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
- * @return the result returned by one of the tasks.
+ * @return the result returned by one of the tasks
* @throws InterruptedException if interrupted while waiting
* @throws NullPointerException if tasks, or unit, or any element
- * task subject to execution is <tt>null</tt>
+ * task subject to execution is {@code null}
* @throws TimeoutException if the given timeout elapses before
* any task successfully completes
* @throws ExecutionException if no task successfully completes
--- a/jdk/src/share/classes/java/util/concurrent/Executors.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/Executors.java Tue Jul 09 15:26:20 2013 -0700
@@ -62,7 +62,7 @@
* that sets newly created threads to a known state.
* <li> Methods that create and return a {@link Callable}
* out of other closure-like forms, so they can be used
- * in execution methods requiring <tt>Callable</tt>.
+ * in execution methods requiring {@code Callable}.
* </ul>
*
* @since 1.5
@@ -73,7 +73,7 @@
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
- * <tt>nThreads</tt> threads will be active processing tasks.
+ * {@code nThreads} threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
@@ -92,10 +92,47 @@
}
/**
+ * Creates a thread pool that maintains enough threads to support
+ * the given parallelism level, and may use multiple queues to
+ * reduce contention. The parallelism level corresponds to the
+ * maximum number of threads actively engaged in, or available to
+ * engage in, task processing. The actual number of threads may
+ * grow and shrink dynamically. A work-stealing pool makes no
+ * guarantees about the order in which submitted tasks are
+ * executed.
+ *
+ * @param parallelism the targeted parallelism level
+ * @return the newly created thread pool
+ * @throws IllegalArgumentException if {@code parallelism <= 0}
+ * @since 1.8
+ */
+ public static ExecutorService newWorkStealingPool(int parallelism) {
+ return new ForkJoinPool
+ (parallelism,
+ ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+ null, true);
+ }
+
+ /**
+ * Creates a work-stealing thread pool using all
+ * {@link Runtime#availableProcessors available processors}
+ * as its target parallelism level.
+ * @return the newly created thread pool
+ * @see #newWorkStealingPool(int)
+ * @since 1.8
+ */
+ public static ExecutorService newWorkStealingPool() {
+ return new ForkJoinPool
+ (Runtime.getRuntime().availableProcessors(),
+ ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+ null, true);
+ }
+
+ /**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue, using the provided
* ThreadFactory to create new threads when needed. At any point,
- * at most <tt>nThreads</tt> threads will be active processing
+ * at most {@code nThreads} threads will be active processing
* tasks. If additional tasks are submitted when all threads are
* active, they will wait in the queue until a thread is
* available. If any thread terminates due to a failure during
@@ -125,7 +162,7 @@
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
- * <tt>newFixedThreadPool(1)</tt> the returned executor is
+ * {@code newFixedThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
*
* @return the newly created single-threaded Executor
@@ -141,7 +178,7 @@
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue, and uses the provided ThreadFactory to
* create a new thread when needed. Unlike the otherwise
- * equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the
+ * equivalent {@code newFixedThreadPool(1, threadFactory)} the
* returned executor is guaranteed not to be reconfigurable to use
* additional threads.
*
@@ -164,7 +201,7 @@
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
- * Calls to <tt>execute</tt> will reuse previously constructed
+ * Calls to {@code execute} will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
@@ -206,7 +243,7 @@
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
- * <tt>newScheduledThreadPool(1)</tt> the returned executor is
+ * {@code newScheduledThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
* @return the newly created scheduled executor
*/
@@ -223,7 +260,7 @@
* place if needed to execute subsequent tasks.) Tasks are
* guaranteed to execute sequentially, and no more than one task
* will be active at any given time. Unlike the otherwise
- * equivalent <tt>newScheduledThreadPool(1, threadFactory)</tt>
+ * equivalent {@code newScheduledThreadPool(1, threadFactory)}
* the returned executor is guaranteed not to be reconfigurable to
* use additional threads.
* @param threadFactory the factory to use when creating new
@@ -240,7 +277,7 @@
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
- * even if they are idle.
+ * even if they are idle
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
@@ -252,9 +289,9 @@
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
- * even if they are idle.
+ * even if they are idle
* @param threadFactory the factory to use when the executor
- * creates a new thread.
+ * creates a new thread
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
* @throws NullPointerException if threadFactory is null
@@ -264,7 +301,6 @@
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
-
/**
* Returns an object that delegates all defined {@link
* ExecutorService} methods to the given executor, but not any
@@ -272,7 +308,7 @@
* casts. This provides a way to safely "freeze" configuration and
* disallow tuning of a given concrete implementation.
* @param executor the underlying implementation
- * @return an <tt>ExecutorService</tt> instance
+ * @return an {@code ExecutorService} instance
* @throws NullPointerException if executor null
*/
public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
@@ -288,7 +324,7 @@
* casts. This provides a way to safely "freeze" configuration and
* disallow tuning of a given concrete implementation.
* @param executor the underlying implementation
- * @return a <tt>ScheduledExecutorService</tt> instance
+ * @return a {@code ScheduledExecutorService} instance
* @throws NullPointerException if executor null
*/
public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
@@ -303,9 +339,9 @@
* same {@link ThreadGroup}. If there is a {@link
* java.lang.SecurityManager}, it uses the group of {@link
* System#getSecurityManager}, else the group of the thread
- * invoking this <tt>defaultThreadFactory</tt> method. Each new
+ * invoking this {@code defaultThreadFactory} method. Each new
* thread is created as a non-daemon thread with priority set to
- * the smaller of <tt>Thread.NORM_PRIORITY</tt> and the maximum
+ * the smaller of {@code Thread.NORM_PRIORITY} and the maximum
* priority permitted in the thread group. New threads have names
* accessible via {@link Thread#getName} of
* <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
@@ -324,30 +360,31 @@
* Executors#defaultThreadFactory}, additionally setting the
* AccessControlContext and contextClassLoader of new threads to
* be the same as the thread invoking this
- * <tt>privilegedThreadFactory</tt> method. A new
- * <tt>privilegedThreadFactory</tt> can be created within an
- * {@link AccessController#doPrivileged} action setting the
- * current thread's access control context to create threads with
- * the selected permission settings holding within that action.
+ * {@code privilegedThreadFactory} method. A new
+ * {@code privilegedThreadFactory} can be created within an
+ * {@link AccessController#doPrivileged AccessController.doPrivileged}
+ * action setting the current thread's access control context to
+ * create threads with the selected permission settings holding
+ * within that action.
*
- * <p> Note that while tasks running within such threads will have
+ * <p>Note that while tasks running within such threads will have
* the same access control and class loader settings as the
* current thread, they need not have the same {@link
* java.lang.ThreadLocal} or {@link
* java.lang.InheritableThreadLocal} values. If necessary,
* particular values of thread locals can be set or reset before
* any task runs in {@link ThreadPoolExecutor} subclasses using
- * {@link ThreadPoolExecutor#beforeExecute}. Also, if it is
- * necessary to initialize worker threads to have the same
- * InheritableThreadLocal settings as some other designated
- * thread, you can create a custom ThreadFactory in which that
- * thread waits for and services requests to create others that
- * will inherit its values.
+ * {@link ThreadPoolExecutor#beforeExecute(Thread, Runnable)}.
+ * Also, if it is necessary to initialize worker threads to have
+ * the same InheritableThreadLocal settings as some other
+ * designated thread, you can create a custom ThreadFactory in
+ * which that thread waits for and services requests to create
+ * others that will inherit its values.
*
* @return a thread factory
* @throws AccessControlException if the current access control
* context does not have permission to both get and set context
- * class loader.
+ * class loader
*/
public static ThreadFactory privilegedThreadFactory() {
return new PrivilegedThreadFactory();
@@ -357,7 +394,7 @@
* Returns a {@link Callable} object that, when
* called, runs the given task and returns the given result. This
* can be useful when applying methods requiring a
- * <tt>Callable</tt> to an otherwise resultless action.
+ * {@code Callable} to an otherwise resultless action.
* @param task the task to run
* @param result the result to return
* @return a callable object
@@ -371,7 +408,7 @@
/**
* Returns a {@link Callable} object that, when
- * called, runs the given task and returns <tt>null</tt>.
+ * called, runs the given task and returns {@code null}.
* @param task the task to run
* @return a callable object
* @throws NullPointerException if task null
@@ -412,18 +449,17 @@
}
/**
- * Returns a {@link Callable} object that will, when
- * called, execute the given <tt>callable</tt> under the current
- * access control context. This method should normally be
- * invoked within an {@link AccessController#doPrivileged} action
- * to create callables that will, if possible, execute under the
- * selected permission settings holding within that action; or if
- * not possible, throw an associated {@link
+ * Returns a {@link Callable} object that will, when called,
+ * execute the given {@code callable} under the current access
+ * control context. This method should normally be invoked within
+ * an {@link AccessController#doPrivileged AccessController.doPrivileged}
+ * action to create callables that will, if possible, execute
+ * under the selected permission settings holding within that
+ * action; or if not possible, throw an associated {@link
* AccessControlException}.
* @param callable the underlying task
* @return a callable object
* @throws NullPointerException if callable null
- *
*/
public static <T> Callable<T> privilegedCallable(Callable<T> callable) {
if (callable == null)
@@ -432,22 +468,23 @@
}
/**
- * Returns a {@link Callable} object that will, when
- * called, execute the given <tt>callable</tt> under the current
- * access control context, with the current context class loader
- * as the context class loader. This method should normally be
- * invoked within an {@link AccessController#doPrivileged} action
- * to create callables that will, if possible, execute under the
- * selected permission settings holding within that action; or if
- * not possible, throw an associated {@link
+ * Returns a {@link Callable} object that will, when called,
+ * execute the given {@code callable} under the current access
+ * control context, with the current context class loader as the
+ * context class loader. This method should normally be invoked
+ * within an
+ * {@link AccessController#doPrivileged AccessController.doPrivileged}
+ * action to create callables that will, if possible, execute
+ * under the selected permission settings holding within that
+ * action; or if not possible, throw an associated {@link
* AccessControlException}.
+ *
* @param callable the underlying task
- *
* @return a callable object
* @throws NullPointerException if callable null
* @throws AccessControlException if the current access control
* context does not have permission to both set and get context
- * class loader.
+ * class loader
*/
public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable) {
if (callable == null)
@@ -699,7 +736,6 @@
}
}
-
/** Cannot instantiate. */
private Executors() {}
}
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java Tue Jul 09 15:26:20 2013 -0700
@@ -47,6 +47,7 @@
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RunnableFuture;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
/**
@@ -79,9 +80,9 @@
* level; by default, equal to the number of available processors. The
* pool attempts to maintain enough active (or available) threads by
* dynamically adding, suspending, or resuming internal worker
- * threads, even if some tasks are stalled waiting to join
- * others. However, no such adjustments are guaranteed in the face of
- * blocked I/O or other unmanaged synchronization. The nested {@link
+ * threads, even if some tasks are stalled waiting to join others.
+ * However, no such adjustments are guaranteed in the face of blocked
+ * I/O or other unmanaged synchronization. The nested {@link
* ManagedBlocker} interface enables extension of the kinds of
* synchronization accommodated.
*
@@ -157,6 +158,7 @@
* @since 1.7
* @author Doug Lea
*/
+@sun.misc.Contended
public class ForkJoinPool extends AbstractExecutorService {
/*
@@ -189,32 +191,35 @@
* (http://research.sun.com/scalable/pubs/index.html) and
* "Idempotent work stealing" by Michael, Saraswat, and Vechev,
* PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
- * The main differences ultimately stem from GC requirements that
- * we null out taken slots as soon as we can, to maintain as small
- * a footprint as possible even in programs generating huge
- * numbers of tasks. To accomplish this, we shift the CAS
- * arbitrating pop vs poll (steal) from being on the indices
- * ("base" and "top") to the slots themselves. So, both a
- * successful pop and poll mainly entail a CAS of a slot from
- * non-null to null. Because we rely on CASes of references, we
- * do not need tag bits on base or top. They are simple ints as
- * used in any circular array-based queue (see for example
- * ArrayDeque). Updates to the indices must still be ordered in a
- * way that guarantees that top == base means the queue is empty,
- * but otherwise may err on the side of possibly making the queue
- * appear nonempty when a push, pop, or poll have not fully
- * committed. Note that this means that the poll operation,
- * considered individually, is not wait-free. One thief cannot
- * successfully continue until another in-progress one (or, if
- * previously empty, a push) completes. However, in the
- * aggregate, we ensure at least probabilistic non-blockingness.
- * If an attempted steal fails, a thief always chooses a different
- * random victim target to try next. So, in order for one thief to
- * progress, it suffices for any in-progress poll or new push on
- * any empty queue to complete. (This is why we normally use
- * method pollAt and its variants that try once at the apparent
- * base index, else consider alternative actions, rather than
- * method poll.)
+ * See also "Correct and Efficient Work-Stealing for Weak Memory
+ * Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
+ * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
+ * analysis of memory ordering (atomic, volatile etc) issues. The
+ * main differences ultimately stem from GC requirements that we
+ * null out taken slots as soon as we can, to maintain as small a
+ * footprint as possible even in programs generating huge numbers
+ * of tasks. To accomplish this, we shift the CAS arbitrating pop
+ * vs poll (steal) from being on the indices ("base" and "top") to
+ * the slots themselves. So, both a successful pop and poll
+ * mainly entail a CAS of a slot from non-null to null. Because
+ * we rely on CASes of references, we do not need tag bits on base
+ * or top. They are simple ints as used in any circular
+ * array-based queue (see for example ArrayDeque). Updates to the
+ * indices must still be ordered in a way that guarantees that top
+ * == base means the queue is empty, but otherwise may err on the
+ * side of possibly making the queue appear nonempty when a push,
+ * pop, or poll have not fully committed. Note that this means
+ * that the poll operation, considered individually, is not
+ * wait-free. One thief cannot successfully continue until another
+ * in-progress one (or, if previously empty, a push) completes.
+ * However, in the aggregate, we ensure at least probabilistic
+ * non-blockingness. If an attempted steal fails, a thief always
+ * chooses a different random victim target to try next. So, in
+ * order for one thief to progress, it suffices for any
+ * in-progress poll or new push on any empty queue to
+ * complete. (This is why we normally use method pollAt and its
+ * variants that try once at the apparent base index, else
+ * consider alternative actions, rather than method poll.)
*
* This approach also enables support of a user mode in which local
* task processing is in FIFO, not LIFO order, simply by using
@@ -334,37 +339,35 @@
* has not yet entered the wait queue. We solve this by requiring
* a full sweep of all workers (via repeated calls to method
* scan()) both before and after a newly waiting worker is added
- * to the wait queue. During a rescan, the worker might release
- * some other queued worker rather than itself, which has the same
- * net effect. Because enqueued workers may actually be rescanning
- * rather than waiting, we set and clear the "parker" field of
- * WorkQueues to reduce unnecessary calls to unpark. (This
- * requires a secondary recheck to avoid missed signals.) Note
- * the unusual conventions about Thread.interrupts surrounding
- * parking and other blocking: Because interrupts are used solely
- * to alert threads to check termination, which is checked anyway
- * upon blocking, we clear status (using Thread.interrupted)
- * before any call to park, so that park does not immediately
- * return due to status being set via some other unrelated call to
- * interrupt in user code.
+ * to the wait queue. Because enqueued workers may actually be
+ * rescanning rather than waiting, we set and clear the "parker"
+ * field of WorkQueues to reduce unnecessary calls to unpark.
+ * (This requires a secondary recheck to avoid missed signals.)
+ * Note the unusual conventions about Thread.interrupts
+ * surrounding parking and other blocking: Because interrupts are
+ * used solely to alert threads to check termination, which is
+ * checked anyway upon blocking, we clear status (using
+ * Thread.interrupted) before any call to park, so that park does
+ * not immediately return due to status being set via some other
+ * unrelated call to interrupt in user code.
*
* Signalling. We create or wake up workers only when there
* appears to be at least one task they might be able to find and
- * execute. However, many other threads may notice the same task
- * and each signal to wake up a thread that might take it. So in
- * general, pools will be over-signalled. When a submission is
- * added or another worker adds a task to a queue that has fewer
- * than two tasks, they signal waiting workers (or trigger
- * creation of new ones if fewer than the given parallelism level
- * -- signalWork), and may leave a hint to the unparked worker to
- * help signal others upon wakeup). These primary signals are
- * buttressed by others (see method helpSignal) whenever other
- * threads scan for work or do not have a task to process. On
- * most platforms, signalling (unpark) overhead time is noticeably
+ * execute. When a submission is added or another worker adds a
+ * task to a queue that has fewer than two tasks, they signal
+ * waiting workers (or trigger creation of new ones if fewer than
+ * the given parallelism level -- signalWork). These primary
+ * signals are buttressed by others whenever other threads remove
+ * a task from a queue and notice that there are other tasks there
+ * as well. So in general, pools will be over-signalled. On most
+ * platforms, signalling (unpark) overhead time is noticeably
* long, and the time between signalling a thread and it actually
* making progress can be very noticeably long, so it is worth
* offloading these delays from critical paths as much as
- * possible.
+ * possible. Additionally, workers spin-down gradually, by staying
+ * alive so long as they see the ctl state changing. Similar
+ * stability-sensing techniques are also used before blocking in
+ * awaitJoin and helpComplete.
*
* Trimming workers. To release resources after periods of lack of
* use, a worker starting to wait when the pool is quiescent will
@@ -477,7 +480,7 @@
* Common Pool
* ===========
*
- * The static common Pool always exists after static
+ * The static common pool always exists after static
* initialization. Since it (or any other created pool) need
* never be used, we minimize initial construction overhead and
* footprint to the setup of about a dozen fields, with no nested
@@ -485,8 +488,11 @@
* fullExternalPush during the first submission to the pool.
*
* When external threads submit to the common pool, they can
- * perform some subtask processing (see externalHelpJoin and
- * related methods). We do not need to record whether these
+ * perform subtask processing (see externalHelpJoin and related
+ * methods). This caller-helps policy makes it sensible to set
+ * common pool parallelism level to one (or more) less than the
+ * total number of available cores, or even zero for pure
+ * caller-runs. We do not need to record whether external
* submissions are to the common pool -- if not, externalHelpJoin
* returns quickly (at the most helping to signal some common pool
* workers). These submitters would otherwise be blocked waiting
@@ -631,18 +637,10 @@
* do not want multiple WorkQueue instances or multiple queue
* arrays sharing cache lines. (It would be best for queue objects
* and their arrays to share, but there is nothing available to
- * help arrange that). Unfortunately, because they are recorded
- * in a common array, WorkQueue instances are often moved to be
- * adjacent by garbage collectors. To reduce impact, we use field
- * padding that works OK on common platforms; this effectively
- * trades off slightly slower average field access for the sake of
- * avoiding really bad worst-case access. (Until better JVM
- * support is in place, this padding is dependent on transient
- * properties of JVM field layout rules.) We also take care in
- * allocating, sizing and resizing the array. Non-shared queue
- * arrays are initialized by workers before use. Others are
- * allocated on first use.
+ * help arrange that). The @Contended annotation alerts JVMs to
+ * try to keep instances apart.
*/
+ @sun.misc.Contended
static final class WorkQueue {
/**
* Capacity of work-stealing queue array upon initialization.
@@ -664,16 +662,12 @@
*/
static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
- // Heuristic padding to ameliorate unfortunate memory placements
- volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06;
-
- int seed; // for random scanning; initialize nonzero
volatile int eventCount; // encoded inactivation count; < 0 if inactive
int nextWait; // encoded record of next event waiter
- int hint; // steal or signal hint (index)
- int poolIndex; // index of this queue in pool (or 0)
- final int mode; // 0: lifo, > 0: fifo, < 0: shared
int nsteals; // number of steals
+ int hint; // steal index hint
+ short poolIndex; // index of this queue in pool
+ final short mode; // 0: lifo, > 0: fifo, < 0: shared
volatile int qlock; // 1: locked, -1: terminate; else 0
volatile int base; // index of next slot for poll
int top; // index of next slot for push
@@ -684,15 +678,12 @@
volatile ForkJoinTask<?> currentJoin; // task being joined in awaitJoin
ForkJoinTask<?> currentSteal; // current non-local task being executed
- volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17;
- volatile Object pad18, pad19, pad1a, pad1b, pad1c, pad1d;
-
WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner, int mode,
int seed) {
this.pool = pool;
this.owner = owner;
- this.mode = mode;
- this.seed = seed;
+ this.mode = (short)mode;
+ this.hint = seed; // store initial seed for runWorker
// Place indices in the center of array (that is not yet allocated)
base = top = INITIAL_QUEUE_CAPACITY >>> 1;
}
@@ -705,7 +696,7 @@
return (n >= 0) ? 0 : -n; // ignore transient negative
}
- /**
+ /**
* Provides a more accurate estimate of whether this queue has
* any tasks than does queueSize, by checking whether a
* near-empty queue has at least one unclaimed task.
@@ -730,20 +721,18 @@
*/
final void push(ForkJoinTask<?> task) {
ForkJoinTask<?>[] a; ForkJoinPool p;
- int s = top, m, n;
+ int s = top, n;
if ((a = array) != null) { // ignore if queue removed
- int j = (((m = a.length - 1) & s) << ASHIFT) + ABASE;
- U.putOrderedObject(a, j, task);
- if ((n = (top = s + 1) - base) <= 2) {
- if ((p = pool) != null)
- p.signalWork(this);
- }
+ int m = a.length - 1;
+ U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task);
+ if ((n = (top = s + 1) - base) <= 2)
+ (p = pool).signalWork(p.workQueues, this);
else if (n >= m)
growArray();
}
}
- /**
+ /**
* Initializes or doubles the capacity of array. Call either
* by owner or with lock held -- it is OK for base, but not
* top, to move while resizings are in progress.
@@ -801,9 +790,8 @@
if ((a = array) != null) {
int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null &&
- base == b &&
- U.compareAndSwapObject(a, j, t, null)) {
- base = b + 1;
+ base == b && U.compareAndSwapObject(a, j, t, null)) {
+ U.putOrderedInt(this, QBASE, b + 1);
return t;
}
}
@@ -819,9 +807,8 @@
int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
if (t != null) {
- if (base == b &&
- U.compareAndSwapObject(a, j, t, null)) {
- base = b + 1;
+ if (U.compareAndSwapObject(a, j, t, null)) {
+ U.putOrderedInt(this, QBASE, b + 1);
return t;
}
}
@@ -878,49 +865,43 @@
ForkJoinTask.cancelIgnoringExceptions(t);
}
- /**
- * Computes next value for random probes. Scans don't require
- * a very high quality generator, but also not a crummy one.
- * Marsaglia xor-shift is cheap and works well enough. Note:
- * This is manually inlined in its usages in ForkJoinPool to
- * avoid writes inside busy scan loops.
- */
- final int nextSeed() {
- int r = seed;
- r ^= r << 13;
- r ^= r >>> 17;
- return seed = r ^= r << 5;
- }
-
// Specialized execution methods
/**
- * Pops and runs tasks until empty.
- */
- private void popAndExecAll() {
- // A bit faster than repeated pop calls
- ForkJoinTask<?>[] a; int m, s; long j; ForkJoinTask<?> t;
- while ((a = array) != null && (m = a.length - 1) >= 0 &&
- (s = top - 1) - base >= 0 &&
- (t = ((ForkJoinTask<?>)
- U.getObject(a, j = ((m & s) << ASHIFT) + ABASE)))
- != null) {
- if (U.compareAndSwapObject(a, j, t, null)) {
- top = s;
- t.doExec();
- }
- }
- }
-
- /**
* Polls and runs tasks until empty.
*/
- private void pollAndExecAll() {
+ final void pollAndExecAll() {
for (ForkJoinTask<?> t; (t = poll()) != null;)
t.doExec();
}
/**
+ * Executes a top-level task and any local tasks remaining
+ * after execution.
+ */
+ final void runTask(ForkJoinTask<?> task) {
+ if ((currentSteal = task) != null) {
+ task.doExec();
+ ForkJoinTask<?>[] a = array;
+ int md = mode;
+ ++nsteals;
+ currentSteal = null;
+ if (md != 0)
+ pollAndExecAll();
+ else if (a != null) {
+ int s, m = a.length - 1;
+ ForkJoinTask<?> t;
+ while ((s = top - 1) - base >= 0 &&
+ (t = (ForkJoinTask<?>)U.getAndSetObject
+ (a, ((m & s) << ASHIFT) + ABASE, null)) != null) {
+ top = s;
+ t.doExec();
+ }
+ }
+ }
+ }
+
+ /**
* If present, removes from queue and executes the given task,
* or any other cancelled task. Returns (true) on any CAS
* or consistency check failure so caller can retry.
@@ -928,13 +909,15 @@
* @return false if no progress can be made, else true
*/
final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
- boolean stat = true, removed = false, empty = true;
+ boolean stat;
ForkJoinTask<?>[] a; int m, s, b, n;
- if ((a = array) != null && (m = a.length - 1) >= 0 &&
+ if (task != null && (a = array) != null && (m = a.length - 1) >= 0 &&
(n = (s = top) - (b = base)) > 0) {
+ boolean removed = false, empty = true;
+ stat = true;
for (ForkJoinTask<?> t;;) { // traverse from s to b
- int j = ((--s & m) << ASHIFT) + ABASE;
- t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
+ long j = ((--s & m) << ASHIFT) + ABASE;
+ t = (ForkJoinTask<?>)U.getObject(a, j);
if (t == null) // inconsistent length
break;
else if (t == task) {
@@ -962,68 +945,95 @@
break;
}
}
+ if (removed)
+ task.doExec();
}
- if (removed)
- task.doExec();
+ else
+ stat = false;
return stat;
}
/**
- * Polls for and executes the given task or any other task in
- * its CountedCompleter computation.
+ * Tries to poll for and execute the given task or any other
+ * task in its CountedCompleter computation.
*/
- final boolean pollAndExecCC(ForkJoinTask<?> root) {
- ForkJoinTask<?>[] a; int b; Object o;
- outer: while ((b = base) - top < 0 && (a = array) != null) {
+ final boolean pollAndExecCC(CountedCompleter<?> root) {
+ ForkJoinTask<?>[] a; int b; Object o; CountedCompleter<?> t, r;
+ if ((b = base) - top < 0 && (a = array) != null) {
long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
- if ((o = U.getObject(a, j)) == null ||
- !(o instanceof CountedCompleter))
- break;
- for (CountedCompleter<?> t = (CountedCompleter<?>)o, r = t;;) {
- if (r == root) {
- if (base == b &&
- U.compareAndSwapObject(a, j, t, null)) {
- base = b + 1;
- t.doExec();
+ if ((o = U.getObjectVolatile(a, j)) == null)
+ return true; // retry
+ if (o instanceof CountedCompleter) {
+ for (t = (CountedCompleter<?>)o, r = t;;) {
+ if (r == root) {
+ if (base == b &&
+ U.compareAndSwapObject(a, j, t, null)) {
+ U.putOrderedInt(this, QBASE, b + 1);
+ t.doExec();
+ }
return true;
}
- else
- break; // restart
+ else if ((r = r.completer) == null)
+ break; // not part of root computation
}
- if ((r = r.completer) == null)
- break outer; // not part of root computation
}
}
return false;
}
/**
- * Executes a top-level task and any local tasks remaining
- * after execution.
+ * Tries to pop and execute the given task or any other task
+ * in its CountedCompleter computation.
*/
- final void runTask(ForkJoinTask<?> t) {
- if (t != null) {
- (currentSteal = t).doExec();
- currentSteal = null;
- ++nsteals;
- if (base - top < 0) { // process remaining local tasks
- if (mode == 0)
- popAndExecAll();
- else
- pollAndExecAll();
+ final boolean externalPopAndExecCC(CountedCompleter<?> root) {
+ ForkJoinTask<?>[] a; int s; Object o; CountedCompleter<?> t, r;
+ if (base - (s = top) < 0 && (a = array) != null) {
+ long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
+ if ((o = U.getObject(a, j)) instanceof CountedCompleter) {
+ for (t = (CountedCompleter<?>)o, r = t;;) {
+ if (r == root) {
+ if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
+ if (top == s && array == a &&
+ U.compareAndSwapObject(a, j, t, null)) {
+ top = s - 1;
+ qlock = 0;
+ t.doExec();
+ }
+ else
+ qlock = 0;
+ }
+ return true;
+ }
+ else if ((r = r.completer) == null)
+ break;
+ }
}
}
+ return false;
}
/**
- * Executes a non-top-level (stolen) task.
+ * Internal version
*/
- final void runSubtask(ForkJoinTask<?> t) {
- if (t != null) {
- ForkJoinTask<?> ps = currentSteal;
- (currentSteal = t).doExec();
- currentSteal = ps;
+ final boolean internalPopAndExecCC(CountedCompleter<?> root) {
+ ForkJoinTask<?>[] a; int s; Object o; CountedCompleter<?> t, r;
+ if (base - (s = top) < 0 && (a = array) != null) {
+ long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
+ if ((o = U.getObject(a, j)) instanceof CountedCompleter) {
+ for (t = (CountedCompleter<?>)o, r = t;;) {
+ if (r == root) {
+ if (U.compareAndSwapObject(a, j, t, null)) {
+ top = s - 1;
+ t.doExec();
+ }
+ return true;
+ }
+ else if ((r = r.completer) == null)
+ break;
+ }
+ }
}
+ return false;
}
/**
@@ -1040,6 +1050,7 @@
// Unsafe mechanics
private static final sun.misc.Unsafe U;
+ private static final long QBASE;
private static final long QLOCK;
private static final int ABASE;
private static final int ASHIFT;
@@ -1048,6 +1059,8 @@
U = sun.misc.Unsafe.getUnsafe();
Class<?> k = WorkQueue.class;
Class<?> ak = ForkJoinTask[].class;
+ QBASE = U.objectFieldOffset
+ (k.getDeclaredField("base"));
QLOCK = U.objectFieldOffset
(k.getDeclaredField("qlock"));
ABASE = U.arrayBaseOffset(ak);
@@ -1087,7 +1100,7 @@
/**
* Common pool parallelism. To allow simpler use and management
* when common pool threads are disabled, we allow the underlying
- * common.config field to be zero, but in that case still report
+ * common.parallelism field to be zero, but in that case still report
* parallelism as 1 to reflect resulting caller-runs mechanics.
*/
static final int commonParallelism;
@@ -1227,35 +1240,18 @@
static final int FIFO_QUEUE = 1;
static final int SHARED_QUEUE = -1;
- // bounds for #steps in scan loop -- must be power 2 minus 1
- private static final int MIN_SCAN = 0x1ff; // cover estimation slop
- private static final int MAX_SCAN = 0x1ffff; // 4 * max workers
-
// Instance fields
-
- /*
- * Field layout of this class tends to matter more than one would
- * like. Runtime layout order is only loosely related to
- * declaration order and may differ across JVMs, but the following
- * empirically works OK on current JVMs.
- */
-
- // Heuristic padding to ameliorate unfortunate memory placements
- volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06;
-
volatile long stealCount; // collects worker counts
volatile long ctl; // main pool control
volatile int plock; // shutdown status and seqLock
volatile int indexSeed; // worker/submitter index seed
- final int config; // mode and parallelism level
+ final short parallelism; // parallelism level
+ final short mode; // LIFO/FIFO
WorkQueue[] workQueues; // main registry
final ForkJoinWorkerThreadFactory factory;
final UncaughtExceptionHandler ueh; // per-worker UEH
final String workerNamePrefix; // to create worker name string
- volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17;
- volatile Object pad18, pad19, pad1a, pad1b;
-
/**
* Acquires the plock lock to protect worker array and related
* updates. This method is called only if an initial CAS on plock
@@ -1307,11 +1303,11 @@
* parallelism level exist. Adjusts counts etc on failure.
*/
private void tryAddWorker() {
- long c; int u;
+ long c; int u, e;
while ((u = (int)((c = ctl) >>> 32)) < 0 &&
- (u & SHORT_SIGN) != 0 && (int)c == 0) {
- long nc = (long)(((u + UTC_UNIT) & UTC_MASK) |
- ((u + UAC_UNIT) & UAC_MASK)) << 32;
+ (u & SHORT_SIGN) != 0 && (e = (int)c) >= 0) {
+ long nc = ((long)(((u + UTC_UNIT) & UTC_MASK) |
+ ((u + UAC_UNIT) & UAC_MASK)) << 32) | (long)e;
if (U.compareAndSwapLong(this, CTL, c, nc)) {
ForkJoinWorkerThreadFactory fac;
Throwable ex = null;
@@ -1322,8 +1318,8 @@
wt.start();
break;
}
- } catch (Throwable e) {
- ex = e;
+ } catch (Throwable rex) {
+ ex = rex;
}
deregisterWorker(wt, ex);
break;
@@ -1351,7 +1347,7 @@
do {} while (!U.compareAndSwapInt(this, INDEXSEED, s = indexSeed,
s += SEED_INCREMENT) ||
s == 0); // skip 0
- WorkQueue w = new WorkQueue(this, wt, config >>> 16, s);
+ WorkQueue w = new WorkQueue(this, wt, mode, s);
if (((ps = plock) & PL_LOCK) != 0 ||
!U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
ps = acquirePlock();
@@ -1371,14 +1367,15 @@
}
}
}
- w.eventCount = w.poolIndex = r; // volatile write orders
+ w.poolIndex = (short)r;
+ w.eventCount = r; // volatile write orders
ws[r] = w;
}
} finally {
if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
releasePlock(nps);
}
- wt.setName(workerNamePrefix.concat(Integer.toString(w.poolIndex)));
+ wt.setName(workerNamePrefix.concat(Integer.toString(w.poolIndex >>> 1)));
return w;
}
@@ -1396,9 +1393,7 @@
if (wt != null && (w = wt.workQueue) != null) {
int ps;
w.qlock = -1; // ensure set
- long ns = w.nsteals, sc; // collect steal count
- do {} while (!U.compareAndSwapLong(this, STEALCOUNT,
- sc = stealCount, sc + ns));
+ U.getAndAddLong(this, STEALCOUNT, w.nsteals); // collect steals
if (((ps = plock) & PL_LOCK) != 0 ||
!U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
ps = acquirePlock();
@@ -1464,19 +1459,21 @@
* @param task the task. Caller must ensure non-null.
*/
final void externalPush(ForkJoinTask<?> task) {
- WorkQueue[] ws; WorkQueue q; int z, m; ForkJoinTask<?>[] a;
- if ((z = ThreadLocalRandom.getProbe()) != 0 && plock > 0 &&
- (ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&
- (q = ws[m & z & SQMASK]) != null &&
+ WorkQueue q; int m, s, n, am; ForkJoinTask<?>[] a;
+ int r = ThreadLocalRandom.getProbe();
+ int ps = plock;
+ WorkQueue[] ws = workQueues;
+ if (ps > 0 && ws != null && (m = (ws.length - 1)) >= 0 &&
+ (q = ws[m & r & SQMASK]) != null && r != 0 &&
U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock
- int b = q.base, s = q.top, n, an;
- if ((a = q.array) != null && (an = a.length) > (n = s + 1 - b)) {
- int j = (((an - 1) & s) << ASHIFT) + ABASE;
+ if ((a = q.array) != null &&
+ (am = a.length - 1) > (n = (s = q.top) - q.base)) {
+ int j = ((am & s) << ASHIFT) + ABASE;
U.putOrderedObject(a, j, task);
q.top = s + 1; // push on to deque
q.qlock = 0;
- if (n <= 2)
- signalWork(q);
+ if (n <= 1)
+ signalWork(ws, q);
return;
}
q.qlock = 0;
@@ -1514,7 +1511,7 @@
throw new RejectedExecutionException();
else if (ps == 0 || (ws = workQueues) == null ||
(m = ws.length - 1) < 0) { // initialize workQueues
- int p = config & SMASK; // find power of two table size
+ int p = parallelism; // find power of two table size
int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots
n |= n >>> 1; n |= n >>> 2; n |= n >>> 4;
n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1;
@@ -1546,7 +1543,7 @@
q.qlock = 0; // unlock
}
if (submitted) {
- signalWork(q);
+ signalWork(ws, q);
return;
}
}
@@ -1554,6 +1551,7 @@
}
else if (((ps = plock) & PL_LOCK) == 0) { // create new queue
q = new WorkQueue(this, null, SHARED_QUEUE, r);
+ q.poolIndex = (short)k;
if (((ps = plock) & PL_LOCK) != 0 ||
!U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
ps = acquirePlock();
@@ -1577,41 +1575,42 @@
*/
final void incrementActiveCount() {
long c;
- do {} while (!U.compareAndSwapLong(this, CTL, c = ctl, c + AC_UNIT));
+ do {} while (!U.compareAndSwapLong
+ (this, CTL, c = ctl, ((c & ~AC_MASK) |
+ ((c & AC_MASK) + AC_UNIT))));
}
/**
* Tries to create or activate a worker if too few are active.
*
- * @param q the (non-null) queue holding tasks to be signalled
+ * @param ws the worker array to use to find signallees
+ * @param q if non-null, the queue holding tasks to be processed
*/
- final void signalWork(WorkQueue q) {
- int hint = q.poolIndex;
- long c; int e, u, i, n; WorkQueue[] ws; WorkQueue w; Thread p;
- while ((u = (int)((c = ctl) >>> 32)) < 0) {
- if ((e = (int)c) > 0) {
- if ((ws = workQueues) != null && ws.length > (i = e & SMASK) &&
- (w = ws[i]) != null && w.eventCount == (e | INT_SIGN)) {
- long nc = (((long)(w.nextWait & E_MASK)) |
- ((long)(u + UAC_UNIT) << 32));
- if (U.compareAndSwapLong(this, CTL, c, nc)) {
- w.hint = hint;
- w.eventCount = (e + E_SEQ) & E_MASK;
- if ((p = w.parker) != null)
- U.unpark(p);
- break;
- }
- if (q.top - q.base <= 0)
- break;
- }
- else
- break;
- }
- else {
+ final void signalWork(WorkQueue[] ws, WorkQueue q) {
+ for (;;) {
+ long c; int e, u, i; WorkQueue w; Thread p;
+ if ((u = (int)((c = ctl) >>> 32)) >= 0)
+ break;
+ if ((e = (int)c) <= 0) {
if ((short)u < 0)
tryAddWorker();
break;
}
+ if (ws == null || ws.length <= (i = e & SMASK) ||
+ (w = ws[i]) == null)
+ break;
+ long nc = (((long)(w.nextWait & E_MASK)) |
+ ((long)(u + UAC_UNIT)) << 32);
+ int ne = (e + E_SEQ) & E_MASK;
+ if (w.eventCount == (e | INT_SIGN) &&
+ U.compareAndSwapLong(this, CTL, c, nc)) {
+ w.eventCount = ne;
+ if ((p = w.parker) != null)
+ U.unpark(p);
+ break;
+ }
+ if (q != null && q.base >= q.top)
+ break;
}
}
@@ -1622,215 +1621,152 @@
*/
final void runWorker(WorkQueue w) {
w.growArray(); // allocate queue
- do { w.runTask(scan(w)); } while (w.qlock >= 0);
+ for (int r = w.hint; scan(w, r) == 0; ) {
+ r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
+ }
}
/**
- * Scans for and, if found, returns one task, else possibly
+ * Scans for and, if found, runs one task, else possibly
* inactivates the worker. This method operates on single reads of
* volatile state and is designed to be re-invoked continuously,
* in part because it returns upon detecting inconsistencies,
* contention, or state changes that indicate possible success on
* re-invocation.
*
- * The scan searches for tasks across queues (starting at a random
- * index, and relying on registerWorker to irregularly scatter
- * them within array to avoid bias), checking each at least twice.
- * The scan terminates upon either finding a non-empty queue, or
- * completing the sweep. If the worker is not inactivated, it
- * takes and returns a task from this queue. Otherwise, if not
- * activated, it signals workers (that may include itself) and
- * returns so caller can retry. Also returns for true if the
- * worker array may have changed during an empty scan. On failure
- * to find a task, we take one of the following actions, after
- * which the caller will retry calling this method unless
- * terminated.
- *
- * * If pool is terminating, terminate the worker.
- *
- * * If not already enqueued, try to inactivate and enqueue the
- * worker on wait queue. Or, if inactivating has caused the pool
- * to be quiescent, relay to idleAwaitWork to possibly shrink
- * pool.
- *
- * * If already enqueued and none of the above apply, possibly
- * park awaiting signal, else lingering to help scan and signal.
- *
- * * If a non-empty queue discovered or left as a hint,
- * help wake up other workers before return.
+ * The scan searches for tasks across queues starting at a random
+ * index, checking each at least twice. The scan terminates upon
+ * either finding a non-empty queue, or completing the sweep. If
+ * the worker is not inactivated, it takes and runs a task from
+ * this queue. Otherwise, if not activated, it tries to activate
+ * itself or some other worker by signalling. On failure to find a
+ * task, returns (for retry) if pool state may have changed during
+ * an empty scan, or tries to inactivate if active, else possibly
+ * blocks or terminates via method awaitWork.
*
* @param w the worker (via its WorkQueue)
- * @return a task or null if none found
+ * @param r a random seed
+ * @return worker qlock status if would have waited, else 0
*/
- private final ForkJoinTask<?> scan(WorkQueue w) {
+ private final int scan(WorkQueue w, int r) {
WorkQueue[] ws; int m;
- int ps = plock; // read plock before ws
- if (w != null && (ws = workQueues) != null && (m = ws.length - 1) >= 0) {
- int ec = w.eventCount; // ec is negative if inactive
- int r = w.seed; r ^= r << 13; r ^= r >>> 17; w.seed = r ^= r << 5;
- w.hint = -1; // update seed and clear hint
- int j = ((m + m + 1) | MIN_SCAN) & MAX_SCAN;
- do {
- WorkQueue q; ForkJoinTask<?>[] a; int b;
- if ((q = ws[(r + j) & m]) != null && (b = q.base) - q.top < 0 &&
- (a = q.array) != null) { // probably nonempty
- int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
- ForkJoinTask<?> t = (ForkJoinTask<?>)
- U.getObjectVolatile(a, i);
- if (q.base == b && ec >= 0 && t != null &&
- U.compareAndSwapObject(a, i, t, null)) {
- if ((q.base = b + 1) - q.top < 0)
- signalWork(q);
- return t; // taken
- }
- else if ((ec < 0 || j < m) && (int)(ctl >> AC_SHIFT) <= 0) {
- w.hint = (r + j) & m; // help signal below
- break; // cannot take
+ long c = ctl; // for consistency check
+ if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && w != null) {
+ for (int j = m + m + 1, ec = w.eventCount;;) {
+ WorkQueue q; int b, e; ForkJoinTask<?>[] a; ForkJoinTask<?> t;
+ if ((q = ws[(r - j) & m]) != null &&
+ (b = q.base) - q.top < 0 && (a = q.array) != null) {
+ long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+ if ((t = ((ForkJoinTask<?>)
+ U.getObjectVolatile(a, i))) != null) {
+ if (ec < 0)
+ helpRelease(c, ws, w, q, b);
+ else if (q.base == b &&
+ U.compareAndSwapObject(a, i, t, null)) {
+ U.putOrderedInt(q, QBASE, b + 1);
+ if ((b + 1) - q.top < 0)
+ signalWork(ws, q);
+ w.runTask(t);
+ }
}
- }
- } while (--j >= 0);
-
- int h, e, ns; long c, sc; WorkQueue q;
- if ((ns = w.nsteals) != 0) {
- if (U.compareAndSwapLong(this, STEALCOUNT,
- sc = stealCount, sc + ns))
- w.nsteals = 0; // collect steals and rescan
- }
- else if (plock != ps) // consistency check
- ; // skip
- else if ((e = (int)(c = ctl)) < 0)
- w.qlock = -1; // pool is terminating
- else {
- if ((h = w.hint) < 0) {
- if (ec >= 0) { // try to enqueue/inactivate
- long nc = (((long)ec |
- ((c - AC_UNIT) & (AC_MASK|TC_MASK))));
- w.nextWait = e; // link and mark inactive
- w.eventCount = ec | INT_SIGN;
- if (ctl != c || !U.compareAndSwapLong(this, CTL, c, nc))
- w.eventCount = ec; // unmark on CAS failure
- else if ((int)(c >> AC_SHIFT) == 1 - (config & SMASK))
- idleAwaitWork(w, nc, c);
- }
- else if (w.eventCount < 0 && ctl == c) {
- Thread wt = Thread.currentThread();
- Thread.interrupted(); // clear status
- U.putObject(wt, PARKBLOCKER, this);
- w.parker = wt; // emulate LockSupport.park
- if (w.eventCount < 0) // recheck
- U.park(false, 0L); // block
- w.parker = null;
- U.putObject(wt, PARKBLOCKER, null);
- }
+ break;
}
- if ((h >= 0 || (h = w.hint) >= 0) &&
- (ws = workQueues) != null && h < ws.length &&
- (q = ws[h]) != null) { // signal others before retry
- WorkQueue v; Thread p; int u, i, s;
- for (int n = (config & SMASK) - 1;;) {
- int idleCount = (w.eventCount < 0) ? 0 : -1;
- if (((s = idleCount - q.base + q.top) <= n &&
- (n = s) <= 0) ||
- (u = (int)((c = ctl) >>> 32)) >= 0 ||
- (e = (int)c) <= 0 || m < (i = e & SMASK) ||
- (v = ws[i]) == null)
- break;
- long nc = (((long)(v.nextWait & E_MASK)) |
- ((long)(u + UAC_UNIT) << 32));
- if (v.eventCount != (e | INT_SIGN) ||
- !U.compareAndSwapLong(this, CTL, c, nc))
- break;
- v.hint = h;
- v.eventCount = (e + E_SEQ) & E_MASK;
- if ((p = v.parker) != null)
- U.unpark(p);
- if (--n <= 0)
- break;
+ else if (--j < 0) {
+ if ((ec | (e = (int)c)) < 0) // inactive or terminating
+ return awaitWork(w, c, ec);
+ else if (ctl == c) { // try to inactivate and enqueue
+ long nc = (long)ec | ((c - AC_UNIT) & (AC_MASK|TC_MASK));
+ w.nextWait = e;
+ w.eventCount = ec | INT_SIGN;
+ if (!U.compareAndSwapLong(this, CTL, c, nc))
+ w.eventCount = ec; // back out
}
- }
- }
- }
- return null;
- }
-
- /**
- * If inactivating worker w has caused the pool to become
- * quiescent, checks for pool termination, and, so long as this is
- * not the only worker, waits for event for up to a given
- * duration. On timeout, if ctl has not changed, terminates the
- * worker, which will in turn wake up another worker to possibly
- * repeat this process.
- *
- * @param w the calling worker
- * @param currentCtl the ctl value triggering possible quiescence
- * @param prevCtl the ctl value to restore if thread is terminated
- */
- private void idleAwaitWork(WorkQueue w, long currentCtl, long prevCtl) {
- if (w != null && w.eventCount < 0 &&
- !tryTerminate(false, false) && (int)prevCtl != 0 &&
- ctl == currentCtl) {
- int dc = -(short)(currentCtl >>> TC_SHIFT);
- long parkTime = dc < 0 ? FAST_IDLE_TIMEOUT: (dc + 1) * IDLE_TIMEOUT;
- long deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
- Thread wt = Thread.currentThread();
- while (ctl == currentCtl) {
- Thread.interrupted(); // timed variant of version in scan()
- U.putObject(wt, PARKBLOCKER, this);
- w.parker = wt;
- if (ctl == currentCtl)
- U.park(false, parkTime);
- w.parker = null;
- U.putObject(wt, PARKBLOCKER, null);
- if (ctl != currentCtl)
- break;
- if (deadline - System.nanoTime() <= 0L &&
- U.compareAndSwapLong(this, CTL, currentCtl, prevCtl)) {
- w.eventCount = (w.eventCount + E_SEQ) | E_MASK;
- w.hint = -1;
- w.qlock = -1; // shrink
break;
}
}
}
+ return 0;
}
/**
- * Scans through queues looking for work while joining a task; if
- * any present, signals. May return early if more signalling is
- * detectably unneeded.
+ * A continuation of scan(), possibly blocking or terminating
+ * worker w. Returns without blocking if pool state has apparently
+ * changed since last invocation. Also, if inactivating w has
+ * caused the pool to become quiescent, checks for pool
+ * termination, and, so long as this is not the only worker, waits
+ * for event for up to a given duration. On timeout, if ctl has
+ * not changed, terminates the worker, which will in turn wake up
+ * another worker to possibly repeat this process.
*
- * @param task return early if done
- * @param origin an index to start scan
+ * @param w the calling worker
+ * @param c the ctl value on entry to scan
+ * @param ec the worker's eventCount on entry to scan
*/
- private void helpSignal(ForkJoinTask<?> task, int origin) {
- WorkQueue[] ws; WorkQueue w; Thread p; long c; int m, u, e, i, s;
- if (task != null && task.status >= 0 &&
- (u = (int)(ctl >>> 32)) < 0 && (u >> UAC_SHIFT) < 0 &&
- (ws = workQueues) != null && (m = ws.length - 1) >= 0) {
- outer: for (int k = origin, j = m; j >= 0; --j) {
- WorkQueue q = ws[k++ & m];
- for (int n = m;;) { // limit to at most m signals
- if (task.status < 0)
- break outer;
- if (q == null ||
- ((s = -q.base + q.top) <= n && (n = s) <= 0))
- break;
- if ((u = (int)((c = ctl) >>> 32)) >= 0 ||
- (e = (int)c) <= 0 || m < (i = e & SMASK) ||
- (w = ws[i]) == null)
- break outer;
- long nc = (((long)(w.nextWait & E_MASK)) |
- ((long)(u + UAC_UNIT) << 32));
- if (w.eventCount != (e | INT_SIGN))
- break outer;
- if (U.compareAndSwapLong(this, CTL, c, nc)) {
- w.eventCount = (e + E_SEQ) & E_MASK;
- if ((p = w.parker) != null)
- U.unpark(p);
- if (--n <= 0)
- break;
- }
+ private final int awaitWork(WorkQueue w, long c, int ec) {
+ int stat, ns; long parkTime, deadline;
+ if ((stat = w.qlock) >= 0 && w.eventCount == ec && ctl == c &&
+ !Thread.interrupted()) {
+ int e = (int)c;
+ int u = (int)(c >>> 32);
+ int d = (u >> UAC_SHIFT) + parallelism; // active count
+
+ if (e < 0 || (d <= 0 && tryTerminate(false, false)))
+ stat = w.qlock = -1; // pool is terminating
+ else if ((ns = w.nsteals) != 0) { // collect steals and retry
+ w.nsteals = 0;
+ U.getAndAddLong(this, STEALCOUNT, (long)ns);
+ }
+ else {
+ long pc = ((d > 0 || ec != (e | INT_SIGN)) ? 0L :
+ ((long)(w.nextWait & E_MASK)) | // ctl to restore
+ ((long)(u + UAC_UNIT)) << 32);
+ if (pc != 0L) { // timed wait if last waiter
+ int dc = -(short)(c >>> TC_SHIFT);
+ parkTime = (dc < 0 ? FAST_IDLE_TIMEOUT:
+ (dc + 1) * IDLE_TIMEOUT);
+ deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
}
+ else
+ parkTime = deadline = 0L;
+ if (w.eventCount == ec && ctl == c) {
+ Thread wt = Thread.currentThread();
+ U.putObject(wt, PARKBLOCKER, this);
+ w.parker = wt; // emulate LockSupport.park
+ if (w.eventCount == ec && ctl == c)
+ U.park(false, parkTime); // must recheck before park
+ w.parker = null;
+ U.putObject(wt, PARKBLOCKER, null);
+ if (parkTime != 0L && ctl == c &&
+ deadline - System.nanoTime() <= 0L &&
+ U.compareAndSwapLong(this, CTL, c, pc))
+ stat = w.qlock = -1; // shrink pool
+ }
+ }
+ }
+ return stat;
+ }
+
+ /**
+ * Possibly releases (signals) a worker. Called only from scan()
+ * when a worker with apparently inactive status finds a non-empty
+ * queue. This requires revalidating all of the associated state
+ * from caller.
+ */
+ private final void helpRelease(long c, WorkQueue[] ws, WorkQueue w,
+ WorkQueue q, int b) {
+ WorkQueue v; int e, i; Thread p;
+ if (w != null && w.eventCount < 0 && (e = (int)c) > 0 &&
+ ws != null && ws.length > (i = e & SMASK) &&
+ (v = ws[i]) != null && ctl == c) {
+ long nc = (((long)(v.nextWait & E_MASK)) |
+ ((long)((int)(c >>> 32) + UAC_UNIT)) << 32);
+ int ne = (e + E_SEQ) & E_MASK;
+ if (q != null && q.base == b && w.eventCount < 0 &&
+ v.eventCount == (e | INT_SIGN) &&
+ U.compareAndSwapLong(this, CTL, c, nc)) {
+ v.eventCount = ne;
+ if ((p = v.parker) != null)
+ U.unpark(p);
}
}
}
@@ -1855,7 +1791,8 @@
*/
private int tryHelpStealer(WorkQueue joiner, ForkJoinTask<?> task) {
int stat = 0, steps = 0; // bound to avoid cycles
- if (joiner != null && task != null) { // hoist null checks
+ if (task != null && joiner != null &&
+ joiner.base - joiner.top >= 0) { // hoist checks
restart: for (;;) {
ForkJoinTask<?> subtask = task; // current target
for (WorkQueue j = joiner, v;;) { // v is stealer of subtask
@@ -1882,7 +1819,7 @@
}
}
for (;;) { // help stealer or descend to its stealer
- ForkJoinTask[] a; int b;
+ ForkJoinTask[] a; int b;
if (subtask.status < 0) // surround probes with
continue restart; // consistency checks
if ((b = v.base) - v.top < 0 && (a = v.array) != null) {
@@ -1893,13 +1830,23 @@
v.currentSteal != subtask)
continue restart; // stale
stat = 1; // apparent progress
- if (t != null && v.base == b &&
- U.compareAndSwapObject(a, i, t, null)) {
- v.base = b + 1; // help stealer
- joiner.runSubtask(t);
+ if (v.base == b) {
+ if (t == null)
+ break restart;
+ if (U.compareAndSwapObject(a, i, t, null)) {
+ U.putOrderedInt(v, QBASE, b + 1);
+ ForkJoinTask<?> ps = joiner.currentSteal;
+ int jt = joiner.top;
+ do {
+ joiner.currentSteal = t;
+ t.doExec(); // clear local tasks too
+ } while (task.status >= 0 &&
+ joiner.top != jt &&
+ (t = joiner.pop()) != null);
+ joiner.currentSteal = ps;
+ break restart;
+ }
}
- else if (v.base == b && ++steps == MAX_HELP)
- break restart; // v apparently stalled
}
else { // empty -- try to descend
ForkJoinTask<?> next = v.currentJoin;
@@ -1926,27 +1873,45 @@
* and run tasks within the target's computation.
*
* @param task the task to join
- * @param mode if shared, exit upon completing any task
- * if all workers are active
+ * @param maxTasks the maximum number of other tasks to run
*/
- private int helpComplete(ForkJoinTask<?> task, int mode) {
- WorkQueue[] ws; WorkQueue q; int m, n, s, u;
- if (task != null && (ws = workQueues) != null &&
- (m = ws.length - 1) >= 0) {
- for (int j = 1, origin = j;;) {
+ final int helpComplete(WorkQueue joiner, CountedCompleter<?> task,
+ int maxTasks) {
+ WorkQueue[] ws; int m;
+ int s = 0;
+ if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 &&
+ joiner != null && task != null) {
+ int j = joiner.poolIndex;
+ int scans = m + m + 1;
+ long c = 0L; // for stability check
+ for (int k = scans; ; j += 2) {
+ WorkQueue q;
if ((s = task.status) < 0)
- return s;
- if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) {
- origin = j;
- if (mode == SHARED_QUEUE &&
- ((u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0))
+ break;
+ else if (joiner.internalPopAndExecCC(task)) {
+ if (--maxTasks <= 0) {
+ s = task.status;
break;
+ }
+ k = scans;
}
- else if ((j = (j + 2) & m) == origin)
+ else if ((s = task.status) < 0)
break;
+ else if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) {
+ if (--maxTasks <= 0) {
+ s = task.status;
+ break;
+ }
+ k = scans;
+ }
+ else if (--k < 0) {
+ if (c == (c = ctl))
+ break;
+ k = scans;
+ }
}
}
- return 0;
+ return s;
}
/**
@@ -1955,17 +1920,22 @@
* for blocking. Fails on contention or termination. Otherwise,
* adds a new thread if no idle workers are available and pool
* may become starved.
+ *
+ * @param c the assumed ctl value
*/
- final boolean tryCompensate() {
- int pc = config & SMASK, e, i, tc; long c;
- WorkQueue[] ws; WorkQueue w; Thread p;
- if ((ws = workQueues) != null && (e = (int)(c = ctl)) >= 0) {
- if (e != 0 && (i = e & SMASK) < ws.length &&
- (w = ws[i]) != null && w.eventCount == (e | INT_SIGN)) {
+ final boolean tryCompensate(long c) {
+ WorkQueue[] ws = workQueues;
+ int pc = parallelism, e = (int)c, m, tc;
+ if (ws != null && (m = ws.length - 1) >= 0 && e >= 0 && ctl == c) {
+ WorkQueue w = ws[e & m];
+ if (e != 0 && w != null) {
+ Thread p;
long nc = ((long)(w.nextWait & E_MASK) |
(c & (AC_MASK|TC_MASK)));
- if (U.compareAndSwapLong(this, CTL, c, nc)) {
- w.eventCount = (e + E_SEQ) & E_MASK;
+ int ne = (e + E_SEQ) & E_MASK;
+ if (w.eventCount == (e | INT_SIGN) &&
+ U.compareAndSwapLong(this, CTL, c, nc)) {
+ w.eventCount = ne;
if ((p = w.parker) != null)
U.unpark(p);
return true; // replace with idle worker
@@ -2008,23 +1978,20 @@
*/
final int awaitJoin(WorkQueue joiner, ForkJoinTask<?> task) {
int s = 0;
- if (joiner != null && task != null && (s = task.status) >= 0) {
+ if (task != null && (s = task.status) >= 0 && joiner != null) {
ForkJoinTask<?> prevJoin = joiner.currentJoin;
joiner.currentJoin = task;
- do {} while ((s = task.status) >= 0 && !joiner.isEmpty() &&
- joiner.tryRemoveAndExec(task)); // process local tasks
- if (s >= 0 && (s = task.status) >= 0) {
- helpSignal(task, joiner.poolIndex);
- if ((s = task.status) >= 0 &&
- (task instanceof CountedCompleter))
- s = helpComplete(task, LIFO_QUEUE);
- }
+ do {} while (joiner.tryRemoveAndExec(task) && // process local tasks
+ (s = task.status) >= 0);
+ if (s >= 0 && (task instanceof CountedCompleter))
+ s = helpComplete(joiner, (CountedCompleter<?>)task, Integer.MAX_VALUE);
+ long cc = 0; // for stability checks
while (s >= 0 && (s = task.status) >= 0) {
- if ((!joiner.isEmpty() || // try helping
- (s = tryHelpStealer(joiner, task)) == 0) &&
+ if ((s = tryHelpStealer(joiner, task)) == 0 &&
(s = task.status) >= 0) {
- helpSignal(task, joiner.poolIndex);
- if ((s = task.status) >= 0 && tryCompensate()) {
+ if (!tryCompensate(cc))
+ cc = ctl;
+ else {
if (task.trySetSignal() && (s = task.status) >= 0) {
synchronized (task) {
if (task.status >= 0) {
@@ -2037,9 +2004,11 @@
task.notifyAll();
}
}
- long c; // re-activate
+ long c; // reactivate
do {} while (!U.compareAndSwapLong
- (this, CTL, c = ctl, c + AC_UNIT));
+ (this, CTL, c = ctl,
+ ((c & ~AC_MASK) |
+ ((c & AC_MASK) + AC_UNIT))));
}
}
}
@@ -2061,15 +2030,11 @@
if (joiner != null && task != null && (s = task.status) >= 0) {
ForkJoinTask<?> prevJoin = joiner.currentJoin;
joiner.currentJoin = task;
- do {} while ((s = task.status) >= 0 && !joiner.isEmpty() &&
- joiner.tryRemoveAndExec(task));
- if (s >= 0 && (s = task.status) >= 0) {
- helpSignal(task, joiner.poolIndex);
- if ((s = task.status) >= 0 &&
- (task instanceof CountedCompleter))
- s = helpComplete(task, LIFO_QUEUE);
- }
- if (s >= 0 && joiner.isEmpty()) {
+ do {} while (joiner.tryRemoveAndExec(task) && // process local tasks
+ (s = task.status) >= 0);
+ if (s >= 0) {
+ if (task instanceof CountedCompleter)
+ helpComplete(joiner, (CountedCompleter<?>)task, Integer.MAX_VALUE);
do {} while (task.status >= 0 &&
tryHelpStealer(joiner, task) > 0);
}
@@ -2081,14 +2046,14 @@
* Returns a (probably) non-empty steal queue, if one is found
* during a scan, else null. This method must be retried by
* caller if, by the time it tries to use the queue, it is empty.
- * @param r a (random) seed for scanning
*/
- private WorkQueue findNonEmptyStealQueue(int r) {
+ private WorkQueue findNonEmptyStealQueue() {
+ int r = ThreadLocalRandom.nextSecondarySeed();
for (;;) {
int ps = plock, m; WorkQueue[] ws; WorkQueue q;
if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) {
for (int j = (m + 1) << 2; j >= 0; --j) {
- if ((q = ws[(((r + j) << 1) | 1) & m]) != null &&
+ if ((q = ws[(((r - j) << 1) | 1) & m]) != null &&
q.base - q.top < 0)
return q;
}
@@ -2105,35 +2070,36 @@
* find tasks either.
*/
final void helpQuiescePool(WorkQueue w) {
+ ForkJoinTask<?> ps = w.currentSteal;
for (boolean active = true;;) {
long c; WorkQueue q; ForkJoinTask<?> t; int b;
- while ((t = w.nextLocalTask()) != null) {
- if (w.base - w.top < 0)
- signalWork(w);
+ while ((t = w.nextLocalTask()) != null)
t.doExec();
- }
- if ((q = findNonEmptyStealQueue(w.nextSeed())) != null) {
+ if ((q = findNonEmptyStealQueue()) != null) {
if (!active) { // re-establish active count
active = true;
do {} while (!U.compareAndSwapLong
- (this, CTL, c = ctl, c + AC_UNIT));
+ (this, CTL, c = ctl,
+ ((c & ~AC_MASK) |
+ ((c & AC_MASK) + AC_UNIT))));
}
if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) {
- if (q.base - q.top < 0)
- signalWork(q);
- w.runSubtask(t);
+ (w.currentSteal = t).doExec();
+ w.currentSteal = ps;
}
}
else if (active) { // decrement active count without queuing
- long nc = (c = ctl) - AC_UNIT;
- if ((int)(nc >> AC_SHIFT) + (config & SMASK) == 0)
- return; // bypass decrement-then-increment
+ long nc = ((c = ctl) & ~AC_MASK) | ((c & AC_MASK) - AC_UNIT);
+ if ((int)(nc >> AC_SHIFT) + parallelism == 0)
+ break; // bypass decrement-then-increment
if (U.compareAndSwapLong(this, CTL, c, nc))
active = false;
}
- else if ((int)((c = ctl) >> AC_SHIFT) + (config & SMASK) == 0 &&
- U.compareAndSwapLong(this, CTL, c, c + AC_UNIT))
- return;
+ else if ((int)((c = ctl) >> AC_SHIFT) + parallelism <= 0 &&
+ U.compareAndSwapLong
+ (this, CTL, c, ((c & ~AC_MASK) |
+ ((c & AC_MASK) + AC_UNIT))))
+ break;
}
}
@@ -2147,13 +2113,10 @@
WorkQueue q; int b;
if ((t = w.nextLocalTask()) != null)
return t;
- if ((q = findNonEmptyStealQueue(w.nextSeed())) == null)
+ if ((q = findNonEmptyStealQueue()) == null)
return null;
- if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) {
- if (q.base - q.top < 0)
- signalWork(q);
+ if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
return t;
- }
}
}
@@ -2206,7 +2169,7 @@
static int getSurplusQueuedTaskCount() {
Thread t; ForkJoinWorkerThread wt; ForkJoinPool pool; WorkQueue q;
if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)) {
- int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).config & SMASK;
+ int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).parallelism;
int n = (q = wt.workQueue).top - q.base;
int a = (int)(pool.ctl >> AC_SHIFT) + p;
return n - (a > (p >>>= 1) ? 0 :
@@ -2236,7 +2199,7 @@
*/
private boolean tryTerminate(boolean now, boolean enable) {
int ps;
- if (this == common) // cannot shut down
+ if (this == common) // cannot shut down
return false;
if ((ps = plock) >= 0) { // enable by setting plock
if (!enable)
@@ -2250,7 +2213,7 @@
}
for (long c;;) {
if (((c = ctl) & STOP_BIT) != 0) { // already terminating
- if ((short)(c >>> TC_SHIFT) == -(config & SMASK)) {
+ if ((short)(c >>> TC_SHIFT) + parallelism <= 0) {
synchronized (this) {
notifyAll(); // signal when 0 workers
}
@@ -2259,17 +2222,15 @@
}
if (!now) { // check if idle & no tasks
WorkQueue[] ws; WorkQueue w;
- if ((int)(c >> AC_SHIFT) != -(config & SMASK))
+ if ((int)(c >> AC_SHIFT) + parallelism > 0)
return false;
if ((ws = workQueues) != null) {
for (int i = 0; i < ws.length; ++i) {
- if ((w = ws[i]) != null) {
- if (!w.isEmpty()) { // signal unprocessed tasks
- signalWork(w);
- return false;
- }
- if ((i & 1) != 0 && w.eventCount >= 0)
- return false; // unqueued inactive worker
+ if ((w = ws[i]) != null &&
+ (!w.isEmpty() ||
+ ((i & 1) != 0 && w.eventCount >= 0))) {
+ signalWork(ws, w);
+ return false;
}
}
}
@@ -2336,116 +2297,67 @@
/**
* Tries to pop the given task from submitter's queue in common pool.
*/
- static boolean tryExternalUnpush(ForkJoinTask<?> t) {
- ForkJoinPool p; WorkQueue[] ws; WorkQueue q;
- ForkJoinTask<?>[] a; int m, s, z;
- if (t != null &&
- (z = ThreadLocalRandom.getProbe()) != 0 &&
- (p = common) != null &&
- (ws = p.workQueues) != null &&
- (m = ws.length - 1) >= 0 &&
- (q = ws[m & z & SQMASK]) != null &&
- (s = q.top) != q.base &&
- (a = q.array) != null) {
+ final boolean tryExternalUnpush(ForkJoinTask<?> task) {
+ WorkQueue joiner; ForkJoinTask<?>[] a; int m, s;
+ WorkQueue[] ws = workQueues;
+ int z = ThreadLocalRandom.getProbe();
+ boolean popped = false;
+ if (ws != null && (m = ws.length - 1) >= 0 &&
+ (joiner = ws[z & m & SQMASK]) != null &&
+ joiner.base != (s = joiner.top) &&
+ (a = joiner.array) != null) {
long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
- if (U.getObject(a, j) == t &&
- U.compareAndSwapInt(q, QLOCK, 0, 1)) {
- if (q.array == a && q.top == s && // recheck
- U.compareAndSwapObject(a, j, t, null)) {
- q.top = s - 1;
- q.qlock = 0;
- return true;
+ if (U.getObject(a, j) == task &&
+ U.compareAndSwapInt(joiner, QLOCK, 0, 1)) {
+ if (joiner.top == s && joiner.array == a &&
+ U.compareAndSwapObject(a, j, task, null)) {
+ joiner.top = s - 1;
+ popped = true;
}
- q.qlock = 0;
+ joiner.qlock = 0;
}
}
- return false;
+ return popped;
}
- /**
- * Tries to pop and run local tasks within the same computation
- * as the given root. On failure, tries to help complete from
- * other queues via helpComplete.
- */
- private void externalHelpComplete(WorkQueue q, ForkJoinTask<?> root) {
- ForkJoinTask<?>[] a; int m;
- if (q != null && (a = q.array) != null && (m = (a.length - 1)) >= 0 &&
- root != null && root.status >= 0) {
- for (;;) {
- int s, u; Object o; CountedCompleter<?> task = null;
- if ((s = q.top) - q.base > 0) {
- long j = ((m & (s - 1)) << ASHIFT) + ABASE;
- if ((o = U.getObject(a, j)) != null &&
- (o instanceof CountedCompleter)) {
- CountedCompleter<?> t = (CountedCompleter<?>)o, r = t;
- do {
- if (r == root) {
- if (U.compareAndSwapInt(q, QLOCK, 0, 1)) {
- if (q.array == a && q.top == s &&
- U.compareAndSwapObject(a, j, t, null)) {
- q.top = s - 1;
- task = t;
- }
- q.qlock = 0;
- }
- break;
- }
- } while ((r = r.completer) != null);
+ final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
+ WorkQueue joiner; int m;
+ WorkQueue[] ws = workQueues;
+ int j = ThreadLocalRandom.getProbe();
+ int s = 0;
+ if (ws != null && (m = ws.length - 1) >= 0 &&
+ (joiner = ws[j & m & SQMASK]) != null && task != null) {
+ int scans = m + m + 1;
+ long c = 0L; // for stability check
+ j |= 1; // poll odd queues
+ for (int k = scans; ; j += 2) {
+ WorkQueue q;
+ if ((s = task.status) < 0)
+ break;
+ else if (joiner.externalPopAndExecCC(task)) {
+ if (--maxTasks <= 0) {
+ s = task.status;
+ break;
}
+ k = scans;
}
- if (task != null)
- task.doExec();
- if (root.status < 0 ||
- (config != 0 &&
- ((u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0)))
+ else if ((s = task.status) < 0)
break;
- if (task == null) {
- helpSignal(root, q.poolIndex);
- if (root.status >= 0)
- helpComplete(root, SHARED_QUEUE);
- break;
+ else if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) {
+ if (--maxTasks <= 0) {
+ s = task.status;
+ break;
+ }
+ k = scans;
+ }
+ else if (--k < 0) {
+ if (c == (c = ctl))
+ break;
+ k = scans;
}
}
}
- }
-
- /**
- * Tries to help execute or signal availability of the given task
- * from submitter's queue in common pool.
- */
- static void externalHelpJoin(ForkJoinTask<?> t) {
- // Some hard-to-avoid overlap with tryExternalUnpush
- ForkJoinPool p; WorkQueue[] ws; WorkQueue q, w;
- ForkJoinTask<?>[] a; int m, s, n, z;
- if (t != null &&
- (z = ThreadLocalRandom.getProbe()) != 0 &&
- (p = common) != null &&
- (ws = p.workQueues) != null &&
- (m = ws.length - 1) >= 0 &&
- (q = ws[m & z & SQMASK]) != null &&
- (a = q.array) != null) {
- int am = a.length - 1;
- if ((s = q.top) != q.base) {
- long j = ((am & (s - 1)) << ASHIFT) + ABASE;
- if (U.getObject(a, j) == t &&
- U.compareAndSwapInt(q, QLOCK, 0, 1)) {
- if (q.array == a && q.top == s &&
- U.compareAndSwapObject(a, j, t, null)) {
- q.top = s - 1;
- q.qlock = 0;
- t.doExec();
- }
- else
- q.qlock = 0;
- }
- }
- if (t.status >= 0) {
- if (t instanceof CountedCompleter)
- p.externalHelpComplete(q, t);
- else
- p.helpSignal(t, q.poolIndex);
- }
- }
+ return s;
}
// Exported methods
@@ -2517,7 +2429,7 @@
this(checkParallelism(parallelism),
checkFactory(factory),
handler,
- asyncMode,
+ (asyncMode ? FIFO_QUEUE : LIFO_QUEUE),
"ForkJoinPool-" + nextPoolId() + "-worker-");
checkPermission();
}
@@ -2543,12 +2455,13 @@
private ForkJoinPool(int parallelism,
ForkJoinWorkerThreadFactory factory,
UncaughtExceptionHandler handler,
- boolean asyncMode,
+ int mode,
String workerNamePrefix) {
this.workerNamePrefix = workerNamePrefix;
this.factory = factory;
this.ueh = handler;
- this.config = parallelism | (asyncMode ? (FIFO_QUEUE << 16) : 0);
+ this.mode = (short)mode;
+ this.parallelism = (short)parallelism;
long np = (long)(-parallelism); // offset ctl counts
this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
}
@@ -2736,8 +2649,8 @@
* @return the targeted parallelism level of this pool
*/
public int getParallelism() {
- int par = (config & SMASK);
- return (par > 0) ? par : 1;
+ int par;
+ return ((par = parallelism) > 0) ? par : 1;
}
/**
@@ -2759,7 +2672,7 @@
* @return the number of worker threads
*/
public int getPoolSize() {
- return (config & SMASK) + (short)(ctl >>> TC_SHIFT);
+ return parallelism + (short)(ctl >>> TC_SHIFT);
}
/**
@@ -2769,7 +2682,7 @@
* @return {@code true} if this pool uses async mode
*/
public boolean getAsyncMode() {
- return (config >>> 16) == FIFO_QUEUE;
+ return mode == FIFO_QUEUE;
}
/**
@@ -2800,7 +2713,7 @@
* @return the number of active threads
*/
public int getActiveThreadCount() {
- int r = (config & SMASK) + (int)(ctl >> AC_SHIFT);
+ int r = parallelism + (int)(ctl >> AC_SHIFT);
return (r <= 0) ? 0 : r; // suppress momentarily negative values
}
@@ -2816,7 +2729,7 @@
* @return {@code true} if all threads are currently idle
*/
public boolean isQuiescent() {
- return (int)(ctl >> AC_SHIFT) + (config & SMASK) == 0;
+ return parallelism + (int)(ctl >> AC_SHIFT) <= 0;
}
/**
@@ -2979,7 +2892,7 @@
}
}
}
- int pc = (config & SMASK);
+ int pc = parallelism;
int tc = pc + (short)(c >>> TC_SHIFT);
int ac = pc + (int)(c >> AC_SHIFT);
if (ac < 0) // ignore transient negative
@@ -3052,7 +2965,7 @@
public boolean isTerminated() {
long c = ctl;
return ((c & STOP_BIT) != 0L &&
- (short)(c >>> TC_SHIFT) == -(config & SMASK));
+ (short)(c >>> TC_SHIFT) + parallelism <= 0);
}
/**
@@ -3071,7 +2984,7 @@
public boolean isTerminating() {
long c = ctl;
return ((c & STOP_BIT) != 0L &&
- (short)(c >>> TC_SHIFT) != -(config & SMASK));
+ (short)(c >>> TC_SHIFT) + parallelism > 0);
}
/**
@@ -3108,19 +3021,20 @@
long nanos = unit.toNanos(timeout);
if (isTerminated())
return true;
- long startTime = System.nanoTime();
- boolean terminated = false;
+ if (nanos <= 0L)
+ return false;
+ long deadline = System.nanoTime() + nanos;
synchronized (this) {
- for (long waitTime = nanos, millis = 0L;;) {
- if (terminated = isTerminated() ||
- waitTime <= 0L ||
- (millis = unit.toMillis(waitTime)) <= 0L)
- break;
- wait(millis);
- waitTime = nanos - (System.nanoTime() - startTime);
+ for (;;) {
+ if (isTerminated())
+ return true;
+ if (nanos <= 0L)
+ return false;
+ long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
+ wait(millis > 0L ? millis : 1L);
+ nanos = deadline - System.nanoTime();
}
}
- return terminated;
}
/**
@@ -3159,11 +3073,8 @@
ForkJoinTask<?> t; WorkQueue q; int b;
if ((q = ws[r++ & m]) != null && (b = q.base) - q.top < 0) {
found = true;
- if ((t = q.pollAt(b)) != null) {
- if (q.base - q.top < 0)
- signalWork(q);
+ if ((t = q.pollAt(b)) != null)
t.doExec();
- }
break;
}
}
@@ -3278,21 +3189,8 @@
Thread t = Thread.currentThread();
if (t instanceof ForkJoinWorkerThread) {
ForkJoinPool p = ((ForkJoinWorkerThread)t).pool;
- while (!blocker.isReleasable()) { // variant of helpSignal
- WorkQueue[] ws; WorkQueue q; int m, u;
- if ((ws = p.workQueues) != null && (m = ws.length - 1) >= 0) {
- for (int i = 0; i <= m; ++i) {
- if (blocker.isReleasable())
- return;
- if ((q = ws[i]) != null && q.base - q.top < 0) {
- p.signalWork(q);
- if ((u = (int)(p.ctl >>> 32)) >= 0 ||
- (u >> UAC_SHIFT) >= 0)
- break;
- }
- }
- }
- if (p.tryCompensate()) {
+ while (!blocker.isReleasable()) {
+ if (p.tryCompensate(p.ctl)) {
try {
do {} while (!blocker.isReleasable() &&
!blocker.block());
@@ -3330,6 +3228,7 @@
private static final long STEALCOUNT;
private static final long PLOCK;
private static final long INDEXSEED;
+ private static final long QBASE;
private static final long QLOCK;
static {
@@ -3349,6 +3248,8 @@
PARKBLOCKER = U.objectFieldOffset
(tk.getDeclaredField("parkBlocker"));
Class<?> wk = WorkQueue.class;
+ QBASE = U.objectFieldOffset
+ (wk.getDeclaredField("base"));
QLOCK = U.objectFieldOffset
(wk.getDeclaredField("qlock"));
Class<?> ak = ForkJoinTask[].class;
@@ -3368,7 +3269,7 @@
common = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<ForkJoinPool>() {
public ForkJoinPool run() { return makeCommonPool(); }});
- int par = common.config; // report 1 even if threads disabled
+ int par = common.parallelism; // report 1 even if threads disabled
commonParallelism = par > 0 ? par : 1;
}
@@ -3381,7 +3282,7 @@
ForkJoinWorkerThreadFactory factory
= defaultForkJoinWorkerThreadFactory;
UncaughtExceptionHandler handler = null;
- try { // ignore exceptions in accesing/parsing properties
+ try { // ignore exceptions in accessing/parsing properties
String pp = System.getProperty
("java.util.concurrent.ForkJoinPool.common.parallelism");
String fp = System.getProperty
@@ -3399,11 +3300,12 @@
} catch (Exception ignore) {
}
- if (parallelism < 0)
- parallelism = Runtime.getRuntime().availableProcessors();
+ if (parallelism < 0 && // default 1 less than #cores
+ (parallelism = Runtime.getRuntime().availableProcessors() - 1) < 0)
+ parallelism = 0;
if (parallelism > MAX_CAP)
parallelism = MAX_CAP;
- return new ForkJoinPool(parallelism, factory, handler, false,
+ return new ForkJoinPool(parallelism, factory, handler, LIFO_QUEUE,
"ForkJoinPool.commonPool-worker-");
}
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java Tue Jul 09 15:26:20 2013 -0700
@@ -165,7 +165,7 @@
* supports other methods and techniques (for example the use of
* {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that
* may be of use in constructing custom subclasses for problems that
- * are not statically structured as DAGs. To support such usages a
+ * are not statically structured as DAGs. To support such usages, a
* ForkJoinTask may be atomically <em>tagged</em> with a {@code short}
* value using {@link #setForkJoinTaskTag} or {@link
* #compareAndSetForkJoinTaskTag} and checked using {@link
@@ -314,25 +314,35 @@
*/
private int externalAwaitDone() {
int s;
- ForkJoinPool.externalHelpJoin(this);
- boolean interrupted = false;
- while ((s = status) >= 0) {
- if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
- synchronized (this) {
- if (status >= 0) {
- try {
- wait();
- } catch (InterruptedException ie) {
- interrupted = true;
+ ForkJoinPool cp = ForkJoinPool.common;
+ if ((s = status) >= 0) {
+ if (cp != null) {
+ if (this instanceof CountedCompleter)
+ s = cp.externalHelpComplete((CountedCompleter<?>)this, Integer.MAX_VALUE);
+ else if (cp.tryExternalUnpush(this))
+ s = doExec();
+ }
+ if (s >= 0 && (s = status) >= 0) {
+ boolean interrupted = false;
+ do {
+ if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+ synchronized (this) {
+ if (status >= 0) {
+ try {
+ wait();
+ } catch (InterruptedException ie) {
+ interrupted = true;
+ }
+ }
+ else
+ notifyAll();
}
}
- else
- notifyAll();
- }
+ } while ((s = status) >= 0);
+ if (interrupted)
+ Thread.currentThread().interrupt();
}
}
- if (interrupted)
- Thread.currentThread().interrupt();
return s;
}
@@ -341,9 +351,15 @@
*/
private int externalInterruptibleAwaitDone() throws InterruptedException {
int s;
+ ForkJoinPool cp = ForkJoinPool.common;
if (Thread.interrupted())
throw new InterruptedException();
- ForkJoinPool.externalHelpJoin(this);
+ if ((s = status) >= 0 && cp != null) {
+ if (this instanceof CountedCompleter)
+ cp.externalHelpComplete((CountedCompleter<?>)this, Integer.MAX_VALUE);
+ else if (cp.tryExternalUnpush(this))
+ doExec();
+ }
while ((s = status) >= 0) {
if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
synchronized (this) {
@@ -357,7 +373,6 @@
return s;
}
-
/**
* Implementation for join, get, quietlyJoin. Directly handles
* only cases of already-completed, external wait, and
@@ -629,14 +644,9 @@
/**
* A version of "sneaky throw" to relay exceptions
*/
- static void rethrow(final Throwable ex) {
- if (ex != null) {
- if (ex instanceof Error)
- throw (Error)ex;
- if (ex instanceof RuntimeException)
- throw (RuntimeException)ex;
+ static void rethrow(Throwable ex) {
+ if (ex != null)
ForkJoinTask.<RuntimeException>uncheckedThrow(ex);
- }
}
/**
@@ -646,8 +656,7 @@
*/
@SuppressWarnings("unchecked") static <T extends Throwable>
void uncheckedThrow(Throwable t) throws T {
- if (t != null)
- throw (T)t; // rely on vacuous cast
+ throw (T)t; // rely on vacuous cast
}
/**
@@ -1010,6 +1019,7 @@
// Messy in part because we measure in nanosecs, but wait in millisecs
int s; long ms;
long ns = unit.toNanos(timeout);
+ ForkJoinPool cp;
if ((s = status) >= 0 && ns > 0L) {
long deadline = System.nanoTime() + ns;
ForkJoinPool p = null;
@@ -1021,8 +1031,12 @@
w = wt.workQueue;
p.helpJoinOnce(w, this); // no retries on failure
}
- else
- ForkJoinPool.externalHelpJoin(this);
+ else if ((cp = ForkJoinPool.common) != null) {
+ if (this instanceof CountedCompleter)
+ cp.externalHelpComplete((CountedCompleter<?>)this, Integer.MAX_VALUE);
+ else if (cp.tryExternalUnpush(this))
+ doExec();
+ }
boolean canBlock = false;
boolean interrupted = false;
try {
@@ -1030,7 +1044,7 @@
if (w != null && w.qlock < 0)
cancelIgnoringExceptions(this);
else if (!canBlock) {
- if (p == null || p.tryCompensate())
+ if (p == null || p.tryCompensate(p.ctl))
canBlock = true;
}
else {
@@ -1171,7 +1185,7 @@
Thread t;
return (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
((ForkJoinWorkerThread)t).workQueue.tryUnpush(this) :
- ForkJoinPool.tryExternalUnpush(this));
+ ForkJoinPool.common.tryExternalUnpush(this));
}
/**
@@ -1340,7 +1354,7 @@
*
* @param e the expected tag value
* @param tag the new tag value
- * @return true if successful; i.e., the current value was
+ * @return {@code true} if successful; i.e., the current value was
* equal to e and is now tag.
* @since 1.8
*/
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Tue Jul 09 15:26:20 2013 -0700
@@ -43,8 +43,8 @@
* scheduling or execution. However, you can override initialization
* and termination methods surrounding the main task processing loop.
* If you do create such a subclass, you will also need to supply a
- * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to use it
- * in a {@code ForkJoinPool}.
+ * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to
+ * {@linkplain ForkJoinPool#ForkJoinPool use it} in a {@code ForkJoinPool}.
*
* @since 1.7
* @author Doug Lea
@@ -89,16 +89,17 @@
}
/**
- * Returns the index number of this thread in its pool. The
- * returned value ranges from zero to the maximum number of
- * threads (minus one) that have ever been created in the pool.
- * This method may be useful for applications that track status or
- * collect results per-worker rather than per-task.
+ * Returns the unique index number of this thread in its pool.
+ * The returned value ranges from zero to the maximum number of
+ * threads (minus one) that may exist in the pool, and does not
+ * change during the lifetime of the thread. This method may be
+ * useful for applications that track status or collect results
+ * per-worker-thread rather than per-task.
*
* @return the index number
*/
public int getPoolIndex() {
- return workQueue.poolIndex;
+ return workQueue.poolIndex >>> 1; // ignore odd/even tag bit
}
/**
--- a/jdk/src/share/classes/java/util/concurrent/Future.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/Future.java Tue Jul 09 15:26:20 2013 -0700
@@ -36,19 +36,19 @@
package java.util.concurrent;
/**
- * A <tt>Future</tt> represents the result of an asynchronous
+ * A {@code Future} represents the result of an asynchronous
* computation. Methods are provided to check if the computation is
* complete, to wait for its completion, and to retrieve the result of
* the computation. The result can only be retrieved using method
- * <tt>get</tt> when the computation has completed, blocking if
+ * {@code get} when the computation has completed, blocking if
* necessary until it is ready. Cancellation is performed by the
- * <tt>cancel</tt> method. Additional methods are provided to
+ * {@code cancel} method. Additional methods are provided to
* determine if the task completed normally or was cancelled. Once a
* computation has completed, the computation cannot be cancelled.
- * If you would like to use a <tt>Future</tt> for the sake
+ * If you would like to use a {@code Future} for the sake
* of cancellability but not provide a usable result, you can
* declare types of the form {@code Future<?>} and
- * return <tt>null</tt> as a result of the underlying task.
+ * return {@code null} as a result of the underlying task.
*
* <p>
* <b>Sample Usage</b> (Note that the following classes are all
@@ -72,9 +72,9 @@
* }
* }}</pre>
*
- * The {@link FutureTask} class is an implementation of <tt>Future</tt> that
- * implements <tt>Runnable</tt>, and so may be executed by an <tt>Executor</tt>.
- * For example, the above construction with <tt>submit</tt> could be replaced by:
+ * The {@link FutureTask} class is an implementation of {@code Future} that
+ * implements {@code Runnable}, and so may be executed by an {@code Executor}.
+ * For example, the above construction with {@code submit} could be replaced by:
* <pre> {@code
* FutureTask<String> future =
* new FutureTask<String>(new Callable<String>() {
@@ -91,7 +91,7 @@
* @see Executor
* @since 1.5
* @author Doug Lea
- * @param <V> The result type returned by this Future's <tt>get</tt> method
+ * @param <V> The result type returned by this Future's {@code get} method
*/
public interface Future<V> {
@@ -99,41 +99,41 @@
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
- * and this task has not started when <tt>cancel</tt> is called,
+ * and this task has not started when {@code cancel} is called,
* this task should never run. If the task has already started,
- * then the <tt>mayInterruptIfRunning</tt> parameter determines
+ * then the {@code mayInterruptIfRunning} parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
- * always return <tt>true</tt>. Subsequent calls to {@link #isCancelled}
- * will always return <tt>true</tt> if this method returned <tt>true</tt>.
+ * always return {@code true}. Subsequent calls to {@link #isCancelled}
+ * will always return {@code true} if this method returned {@code true}.
*
- * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
+ * @param mayInterruptIfRunning {@code true} if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
- * @return <tt>false</tt> if the task could not be cancelled,
+ * @return {@code false} if the task could not be cancelled,
* typically because it has already completed normally;
- * <tt>true</tt> otherwise
+ * {@code true} otherwise
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
- * Returns <tt>true</tt> if this task was cancelled before it completed
+ * Returns {@code true} if this task was cancelled before it completed
* normally.
*
- * @return <tt>true</tt> if this task was cancelled before it completed
+ * @return {@code true} if this task was cancelled before it completed
*/
boolean isCancelled();
/**
- * Returns <tt>true</tt> if this task completed.
+ * Returns {@code true} if this task completed.
*
* Completion may be due to normal termination, an exception, or
* cancellation -- in all of these cases, this method will return
- * <tt>true</tt>.
+ * {@code true}.
*
- * @return <tt>true</tt> if this task completed
+ * @return {@code true} if this task completed
*/
boolean isDone();
--- a/jdk/src/share/classes/java/util/concurrent/FutureTask.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/FutureTask.java Tue Jul 09 15:26:20 2013 -0700
@@ -162,19 +162,23 @@
}
public boolean cancel(boolean mayInterruptIfRunning) {
- if (state != NEW)
+ if (!(state == NEW &&
+ UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
+ mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
- if (mayInterruptIfRunning) {
- if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING))
- return false;
- Thread t = runner;
- if (t != null)
- t.interrupt();
- UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state
+ try { // in case call to interrupt throws exception
+ if (mayInterruptIfRunning) {
+ try {
+ Thread t = runner;
+ if (t != null)
+ t.interrupt();
+ } finally { // final state
+ UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
+ }
+ }
+ } finally {
+ finishCompletion();
}
- else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED))
- return false;
- finishCompletion();
return true;
}
@@ -288,7 +292,7 @@
* designed for use with tasks that intrinsically execute more
* than once.
*
- * @return true if successfully run and reset
+ * @return {@code true} if successfully run and reset
*/
protected boolean runAndReset() {
if (state != NEW ||
--- a/jdk/src/share/classes/java/util/concurrent/RecursiveAction.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/RecursiveAction.java Tue Jul 09 15:26:20 2013 -0700
@@ -63,7 +63,7 @@
* }
* }
* // implementation details follow:
- * final static int THRESHOLD = 1000;
+ * static final int THRESHOLD = 1000;
* void sortSequentially(int lo, int hi) {
* Arrays.sort(array, lo, hi);
* }
@@ -140,21 +140,21 @@
* int h = hi;
* Applyer right = null;
* while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
- * int mid = (l + h) >>> 1;
- * right = new Applyer(array, mid, h, right);
- * right.fork();
- * h = mid;
+ * int mid = (l + h) >>> 1;
+ * right = new Applyer(array, mid, h, right);
+ * right.fork();
+ * h = mid;
* }
* double sum = atLeaf(l, h);
* while (right != null) {
- * if (right.tryUnfork()) // directly calculate if not stolen
- * sum += right.atLeaf(right.lo, right.hi);
+ * if (right.tryUnfork()) // directly calculate if not stolen
+ * sum += right.atLeaf(right.lo, right.hi);
* else {
- * right.join();
- * sum += right.result;
- * }
- * right = right.next;
- * }
+ * right.join();
+ * sum += right.result;
+ * }
+ * right = right.next;
+ * }
* result = sum;
* }
* }}</pre>
--- a/jdk/src/share/classes/java/util/concurrent/RecursiveTask.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/RecursiveTask.java Tue Jul 09 15:26:20 2013 -0700
@@ -46,7 +46,7 @@
* Fibonacci(int n) { this.n = n; }
* Integer compute() {
* if (n <= 1)
- * return n;
+ * return n;
* Fibonacci f1 = new Fibonacci(n - 1);
* f1.fork();
* Fibonacci f2 = new Fibonacci(n - 2);
@@ -75,6 +75,7 @@
/**
* The main computation performed by this task.
+ * @return the result of the computation
*/
protected abstract V compute();
--- a/jdk/src/share/classes/java/util/concurrent/RejectedExecutionException.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/RejectedExecutionException.java Tue Jul 09 15:26:20 2013 -0700
@@ -46,14 +46,14 @@
private static final long serialVersionUID = -375805702767069545L;
/**
- * Constructs a <tt>RejectedExecutionException</tt> with no detail message.
+ * Constructs a {@code RejectedExecutionException} with no detail message.
* The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause(Throwable) initCause}.
*/
public RejectedExecutionException() { }
/**
- * Constructs a <tt>RejectedExecutionException</tt> with the
+ * Constructs a {@code RejectedExecutionException} with the
* specified detail message. The cause is not initialized, and may
* subsequently be initialized by a call to {@link
* #initCause(Throwable) initCause}.
@@ -65,7 +65,7 @@
}
/**
- * Constructs a <tt>RejectedExecutionException</tt> with the
+ * Constructs a {@code RejectedExecutionException} with the
* specified detail message and cause.
*
* @param message the detail message
@@ -77,10 +77,10 @@
}
/**
- * Constructs a <tt>RejectedExecutionException</tt> with the
+ * Constructs a {@code RejectedExecutionException} with the
* specified cause. The detail message is set to {@code (cause ==
* null ? null : cause.toString())} (which typically contains
- * the class and detail message of <tt>cause</tt>).
+ * the class and detail message of {@code cause}).
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method)
--- a/jdk/src/share/classes/java/util/concurrent/RunnableFuture.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/RunnableFuture.java Tue Jul 09 15:26:20 2013 -0700
@@ -37,13 +37,13 @@
/**
* A {@link Future} that is {@link Runnable}. Successful execution of
- * the <tt>run</tt> method causes completion of the <tt>Future</tt>
+ * the {@code run} method causes completion of the {@code Future}
* and allows access to its results.
* @see FutureTask
* @see Executor
* @since 1.6
* @author Doug Lea
- * @param <V> The result type returned by this Future's <tt>get</tt> method
+ * @param <V> The result type returned by this Future's {@code get} method
*/
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
--- a/jdk/src/share/classes/java/util/concurrent/RunnableScheduledFuture.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/RunnableScheduledFuture.java Tue Jul 09 15:26:20 2013 -0700
@@ -37,22 +37,22 @@
/**
* A {@link ScheduledFuture} that is {@link Runnable}. Successful
- * execution of the <tt>run</tt> method causes completion of the
- * <tt>Future</tt> and allows access to its results.
+ * execution of the {@code run} method causes completion of the
+ * {@code Future} and allows access to its results.
* @see FutureTask
* @see Executor
* @since 1.6
* @author Doug Lea
- * @param <V> The result type returned by this Future's <tt>get</tt> method
+ * @param <V> The result type returned by this Future's {@code get} method
*/
public interface RunnableScheduledFuture<V> extends RunnableFuture<V>, ScheduledFuture<V> {
/**
- * Returns true if this is a periodic task. A periodic task may
+ * Returns {@code true} if this task is periodic. A periodic task may
* re-run according to some schedule. A non-periodic task can be
* run only once.
*
- * @return true if this task is periodic
+ * @return {@code true} if this task is periodic
*/
boolean isPeriodic();
}
--- a/jdk/src/share/classes/java/util/concurrent/ScheduledExecutorService.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ScheduledExecutorService.java Tue Jul 09 15:26:20 2013 -0700
@@ -39,30 +39,30 @@
* An {@link ExecutorService} that can schedule commands to run after a given
* delay, or to execute periodically.
*
- * <p> The <tt>schedule</tt> methods create tasks with various delays
+ * <p>The {@code schedule} methods create tasks with various delays
* and return a task object that can be used to cancel or check
- * execution. The <tt>scheduleAtFixedRate</tt> and
- * <tt>scheduleWithFixedDelay</tt> methods create and execute tasks
+ * execution. The {@code scheduleAtFixedRate} and
+ * {@code scheduleWithFixedDelay} methods create and execute tasks
* that run periodically until cancelled.
*
- * <p> Commands submitted using the {@link Executor#execute} and
- * {@link ExecutorService} <tt>submit</tt> methods are scheduled with
- * a requested delay of zero. Zero and negative delays (but not
- * periods) are also allowed in <tt>schedule</tt> methods, and are
+ * <p>Commands submitted using the {@link Executor#execute(Runnable)}
+ * and {@link ExecutorService} {@code submit} methods are scheduled
+ * with a requested delay of zero. Zero and negative delays (but not
+ * periods) are also allowed in {@code schedule} methods, and are
* treated as requests for immediate execution.
*
- * <p>All <tt>schedule</tt> methods accept <em>relative</em> delays and
+ * <p>All {@code schedule} methods accept <em>relative</em> delays and
* periods as arguments, not absolute times or dates. It is a simple
* matter to transform an absolute time represented as a {@link
* java.util.Date} to the required form. For example, to schedule at
- * a certain future <tt>date</tt>, you can use: <tt>schedule(task,
+ * a certain future {@code date}, you can use: {@code schedule(task,
* date.getTime() - System.currentTimeMillis(),
- * TimeUnit.MILLISECONDS)</tt>. Beware however that expiration of a
- * relative delay need not coincide with the current <tt>Date</tt> at
+ * TimeUnit.MILLISECONDS)}. Beware however that expiration of a
+ * relative delay need not coincide with the current {@code Date} at
* which the task is enabled due to network time synchronization
* protocols, clock drift, or other factors.
*
- * The {@link Executors} class provides convenient factory methods for
+ * <p>The {@link Executors} class provides convenient factory methods for
* the ScheduledExecutorService implementations provided in this package.
*
* <h3>Usage Example</h3>
@@ -101,8 +101,8 @@
* @param delay the time from now to delay execution
* @param unit the time unit of the delay parameter
* @return a ScheduledFuture representing pending completion of
- * the task and whose <tt>get()</tt> method will return
- * <tt>null</tt> upon completion
+ * the task and whose {@code get()} method will return
+ * {@code null} upon completion
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* @throws NullPointerException if command is null
@@ -129,8 +129,8 @@
* Creates and executes a periodic action that becomes enabled first
* after the given initial delay, and subsequently with the given
* period; that is executions will commence after
- * <tt>initialDelay</tt> then <tt>initialDelay+period</tt>, then
- * <tt>initialDelay + 2 * period</tt>, and so on.
+ * {@code initialDelay} then {@code initialDelay+period}, then
+ * {@code initialDelay + 2 * period}, and so on.
* If any execution of the task
* encounters an exception, subsequent executions are suppressed.
* Otherwise, the task will only terminate via cancellation or
@@ -143,7 +143,7 @@
* @param period the period between successive executions
* @param unit the time unit of the initialDelay and period parameters
* @return a ScheduledFuture representing pending completion of
- * the task, and whose <tt>get()</tt> method will throw an
+ * the task, and whose {@code get()} method will throw an
* exception upon cancellation
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
@@ -170,7 +170,7 @@
* execution and the commencement of the next
* @param unit the time unit of the initialDelay and delay parameters
* @return a ScheduledFuture representing pending completion of
- * the task, and whose <tt>get()</tt> method will throw an
+ * the task, and whose {@code get()} method will throw an
* exception upon cancellation
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
--- a/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Tue Jul 09 15:26:20 2013 -0700
@@ -81,7 +81,7 @@
* without threads to handle tasks once they become eligible to run.
*
* <p><b>Extension notes:</b> This class overrides the
- * {@link ThreadPoolExecutor#execute execute} and
+ * {@link ThreadPoolExecutor#execute(Runnable) execute} and
* {@link AbstractExecutorService#submit(Runnable) submit}
* methods to generate internal {@link ScheduledFuture} objects to
* control per-task delays and scheduling. To preserve
@@ -256,9 +256,9 @@
}
/**
- * Returns true if this is a periodic (not a one-shot) action.
+ * Returns {@code true} if this is a periodic (not a one-shot) action.
*
- * @return true if periodic
+ * @return {@code true} if periodic
*/
public boolean isPeriodic() {
return period != 0;
@@ -315,7 +315,7 @@
* is shut down, rejects the task. Otherwise adds task to queue
* and starts a thread, if necessary, to run it. (We cannot
* prestart the thread to run the task because the task (probably)
- * shouldn't be run yet,) If the pool is shut down while the task
+ * shouldn't be run yet.) If the pool is shut down while the task
* is being added, cancel and remove it if required by state and
* run-after-shutdown parameters.
*
@@ -654,7 +654,7 @@
* {@code false} when already shutdown.
* This value is by default {@code false}.
*
- * @param value if {@code true}, continue after shutdown, else don't.
+ * @param value if {@code true}, continue after shutdown, else don't
* @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
*/
public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
@@ -686,7 +686,7 @@
* {@code false} when already shutdown.
* This value is by default {@code true}.
*
- * @param value if {@code true}, execute after shutdown, else don't.
+ * @param value if {@code true}, execute after shutdown, else don't
* @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
*/
public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
@@ -1081,7 +1081,8 @@
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return finishPoll(first);
- else if (leader != null)
+ first = null; // don't retain ref while waiting
+ if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
@@ -1121,6 +1122,7 @@
return finishPoll(first);
if (nanos <= 0)
return null;
+ first = null; // don't retain ref while waiting
if (nanos < delay || leader != null)
nanos = available.awaitNanos(nanos);
else {
--- a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Tue Jul 09 15:26:20 2013 -0700
@@ -75,22 +75,23 @@
* corePoolSize (see {@link #getCorePoolSize}) and
* maximumPoolSize (see {@link #getMaximumPoolSize}).
*
- * When a new task is submitted in method {@link #execute}, and fewer
- * than corePoolSize threads are running, a new thread is created to
- * handle the request, even if other worker threads are idle. If
- * there are more than corePoolSize but less than maximumPoolSize
- * threads running, a new thread will be created only if the queue is
- * full. By setting corePoolSize and maximumPoolSize the same, you
- * create a fixed-size thread pool. By setting maximumPoolSize to an
- * essentially unbounded value such as {@code Integer.MAX_VALUE}, you
- * allow the pool to accommodate an arbitrary number of concurrent
- * tasks. Most typically, core and maximum pool sizes are set only
- * upon construction, but they may also be changed dynamically using
- * {@link #setCorePoolSize} and {@link #setMaximumPoolSize}. </dd>
+ * When a new task is submitted in method {@link #execute(Runnable)},
+ * and fewer than corePoolSize threads are running, a new thread is
+ * created to handle the request, even if other worker threads are
+ * idle. If there are more than corePoolSize but less than
+ * maximumPoolSize threads running, a new thread will be created only
+ * if the queue is full. By setting corePoolSize and maximumPoolSize
+ * the same, you create a fixed-size thread pool. By setting
+ * maximumPoolSize to an essentially unbounded value such as {@code
+ * Integer.MAX_VALUE}, you allow the pool to accommodate an arbitrary
+ * number of concurrent tasks. Most typically, core and maximum pool
+ * sizes are set only upon construction, but they may also be changed
+ * dynamically using {@link #setCorePoolSize} and {@link
+ * #setMaximumPoolSize}. </dd>
*
* <dt>On-demand construction</dt>
*
- * <dd> By default, even core threads are initially created and
+ * <dd>By default, even core threads are initially created and
* started only when new tasks arrive, but this can be overridden
* dynamically using method {@link #prestartCoreThread} or {@link
* #prestartAllCoreThreads}. You probably want to prestart threads if
@@ -117,17 +118,17 @@
*
* <dd>If the pool currently has more than corePoolSize threads,
* excess threads will be terminated if they have been idle for more
- * than the keepAliveTime (see {@link #getKeepAliveTime}). This
- * provides a means of reducing resource consumption when the pool is
- * not being actively used. If the pool becomes more active later, new
- * threads will be constructed. This parameter can also be changed
- * dynamically using method {@link #setKeepAliveTime}. Using a value
- * of {@code Long.MAX_VALUE} {@link TimeUnit#NANOSECONDS} effectively
- * disables idle threads from ever terminating prior to shut down. By
- * default, the keep-alive policy applies only when there are more
- * than corePoolSizeThreads. But method {@link
- * #allowCoreThreadTimeOut(boolean)} can be used to apply this
- * time-out policy to core threads as well, so long as the
+ * than the keepAliveTime (see {@link #getKeepAliveTime(TimeUnit)}).
+ * This provides a means of reducing resource consumption when the
+ * pool is not being actively used. If the pool becomes more active
+ * later, new threads will be constructed. This parameter can also be
+ * changed dynamically using method {@link #setKeepAliveTime(long,
+ * TimeUnit)}. Using a value of {@code Long.MAX_VALUE} {@link
+ * TimeUnit#NANOSECONDS} effectively disables idle threads from ever
+ * terminating prior to shut down. By default, the keep-alive policy
+ * applies only when there are more than corePoolSize threads. But
+ * method {@link #allowCoreThreadTimeOut(boolean)} can be used to
+ * apply this time-out policy to core threads as well, so long as the
* keepAliveTime value is non-zero. </dd>
*
* <dt>Queuing</dt>
@@ -197,14 +198,14 @@
*
* <dt>Rejected tasks</dt>
*
- * <dd> New tasks submitted in method {@link #execute} will be
- * <em>rejected</em> when the Executor has been shut down, and also
- * when the Executor uses finite bounds for both maximum threads and
- * work queue capacity, and is saturated. In either case, the {@code
- * execute} method invokes the {@link
- * RejectedExecutionHandler#rejectedExecution} method of its {@link
- * RejectedExecutionHandler}. Four predefined handler policies are
- * provided:
+ * <dd>New tasks submitted in method {@link #execute(Runnable)} will be
+ * <em>rejected</em> when the Executor has been shut down, and also when
+ * the Executor uses finite bounds for both maximum threads and work queue
+ * capacity, and is saturated. In either case, the {@code execute} method
+ * invokes the {@link
+ * RejectedExecutionHandler#rejectedExecution(Runnable, ThreadPoolExecutor)}
+ * method of its {@link RejectedExecutionHandler}. Four predefined handler
+ * policies are provided:
*
* <ol>
*
@@ -234,30 +235,31 @@
*
* <dt>Hook methods</dt>
*
- * <dd>This class provides {@code protected} overridable {@link
- * #beforeExecute} and {@link #afterExecute} methods that are called
+ * <dd>This class provides {@code protected} overridable
+ * {@link #beforeExecute(Thread, Runnable)} and
+ * {@link #afterExecute(Runnable, Throwable)} methods that are called
* before and after execution of each task. These can be used to
* manipulate the execution environment; for example, reinitializing
- * ThreadLocals, gathering statistics, or adding log
- * entries. Additionally, method {@link #terminated} can be overridden
- * to perform any special processing that needs to be done once the
- * Executor has fully terminated.
+ * ThreadLocals, gathering statistics, or adding log entries.
+ * Additionally, method {@link #terminated} can be overridden to perform
+ * any special processing that needs to be done once the Executor has
+ * fully terminated.
*
* <p>If hook or callback methods throw exceptions, internal worker
* threads may in turn fail and abruptly terminate.</dd>
*
* <dt>Queue maintenance</dt>
*
- * <dd> Method {@link #getQueue} allows access to the work queue for
- * purposes of monitoring and debugging. Use of this method for any
- * other purpose is strongly discouraged. Two supplied methods,
- * {@link #remove} and {@link #purge} are available to assist in
- * storage reclamation when large numbers of queued tasks become
- * cancelled.</dd>
+ * <dd>Method {@link #getQueue()} allows access to the work queue
+ * for purposes of monitoring and debugging. Use of this method for
+ * any other purpose is strongly discouraged. Two supplied methods,
+ * {@link #remove(Runnable)} and {@link #purge} are available to
+ * assist in storage reclamation when large numbers of queued tasks
+ * become cancelled.</dd>
*
* <dt>Finalization</dt>
*
- * <dd> A pool that is no longer referenced in a program <em>AND</em>
+ * <dd>A pool that is no longer referenced in a program <em>AND</em>
* has no remaining threads will be {@code shutdown} automatically. If
* you would like to ensure that unreferenced pools are reclaimed even
* if users forget to call {@link #shutdown}, then you must arrange
@@ -267,7 +269,7 @@
*
* </dl>
*
- * <p> <b>Extension example</b>. Most extensions of this class
+ * <p><b>Extension example</b>. Most extensions of this class
* override one or more of the protected hook methods. For example,
* here is a subclass that adds a simple pause/resume feature:
*
@@ -336,7 +338,7 @@
* bookkeeping before terminating. The user-visible pool size is
* reported as the current size of the workers set.
*
- * The runState provides the main lifecyle control, taking on values:
+ * The runState provides the main lifecycle control, taking on values:
*
* RUNNING: Accept new tasks and process queued tasks
* SHUTDOWN: Don't accept new tasks, but process queued tasks
@@ -406,14 +408,14 @@
}
/**
- * Attempt to CAS-increment the workerCount field of ctl.
+ * Attempts to CAS-increment the workerCount field of ctl.
*/
private boolean compareAndIncrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect + 1);
}
/**
- * Attempt to CAS-decrement the workerCount field of ctl.
+ * Attempts to CAS-decrement the workerCount field of ctl.
*/
private boolean compareAndDecrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect - 1);
@@ -498,7 +500,7 @@
* We go further and preserve pool invariants even in the face of
* errors such as OutOfMemoryError, that might be thrown while
* trying to create threads. Such errors are rather common due to
- * the need to allocate a native stack in Thread#start, and users
+ * the need to allocate a native stack in Thread.start, and users
* will want to perform clean pool shutdown to clean up. There
* will likely be enough memory available for the cleanup code to
* complete without encountering yet another OutOfMemoryError.
@@ -848,7 +850,7 @@
*/
private List<Runnable> drainQueue() {
BlockingQueue<Runnable> q = workQueue;
- List<Runnable> taskList = new ArrayList<Runnable>();
+ ArrayList<Runnable> taskList = new ArrayList<Runnable>();
q.drainTo(taskList);
if (!q.isEmpty()) {
for (Runnable r : q.toArray(new Runnable[0])) {
@@ -873,7 +875,7 @@
* factory fails to create a thread when asked. If the thread
* creation fails, either due to the thread factory returning
* null, or due to an exception (typically OutOfMemoryError in
- * Thread#start), we roll back cleanly.
+ * Thread.start()), we roll back cleanly.
*
* @param firstTask the task the new thread should run first (or
* null if none). Workers are created with an initial first task
@@ -920,17 +922,16 @@
boolean workerAdded = false;
Worker w = null;
try {
- final ReentrantLock mainLock = this.mainLock;
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
+ final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
- int c = ctl.get();
- int rs = runStateOf(c);
+ int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
@@ -1029,7 +1030,8 @@
* 4. This worker timed out waiting for a task, and timed-out
* workers are subject to termination (that is,
* {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
- * both before and after the timed wait.
+ * both before and after the timed wait, and if the queue is
+ * non-empty, this worker is not the last thread in the pool.
*
* @return task, or null if the worker must exit, in which case
* workerCount is decremented
@@ -1037,7 +1039,6 @@
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
- retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
@@ -1048,20 +1049,16 @@
return null;
}
- boolean timed; // Are workers subject to culling?
+ int wc = workerCountOf(c);
- for (;;) {
- int wc = workerCountOf(c);
- timed = allowCoreThreadTimeOut || wc > corePoolSize;
+ // Are workers subject to culling?
+ boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
- if (wc <= maximumPoolSize && ! (timedOut && timed))
- break;
+ if ((wc > maximumPoolSize || (timed && timedOut))
+ && (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
- c = ctl.get(); // Re-read ctl
- if (runStateOf(c) != rs)
- continue retry;
- // else CAS failed due to workerCount change; retry inner loop
+ continue;
}
try {
@@ -1090,9 +1087,9 @@
* usually leads processWorkerExit to replace this thread.
*
* 2. Before running any task, the lock is acquired to prevent
- * other pool interrupts while the task is executing, and
- * clearInterruptsForTaskRun called to ensure that unless pool is
- * stopping, this thread does not have its interrupt set.
+ * other pool interrupts while the task is executing, and then we
+ * ensure that unless pool is stopping, this thread does not have
+ * its interrupt set.
*
* 3. Each task run is preceded by a call to beforeExecute, which
* might throw an exception, in which case we cause thread to die
@@ -1100,12 +1097,12 @@
* the task.
*
* 4. Assuming beforeExecute completes normally, we run the task,
- * gathering any of its thrown exceptions to send to
- * afterExecute. We separately handle RuntimeException, Error
- * (both of which the specs guarantee that we trap) and arbitrary
- * Throwables. Because we cannot rethrow Throwables within
- * Runnable.run, we wrap them within Errors on the way out (to the
- * thread's UncaughtExceptionHandler). Any thrown exception also
+ * gathering any of its thrown exceptions to send to afterExecute.
+ * We separately handle RuntimeException, Error (both of which the
+ * specs guarantee that we trap) and arbitrary Throwables.
+ * Because we cannot rethrow Throwables within Runnable.run, we
+ * wrap them within Errors on the way out (to the thread's
+ * UncaughtExceptionHandler). Any thrown exception also
* conservatively causes thread to die.
*
* 5. After task.run completes, we call afterExecute, which may
@@ -1443,7 +1440,7 @@
* ignored or suppressed interruption, causing this executor not
* to properly terminate.
*
- * @return true if terminating but not yet terminated
+ * @return {@code true} if terminating but not yet terminated
*/
public boolean isTerminating() {
int c = ctl.get();
@@ -1497,7 +1494,7 @@
* Returns the thread factory used to create new threads.
*
* @return the current thread factory
- * @see #setThreadFactory
+ * @see #setThreadFactory(ThreadFactory)
*/
public ThreadFactory getThreadFactory() {
return threadFactory;
@@ -1520,7 +1517,7 @@
* Returns the current handler for unexecutable tasks.
*
* @return the current handler
- * @see #setRejectedExecutionHandler
+ * @see #setRejectedExecutionHandler(RejectedExecutionHandler)
*/
public RejectedExecutionHandler getRejectedExecutionHandler() {
return handler;
@@ -1692,7 +1689,7 @@
* @param unit the time unit of the {@code time} argument
* @throws IllegalArgumentException if {@code time} less than zero or
* if {@code time} is zero and {@code allowsCoreThreadTimeOut}
- * @see #getKeepAliveTime
+ * @see #getKeepAliveTime(TimeUnit)
*/
public void setKeepAliveTime(long time, TimeUnit unit) {
if (time < 0)
@@ -1713,7 +1710,7 @@
*
* @param unit the desired time unit of the result
* @return the time limit
- * @see #setKeepAliveTime
+ * @see #setKeepAliveTime(long, TimeUnit)
*/
public long getKeepAliveTime(TimeUnit unit) {
return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
@@ -1738,7 +1735,7 @@
* present, thus causing it not to be run if it has not already
* started.
*
- * <p> This method may be useful as one part of a cancellation
+ * <p>This method may be useful as one part of a cancellation
* scheme. It may fail to remove tasks that have been converted
* into other forms before being placed on the internal queue. For
* example, a task entered using {@code submit} might be
@@ -1747,7 +1744,7 @@
* remove those Futures that have been cancelled.
*
* @param task the task to remove
- * @return true if the task was removed
+ * @return {@code true} if the task was removed
*/
public boolean remove(Runnable task) {
boolean removed = workQueue.remove(task);
@@ -2042,7 +2039,7 @@
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
- * @throws RejectedExecutionException always.
+ * @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
@@ -2099,4 +2096,3 @@
}
}
}
-
--- a/jdk/src/share/classes/java/util/regex/MatchResult.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/regex/MatchResult.java Tue Jul 09 15:26:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, 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
@@ -77,7 +77,7 @@
public int start(int group);
/**
- * Returns the offset after the last character matched. </p>
+ * Returns the offset after the last character matched.
*
* @return The offset after the last character matched
*
--- a/jdk/src/share/classes/java/util/regex/Matcher.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/regex/Matcher.java Tue Jul 09 15:26:20 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, 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,8 +28,8 @@
import java.util.Objects;
/**
- * An engine that performs match operations on a {@link java.lang.CharSequence
- * </code>character sequence<code>} by interpreting a {@link Pattern}.
+ * An engine that performs match operations on a {@linkplain java.lang.CharSequence
+ * character sequence} by interpreting a {@link Pattern}.
*
* <p> A matcher is created from a pattern by invoking the pattern's {@link
* Pattern#matcher matcher} method. Once created, a matcher can be used to
@@ -330,7 +330,7 @@
}
/**
- * Returns the start index of the previous match. </p>
+ * Returns the start index of the previous match.
*
* @return The index of the first character matched
*
@@ -402,7 +402,7 @@
}
/**
- * Returns the offset after the last character matched. </p>
+ * Returns the offset after the last character matched.
*
* @return The offset after the last character matched
*
@@ -647,6 +647,7 @@
* invocations of the {@link #find()} method will start at the first
* character not matched by this match. </p>
*
+ * @param start the index to start searching for a match
* @throws IndexOutOfBoundsException
* If start is less than zero or if start is greater than the
* length of the input sequence.
@@ -736,8 +737,8 @@
* captured during the previous match: Each occurrence of
* <tt>${</tt><i>name</i><tt>}</tt> or <tt>$</tt><i>g</i>
* will be replaced by the result of evaluating the corresponding
- * {@link #group(String) group(name)} or {@link #group(int) group(g)</tt>}
- * respectively. For <tt>$</tt><i>g</i><tt></tt>,
+ * {@link #group(String) group(name)} or {@link #group(int) group(g)}
+ * respectively. For <tt>$</tt><i>g</i>,
* the first number after the <tt>$</tt> is always treated as part of
* the group reference. Subsequent numbers are incorporated into g if
* they would form a legal group reference. Only the numerals '0'
--- a/jdk/src/share/classes/java/util/regex/Pattern.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/regex/Pattern.java Tue Jul 09 15:26:20 2013 -0700
@@ -45,8 +45,8 @@
*
* <p> A regular expression, specified as a string, must first be compiled into
* an instance of this class. The resulting pattern can then be used to create
- * a {@link Matcher} object that can match arbitrary {@link
- * java.lang.CharSequence </code>character sequences<code>} against the regular
+ * a {@link Matcher} object that can match arbitrary {@linkplain
+ * java.lang.CharSequence character sequences} against the regular
* expression. All of the state involved in performing a match resides in the
* matcher, so many matchers can share the same pattern.
*
@@ -73,15 +73,14 @@
* such use.
*
*
- * <a name="sum">
- * <h4> Summary of regular-expression constructs </h4>
+ * <h3><a name="sum">Summary of regular-expression constructs</a></h3>
*
* <table border="0" cellpadding="1" cellspacing="0"
* summary="Regular expression constructs, and what they match">
*
* <tr align="left">
- * <th bgcolor="#CCCCFF" align="left" id="construct">Construct</th>
- * <th bgcolor="#CCCCFF" align="left" id="matches">Matches</th>
+ * <th align="left" id="construct">Construct</th>
+ * <th align="left" id="matches">Matches</th>
* </tr>
*
* <tr><th> </th></tr>
@@ -128,24 +127,24 @@
* <tr><th> </th></tr>
* <tr align="left"><th colspan="2" id="classes">Character classes</th></tr>
*
- * <tr><td valign="top" headers="construct classes"><tt>[abc]</tt></td>
- * <td headers="matches"><tt>a</tt>, <tt>b</tt>, or <tt>c</tt> (simple class)</td></tr>
- * <tr><td valign="top" headers="construct classes"><tt>[^abc]</tt></td>
- * <td headers="matches">Any character except <tt>a</tt>, <tt>b</tt>, or <tt>c</tt> (negation)</td></tr>
- * <tr><td valign="top" headers="construct classes"><tt>[a-zA-Z]</tt></td>
- * <td headers="matches"><tt>a</tt> through <tt>z</tt>
- * or <tt>A</tt> through <tt>Z</tt>, inclusive (range)</td></tr>
- * <tr><td valign="top" headers="construct classes"><tt>[a-d[m-p]]</tt></td>
- * <td headers="matches"><tt>a</tt> through <tt>d</tt>,
- * or <tt>m</tt> through <tt>p</tt>: <tt>[a-dm-p]</tt> (union)</td></tr>
- * <tr><td valign="top" headers="construct classes"><tt>[a-z&&[def]]</tt></td>
- * <td headers="matches"><tt>d</tt>, <tt>e</tt>, or <tt>f</tt> (intersection)</tr>
- * <tr><td valign="top" headers="construct classes"><tt>[a-z&&[^bc]]</tt></td>
- * <td headers="matches"><tt>a</tt> through <tt>z</tt>,
- * except for <tt>b</tt> and <tt>c</tt>: <tt>[ad-z]</tt> (subtraction)</td></tr>
- * <tr><td valign="top" headers="construct classes"><tt>[a-z&&[^m-p]]</tt></td>
- * <td headers="matches"><tt>a</tt> through <tt>z</tt>,
- * and not <tt>m</tt> through <tt>p</tt>: <tt>[a-lq-z]</tt>(subtraction)</td></tr>
+ * <tr><td valign="top" headers="construct classes">{@code [abc]}</td>
+ * <td headers="matches">{@code a}, {@code b}, or {@code c} (simple class)</td></tr>
+ * <tr><td valign="top" headers="construct classes">{@code [^abc]}</td>
+ * <td headers="matches">Any character except {@code a}, {@code b}, or {@code c} (negation)</td></tr>
+ * <tr><td valign="top" headers="construct classes">{@code [a-zA-Z]}</td>
+ * <td headers="matches">{@code a} through {@code z}
+ * or {@code A} through {@code Z}, inclusive (range)</td></tr>
+ * <tr><td valign="top" headers="construct classes">{@code [a-d[m-p]]}</td>
+ * <td headers="matches">{@code a} through {@code d},
+ * or {@code m} through {@code p}: {@code [a-dm-p]} (union)</td></tr>
+ * <tr><td valign="top" headers="construct classes">{@code [a-z&&[def]]}</td>
+ * <td headers="matches">{@code d}, {@code e}, or {@code f} (intersection)</tr>
+ * <tr><td valign="top" headers="construct classes">{@code [a-z&&[^bc]]}</td>
+ * <td headers="matches">{@code a} through {@code z},
+ * except for {@code b} and {@code c}: {@code [ad-z]} (subtraction)</td></tr>
+ * <tr><td valign="top" headers="construct classes">{@code [a-z&&[^m-p]]}</td>
+ * <td headers="matches">{@code a} through {@code z},
+ * and not {@code m} through {@code p}: {@code [a-lq-z]}(subtraction)</td></tr>
* <tr><th> </th></tr>
*
* <tr align="left"><th colspan="2" id="predef">Predefined character classes</th></tr>
@@ -175,36 +174,36 @@
* <tr><td valign="top" headers="construct predef"><tt>\W</tt></td>
* <td headers="matches">A non-word character: <tt>[^\w]</tt></td></tr>
* <tr><th> </th></tr>
- * <tr align="left"><th colspan="2" id="posix">POSIX character classes</b> (US-ASCII only)<b></th></tr>
+ * <tr align="left"><th colspan="2" id="posix"><b>POSIX character classes (US-ASCII only)</b></th></tr>
*
- * <tr><td valign="top" headers="construct posix"><tt>\p{Lower}</tt></td>
- * <td headers="matches">A lower-case alphabetic character: <tt>[a-z]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{Upper}</tt></td>
- * <td headers="matches">An upper-case alphabetic character:<tt>[A-Z]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{ASCII}</tt></td>
- * <td headers="matches">All ASCII:<tt>[\x00-\x7F]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{Alpha}</tt></td>
- * <td headers="matches">An alphabetic character:<tt>[\p{Lower}\p{Upper}]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{Digit}</tt></td>
- * <td headers="matches">A decimal digit: <tt>[0-9]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{Alnum}</tt></td>
- * <td headers="matches">An alphanumeric character:<tt>[\p{Alpha}\p{Digit}]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{Punct}</tt></td>
- * <td headers="matches">Punctuation: One of <tt>!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~</tt></td></tr>
- * <!-- <tt>[\!"#\$%&'\(\)\*\+,\-\./:;\<=\>\?@\[\\\]\^_`\{\|\}~]</tt>
- * <tt>[\X21-\X2F\X31-\X40\X5B-\X60\X7B-\X7E]</tt> -->
- * <tr><td valign="top" headers="construct posix"><tt>\p{Graph}</tt></td>
- * <td headers="matches">A visible character: <tt>[\p{Alnum}\p{Punct}]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{Print}</tt></td>
- * <td headers="matches">A printable character: <tt>[\p{Graph}\x20]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{Blank}</tt></td>
- * <td headers="matches">A space or a tab: <tt>[ \t]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{Cntrl}</tt></td>
- * <td headers="matches">A control character: <tt>[\x00-\x1F\x7F]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{XDigit}</tt></td>
- * <td headers="matches">A hexadecimal digit: <tt>[0-9a-fA-F]</tt></td></tr>
- * <tr><td valign="top" headers="construct posix"><tt>\p{Space}</tt></td>
- * <td headers="matches">A whitespace character: <tt>[ \t\n\x0B\f\r]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{Lower}}</td>
+ * <td headers="matches">A lower-case alphabetic character: {@code [a-z]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{Upper}}</td>
+ * <td headers="matches">An upper-case alphabetic character:{@code [A-Z]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{ASCII}}</td>
+ * <td headers="matches">All ASCII:{@code [\x00-\x7F]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{Alpha}}</td>
+ * <td headers="matches">An alphabetic character:{@code [\p{Lower}\p{Upper}]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{Digit}}</td>
+ * <td headers="matches">A decimal digit: {@code [0-9]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{Alnum}}</td>
+ * <td headers="matches">An alphanumeric character:{@code [\p{Alpha}\p{Digit}]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{Punct}}</td>
+ * <td headers="matches">Punctuation: One of {@code !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~}</td></tr>
+ * <!-- {@code [\!"#\$%&'\(\)\*\+,\-\./:;\<=\>\?@\[\\\]\^_`\{\|\}~]}
+ * {@code [\X21-\X2F\X31-\X40\X5B-\X60\X7B-\X7E]} -->
+ * <tr><td valign="top" headers="construct posix">{@code \p{Graph}}</td>
+ * <td headers="matches">A visible character: {@code [\p{Alnum}\p{Punct}]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{Print}}</td>
+ * <td headers="matches">A printable character: {@code [\p{Graph}\x20]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{Blank}}</td>
+ * <td headers="matches">A space or a tab: {@code [ \t]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{Cntrl}}</td>
+ * <td headers="matches">A control character: {@code [\x00-\x1F\x7F]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{XDigit}}</td>
+ * <td headers="matches">A hexadecimal digit: {@code [0-9a-fA-F]}</td></tr>
+ * <tr><td valign="top" headers="construct posix">{@code \p{Space}}</td>
+ * <td headers="matches">A whitespace character: {@code [ \t\n\x0B\f\r]}</td></tr>
*
* <tr><th> </th></tr>
* <tr align="left"><th colspan="2">java.lang.Character classes (simple <a href="#jcc">java character type</a>)</th></tr>
@@ -220,19 +219,19 @@
*
* <tr><th> </th></tr>
* <tr align="left"><th colspan="2" id="unicode">Classes for Unicode scripts, blocks, categories and binary properties</th></tr>
- * * <tr><td valign="top" headers="construct unicode"><tt>\p{IsLatin}</tt></td>
+ * * <tr><td valign="top" headers="construct unicode">{@code \p{IsLatin}}</td>
* <td headers="matches">A Latin script character (<a href="#usc">script</a>)</td></tr>
- * <tr><td valign="top" headers="construct unicode"><tt>\p{InGreek}</tt></td>
+ * <tr><td valign="top" headers="construct unicode">{@code \p{InGreek}}</td>
* <td headers="matches">A character in the Greek block (<a href="#ubc">block</a>)</td></tr>
- * <tr><td valign="top" headers="construct unicode"><tt>\p{Lu}</tt></td>
+ * <tr><td valign="top" headers="construct unicode">{@code \p{Lu}}</td>
* <td headers="matches">An uppercase letter (<a href="#ucc">category</a>)</td></tr>
- * <tr><td valign="top" headers="construct unicode"><tt>\p{IsAlphabetic}</tt></td>
+ * <tr><td valign="top" headers="construct unicode">{@code \p{IsAlphabetic}}</td>
* <td headers="matches">An alphabetic character (<a href="#ubpc">binary property</a>)</td></tr>
- * <tr><td valign="top" headers="construct unicode"><tt>\p{Sc}</tt></td>
+ * <tr><td valign="top" headers="construct unicode">{@code \p{Sc}}</td>
* <td headers="matches">A currency symbol</td></tr>
- * <tr><td valign="top" headers="construct unicode"><tt>\P{InGreek}</tt></td>
+ * <tr><td valign="top" headers="construct unicode">{@code \P{InGreek}}</td>
* <td headers="matches">Any character except one in the Greek block (negation)</td></tr>
- * <tr><td valign="top" headers="construct unicode"><tt>[\p{L}&&[^\p{Lu}]] </tt></td>
+ * <tr><td valign="top" headers="construct unicode">{@code [\p{L}&&[^\p{Lu}]]}</td>
* <td headers="matches">Any letter except an uppercase letter (subtraction)</td></tr>
*
* <tr><th> </th></tr>
@@ -376,8 +375,7 @@
* <hr>
*
*
- * <a name="bs">
- * <h4> Backslashes, escapes, and quoting </h4>
+ * <h3><a name="bs">Backslashes, escapes, and quoting</a></h3>
*
* <p> The backslash character (<tt>'\'</tt>) serves to introduce escaped
* constructs, as defined in the table above, as well as to quote characters
@@ -405,8 +403,7 @@
* <tt>(hello)</tt> the string literal <tt>"\\(hello\\)"</tt>
* must be used.
*
- * <a name="cc">
- * <h4> Character Classes </h4>
+ * <h3><a name="cc">Character Classes</a></h3>
*
* <p> Character classes may appear within other character classes, and
* may be composed by the union operator (implicit) and the intersection
@@ -435,7 +432,7 @@
* <td><tt>[a-e][i-u]</tt></td></tr>
* <tr><th>5 </th>
* <td>Intersection</td>
- * <td><tt>[a-z&&[aeiou]]</tt></td></tr>
+ * <td>{@code [a-z&&[aeiou]]}</td></tr>
* </table></blockquote>
*
* <p> Note that a different set of metacharacters are in effect inside
@@ -444,8 +441,7 @@
* character class, while the expression <tt>-</tt> becomes a range
* forming metacharacter.
*
- * <a name="lt">
- * <h4> Line terminators </h4>
+ * <h3><a name="lt">Line terminators</a></h3>
*
* <p> A <i>line terminator</i> is a one- or two-character sequence that marks
* the end of a line of the input character sequence. The following are
@@ -480,11 +476,9 @@
* except at the end of input. When in {@link #MULTILINE} mode <tt>$</tt>
* matches just before a line terminator or the end of the input sequence.
*
- * <a name="cg">
- * <h4> Groups and capturing </h4>
+ * <h3><a name="cg">Groups and capturing</a></h3>
*
- * <a name="gnumber">
- * <h5> Group number </h5>
+ * <h4><a name="gnumber">Group number</a></h4>
* <p> Capturing groups are numbered by counting their opening parentheses from
* left to right. In the expression <tt>((A)(B(C)))</tt>, for example, there
* are four such groups: </p>
@@ -507,8 +501,7 @@
* subsequence may be used later in the expression, via a back reference, and
* may also be retrieved from the matcher once the match operation is complete.
*
- * <a name="groupname">
- * <h5> Group name </h5>
+ * <h4><a name="groupname">Group name</a></h4>
* <p>A capturing group can also be assigned a "name", a <tt>named-capturing group</tt>,
* and then be back-referenced later by the "name". Group names are composed of
* the following characters. The first character must be a <tt>letter</tt>.
@@ -537,7 +530,7 @@
* that do not capture text and do not count towards the group total, or
* <i>named-capturing</i> group.
*
- * <h4> Unicode support </h4>
+ * <h3> Unicode support </h3>
*
* <p> This class is in conformance with Level 1 of <a
* href="http://www.unicode.org/reports/tr18/"><i>Unicode Technical
@@ -568,18 +561,18 @@
* <p>
* Scripts, blocks, categories and binary properties can be used both inside
* and outside of a character class.
- * <a name="usc">
+ *
* <p>
- * <b>Scripts</b> are specified either with the prefix {@code Is}, as in
+ * <b><a name="usc">Scripts</a></b> are specified either with the prefix {@code Is}, as in
* {@code IsHiragana}, or by using the {@code script} keyword (or its short
* form {@code sc})as in {@code script=Hiragana} or {@code sc=Hiragana}.
* <p>
* The script names supported by <code>Pattern</code> are the valid script names
* accepted and defined by
* {@link java.lang.Character.UnicodeScript#forName(String) UnicodeScript.forName}.
- * <a name="ubc">
+ *
* <p>
- * <b>Blocks</b> are specified with the prefix {@code In}, as in
+ * <b><a name="ubc">Blocks</a></b> are specified with the prefix {@code In}, as in
* {@code InMongolian}, or by using the keyword {@code block} (or its short
* form {@code blk}) as in {@code block=Mongolian} or {@code blk=Mongolian}.
* <p>
@@ -587,8 +580,8 @@
* accepted and defined by
* {@link java.lang.Character.UnicodeBlock#forName(String) UnicodeBlock.forName}.
* <p>
- * <a name="ucc">
- * <b>Categories</b> may be specified with the optional prefix {@code Is}:
+ *
+ * <b><a name="ucc">Categories</a></b> may be specified with the optional prefix {@code Is}:
* Both {@code \p{L}} and {@code \p{IsL}} denote the category of Unicode
* letters. Same as scripts and blocks, categories can also be specified
* by using the keyword {@code general_category} (or its short form
@@ -600,8 +593,8 @@
* {@link java.lang.Character Character} class. The category names are those
* defined in the Standard, both normative and informative.
* <p>
- * <a name="ubpc">
- * <b>Binary properties</b> are specified with the prefix {@code Is}, as in
+ *
+ * <b><a name="ubpc">Binary properties</a></b> are specified with the prefix {@code Is}, as in
* {@code IsAlphabetic}. The supported binary properties by <code>Pattern</code>
* are
* <ul>
@@ -629,8 +622,8 @@
* <table border="0" cellpadding="1" cellspacing="0"
* summary="predefined and posix character classes in Unicode mode">
* <tr align="left">
- * <th bgcolor="#CCCCFF" align="left" id="classes">Classes</th>
- * <th bgcolor="#CCCCFF" align="left" id="matches">Matches</th>
+ * <th align="left" id="predef_classes">Classes</th>
+ * <th align="left" id="predef_matches">Matches</th>
*</tr>
* <tr><td><tt>\p{Lower}</tt></td>
* <td>A lowercase character:<tt>\p{IsLowercase}</tt></td></tr>
@@ -649,9 +642,9 @@
* <tr><td><tt>\p{Graph}</tt></td>
* <td>A visible character: <tt>[^\p{IsWhite_Space}\p{gc=Cc}\p{gc=Cs}\p{gc=Cn}]</tt></td></tr>
* <tr><td><tt>\p{Print}</tt></td>
- * <td>A printable character: <tt>[\p{Graph}\p{Blank}&&[^\p{Cntrl}]]</tt></td></tr>
+ * <td>A printable character: {@code [\p{Graph}\p{Blank}&&[^\p{Cntrl}]]}</td></tr>
* <tr><td><tt>\p{Blank}</tt></td>
- * <td>A space or a tab: <tt>[\p{IsWhite_Space}&&[^\p{gc=Zl}\p{gc=Zp}\x0a\x0b\x0c\x0d\x85]]</tt></td></tr>
+ * <td>A space or a tab: {@code [\p{IsWhite_Space}&&[^\p{gc=Zl}\p{gc=Zp}\x0a\x0b\x0c\x0d\x85]]}</td></tr>
* <tr><td><tt>\p{Cntrl}</tt></td>
* <td>A control character: <tt>\p{gc=Cc}</tt></td></tr>
* <tr><td><tt>\p{XDigit}</tt></td>
@@ -676,9 +669,9 @@
* Categories that behave like the java.lang.Character
* boolean is<i>methodname</i> methods (except for the deprecated ones) are
* available through the same <tt>\p{</tt><i>prop</i><tt>}</tt> syntax where
- * the specified property has the name <tt>java<i>methodname</i></tt>.
+ * the specified property has the name <tt>java<i>methodname</i></tt></a>.
*
- * <h4> Comparison to Perl 5 </h4>
+ * <h3> Comparison to Perl 5 </h3>
*
* <p>The <code>Pattern</code> engine performs traditional NFA-based matching
* with ordered alternation as occurs in Perl 5.
@@ -1023,11 +1016,11 @@
private transient boolean hasSupplementary;
/**
- * Compiles the given regular expression into a pattern. </p>
+ * Compiles the given regular expression into a pattern.
*
* @param regex
* The expression to be compiled
- *
+ * @return the given regular expression compiled into a pattern
* @throws PatternSyntaxException
* If the expression's syntax is invalid
*/
@@ -1037,7 +1030,7 @@
/**
* Compiles the given regular expression into a pattern with the given
- * flags. </p>
+ * flags.
*
* @param regex
* The expression to be compiled
@@ -1049,6 +1042,7 @@
* {@link #LITERAL}, {@link #UNICODE_CHARACTER_CLASS}
* and {@link #COMMENTS}
*
+ * @return the given regular expression compiled into a pattern with the given flags
* @throws IllegalArgumentException
* If bit values other than those corresponding to the defined
* match flags are set in <tt>flags</tt>
@@ -1062,7 +1056,6 @@
/**
* Returns the regular expression from which this pattern was compiled.
- * </p>
*
* @return The source of this pattern
*/
@@ -1084,7 +1077,6 @@
/**
* Creates a matcher that will match the given input against this pattern.
- * </p>
*
* @param input
* The character sequence to be matched
@@ -1103,7 +1095,7 @@
}
/**
- * Returns this pattern's match flags. </p>
+ * Returns this pattern's match flags.
*
* @return The match flags specified when this pattern was compiled
*/
@@ -1133,7 +1125,7 @@
*
* @param input
* The character sequence to be matched
- *
+ * @return whether or not the regular expression matches on the input
* @throws PatternSyntaxException
* If the expression's syntax is invalid
*/
@@ -1170,9 +1162,9 @@
*
* <blockquote><table cellpadding=1 cellspacing=0
* summary="Split examples showing regex, limit, and result">
- * <tr><th><P align="left"><i>Regex </i></th>
- * <th><P align="left"><i>Limit </i></th>
- * <th><P align="left"><i>Result </i></th></tr>
+ * <tr><th align="left"><i>Regex </i></th>
+ * <th align="left"><i>Limit </i></th>
+ * <th align="left"><i>Result </i></th></tr>
* <tr><td align=center>:</td>
* <td align=center>2</td>
* <td><tt>{ "boo", "and:foo" }</tt></td></tr>
@@ -1253,8 +1245,8 @@
*
* <blockquote><table cellpadding=1 cellspacing=0
* summary="Split examples showing regex and result">
- * <tr><th><P align="left"><i>Regex </i></th>
- * <th><P align="left"><i>Result</i></th></tr>
+ * <tr><th align="left"><i>Regex </i></th>
+ * <th align="left"><i>Result</i></th></tr>
* <tr><td align=center>:</td>
* <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
* <tr><td align=center>o</td>
--- a/jdk/src/share/classes/java/util/stream/AbstractPipeline.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/AbstractPipeline.java Tue Jul 09 15:26:20 2013 -0700
@@ -53,11 +53,6 @@
* operation, the stream is considered to be consumed, and no more intermediate
* or terminal operations are permitted on this stream instance.
*
- * <p>{@code AbstractPipeline} implements a number of methods that are
- * specified in {@link BaseStream}, though it does not implement
- * {@code BaseStream} directly. Subclasses of {@code AbstractPipeline}
- * will generally implement {@code BaseStream}.
- *
* @implNote
* <p>For sequential streams, and parallel streams without
* <a href="package-summary.html#StreamOps">stateful intermediate
@@ -75,7 +70,7 @@
* @since 1.8
*/
abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
- extends PipelineHelper<E_OUT> {
+ extends PipelineHelper<E_OUT> implements BaseStream<E_OUT, S> {
/**
* Backlink to the head of the pipeline chain (self if this is the source
* stage).
@@ -286,26 +281,20 @@
// BaseStream
- /**
- * Implements {@link BaseStream#sequential()}
- */
+ @Override
public final S sequential() {
sourceStage.parallel = false;
return (S) this;
}
- /**
- * Implements {@link BaseStream#parallel()}
- */
+ @Override
public final S parallel() {
sourceStage.parallel = true;
return (S) this;
}
// Primitive specialization use co-variant overrides, hence is not final
- /**
- * Implements {@link BaseStream#spliterator()}
- */
+ @Override
public Spliterator<E_OUT> spliterator() {
if (linkedOrConsumed)
throw new IllegalStateException("stream has already been operated upon");
@@ -331,9 +320,7 @@
}
}
- /**
- * Implements {@link BaseStream#isParallel()}
- */
+ @Override
public final boolean isParallel() {
return sourceStage.parallel;
}
--- a/jdk/src/share/classes/java/util/stream/BaseStream.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/BaseStream.java Tue Jul 09 15:26:20 2013 -0700
@@ -29,15 +29,13 @@
/**
* Base interface for stream types such as {@link Stream}, {@link IntStream},
- * etc. Contains methods common to all stream types. Many of these methods
- * are implemented by {@link AbstractPipeline}, even though
- * {@code AbstractPipeline} does not directly implement {@code BaseStream}.
+ * etc. Contains methods common to all stream types.
*
* @param <T> type of stream elements
* @param <S> type of stream implementing {@code BaseStream}
* @since 1.8
*/
-interface BaseStream<T, S extends BaseStream<T, S>> {
+public interface BaseStream<T, S extends BaseStream<T, S>> {
/**
* Returns an iterator for the elements of this stream.
*
--- a/jdk/test/java/lang/SecurityManager/CheckPackageAccess.java Mon Jul 08 11:11:07 2013 -0700
+++ b/jdk/test/java/lang/SecurityManager/CheckPackageAccess.java Tue Jul 09 15:26:20 2013 -0700
@@ -22,31 +22,133 @@
*/
/*
- * @test
- * @bug 7146431 8000450
- * @summary Test that internal packages cannot be accessed
+ * @test
+ * @bug 6741606 7146431 8000450
+ * @summary Make sure all restricted packages listed in the package.access
+ * property in the java.security file are blocked
+ * @run main/othervm CheckPackageAccess
*/
+import java.security.Security;
+import java.util.Collections;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/*
+ * The main benefit of this test is to catch merge errors or other types
+ * of issues where one or more of the packages are accidentally
+ * removed. This is why the packages that are known to be restricted have to
+ * be explicitly listed below.
+ */
public class CheckPackageAccess {
+ /*
+ * This array should be updated whenever new packages are added to the
+ * package.access property in the java.security file
+ */
+ private static final String[] packages = {
+ "sun.",
+ "com.sun.corba.se.impl.",
+ "com.sun.xml.internal.",
+ "com.sun.imageio.",
+ "com.sun.istack.internal.",
+ "com.sun.jmx.",
+ "com.sun.proxy.",
+ "com.sun.org.apache.bcel.internal.",
+ "com.sun.org.apache.regexp.internal.",
+ "com.sun.org.apache.xerces.internal.",
+ "com.sun.org.apache.xpath.internal.",
+ "com.sun.org.apache.xalan.internal.extensions.",
+ "com.sun.org.apache.xalan.internal.lib.",
+ "com.sun.org.apache.xalan.internal.res.",
+ "com.sun.org.apache.xalan.internal.templates.",
+ "com.sun.org.apache.xalan.internal.utils.",
+ "com.sun.org.apache.xalan.internal.xslt.",
+ "com.sun.org.apache.xalan.internal.xsltc.cmdline.",
+ "com.sun.org.apache.xalan.internal.xsltc.compiler.",
+ "com.sun.org.apache.xalan.internal.xsltc.trax.",
+ "com.sun.org.apache.xalan.internal.xsltc.util.",
+ "com.sun.org.apache.xml.internal.res.",
+ "com.sun.org.apache.xml.internal.security.",
+ "com.sun.org.apache.xml.internal.serializer.utils.",
+ "com.sun.org.apache.xml.internal.utils.",
+ "com.sun.org.glassfish.",
+ "com.oracle.xmlns.internal.",
+ "com.oracle.webservices.internal.",
+ "oracle.jrockit.jfr.",
+ "org.jcp.xml.dsig.internal.",
+ "jdk.internal.",
+ "jdk.nashorn.internal.",
+ "jdk.nashorn.tools."
+ };
+
public static void main(String[] args) throws Exception {
+ List<String> pkgs = new ArrayList<>(Arrays.asList(packages));
+ String osName = System.getProperty("os.name");
+ if (osName.contains("OS X")) {
+ pkgs.add("apple."); // add apple package for OS X
+ } else if (osName.startsWith("Windows")) {
+ pkgs.add("com.sun.java.accessibility.");
+ }
- String[] pkgs = new String[] {
- "com.sun.corba.se.impl.",
- "com.sun.org.apache.xerces.internal.utils.",
- "com.sun.org.apache.xalan.internal.utils." };
- SecurityManager sm = new SecurityManager();
- System.setSecurityManager(sm);
- for (String pkg : pkgs) {
- System.out.println("Checking package access for " + pkg);
+ List<String> jspkgs =
+ getPackages(Security.getProperty("package.access"));
+
+ // Sort to ensure lists are comparable
+ Collections.sort(pkgs);
+ Collections.sort(jspkgs);
+
+ if (!pkgs.equals(jspkgs)) {
+ for (String p : pkgs)
+ if (!jspkgs.contains(p))
+ System.out.println("In golden set, but not in j.s file: " + p);
+ for (String p : jspkgs)
+ if (!pkgs.contains(p))
+ System.out.println("In j.s file, but not in golden set: " + p);
+
+
+ throw new RuntimeException("restricted packages are not " +
+ "consistent with java.security file");
+ }
+ System.setSecurityManager(new SecurityManager());
+ SecurityManager sm = System.getSecurityManager();
+ for (String pkg : packages) {
+ String subpkg = pkg + "foo";
try {
sm.checkPackageAccess(pkg);
- throw new Exception("Expected PackageAccess SecurityException not thrown");
+ throw new RuntimeException("Able to access " + pkg +
+ " package");
+ } catch (SecurityException se) { }
+ try {
+ sm.checkPackageAccess(subpkg);
+ throw new RuntimeException("Able to access " + subpkg +
+ " package");
} catch (SecurityException se) { }
try {
sm.checkPackageDefinition(pkg);
- throw new Exception("Expected PackageDefinition SecurityException not thrown");
+ throw new RuntimeException("Able to define class in " + pkg +
+ " package");
+ } catch (SecurityException se) { }
+ try {
+ sm.checkPackageDefinition(subpkg);
+ throw new RuntimeException("Able to define class in " + subpkg +
+ " package");
} catch (SecurityException se) { }
}
+ System.out.println("Test passed");
+ }
+
+ private static List<String> getPackages(String p) {
+ List<String> packages = new ArrayList<>();
+ if (p != null && !p.equals("")) {
+ StringTokenizer tok = new StringTokenizer(p, ",");
+ while (tok.hasMoreElements()) {
+ String s = tok.nextToken().trim();
+ packages.add(s);
+ }
+ }
+ return packages;
}
}