# HG changeset patch # User prr # Date 1501184209 25200 # Node ID e4003d3dc465a5cf33ae63ce9c55ad973be52781 # Parent c9ac54d4acb45a394df630724f20714c8878e4c2# Parent 38f385381e541677ae0c0e0c7fb165e33d72698d Merge diff -r c9ac54d4acb4 -r e4003d3dc465 .hgtags --- a/.hgtags Tue Jul 25 14:07:47 2017 -0700 +++ b/.hgtags Thu Jul 27 12:36:49 2017 -0700 @@ -437,3 +437,4 @@ 9927a9f16738e240ab7014f0118f41e314ef8f99 jdk-10+13 9ef5029b247b4d940080417a287440bbdbab995b jdk-10+14 878e216039322cb3f0ecbd0944642a2b4e2593f3 jdk-10+15 +4bbea012e5676e8025ade2bcfab4d6581e6e9f4b jdk-10+16 diff -r c9ac54d4acb4 -r e4003d3dc465 .hgtags-top-repo --- a/.hgtags-top-repo Tue Jul 25 14:07:47 2017 -0700 +++ b/.hgtags-top-repo Thu Jul 27 12:36:49 2017 -0700 @@ -437,3 +437,5 @@ a4371edb589c60db01142e45c317adb9ccbcb083 jdk-9+177 a6c830ee8a6798b186730475e700027cdf4598aa jdk-10+15 2fe66ca1e2b3c361f949de9cb2894661dc0a3fa2 jdk-10+16 +ec4159ebe7050fcc5dcee8a2d150cf948ecc97db jdk-9+178 +252475ccfd84cc249f8d6faf4b7806b5e2c384ce jdk-9+179 diff -r c9ac54d4acb4 -r e4003d3dc465 corba/.hgtags --- a/corba/.hgtags Tue Jul 25 14:07:47 2017 -0700 +++ b/corba/.hgtags Thu Jul 27 12:36:49 2017 -0700 @@ -436,3 +436,4 @@ 40fb9f229471ef357d493813d34b15afcce9f32b jdk-9+176 c72e9d3823f04cb3ef3166646dfea9e4c2769133 jdk-9+177 15f59cfc6fbe9387423fb173e962265c7b5d357e jdk-10+15 +b82b62ed5debda2d98dda597506ef29cf947fbae jdk-10+16 diff -r c9ac54d4acb4 -r e4003d3dc465 hotspot/.hgtags --- a/hotspot/.hgtags Tue Jul 25 14:07:47 2017 -0700 +++ b/hotspot/.hgtags Thu Jul 27 12:36:49 2017 -0700 @@ -596,3 +596,4 @@ 2ab74e5dbdc2b6a962c865500cafd23cf387dc60 jdk-9+176 1ca8f038fceb88c640badf9bd18905205bc63b43 jdk-9+177 c1f3649a3a42f124b418a5a916dbad13d059b757 jdk-10+15 +2fe2a593e8ebf3a9e4dcd9ba3333a7b43126589d jdk-10+16 diff -r c9ac54d4acb4 -r e4003d3dc465 jaxp/.hgtags --- a/jaxp/.hgtags Tue Jul 25 14:07:47 2017 -0700 +++ b/jaxp/.hgtags Thu Jul 27 12:36:49 2017 -0700 @@ -436,3 +436,4 @@ 38cf34e2328070cc691c4f136e6dde1a44c04171 jdk-9+176 332ad9f92632f56f337b8c40edef9a95a42b26bc jdk-9+177 02a876781a3a6193140591d92db7b95ca743eac2 jdk-10+15 +d109d55cf642bf2b438624e81f94c18c168f9178 jdk-10+16 diff -r c9ac54d4acb4 -r e4003d3dc465 jaxws/.hgtags --- a/jaxws/.hgtags Tue Jul 25 14:07:47 2017 -0700 +++ b/jaxws/.hgtags Thu Jul 27 12:36:49 2017 -0700 @@ -439,3 +439,4 @@ ea819b6009d33a72e6672bab6c101d51db0cfb4c jdk-9+176 b44a721aee3d3b2537754e559fe9ecccadea548b jdk-9+177 6d17fd0a5133a0dd916c77a9a24ae7f0ca402876 jdk-10+15 +bc8289ce1ed3ed5fff62152ed46da3be0b60b7c3 jdk-10+16 diff -r c9ac54d4acb4 -r e4003d3dc465 jaxws/src/java.activation/share/classes/javax/activation/CommandInfo.java --- a/jaxws/src/java.activation/share/classes/javax/activation/CommandInfo.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jaxws/src/java.activation/share/classes/javax/activation/CommandInfo.java Thu Jul 27 12:36:49 2017 -0700 @@ -112,7 +112,7 @@ * this method will check if it implements the * java.io.Externalizable interface. If it does, the bean's * readExternal method will be called if an InputStream - * can be acquired from the DataHandler.

+ * can be acquired from the DataHandler. * * @param dh The DataHandler that describes the data to be * passed to the command. diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/.hgtags --- a/jdk/.hgtags Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/.hgtags Thu Jul 27 12:36:49 2017 -0700 @@ -436,3 +436,4 @@ 9f27d513658d5375b0e26846857d92563f279073 jdk-9+176 80acf577b7d0b886fb555c9916552844f6cc72af jdk-9+177 e069834e2c518a7bc2ffadc8c7e3cd7ec69fa8a0 jdk-10+15 +3281b964ab104002623d744e8b77a12269b70acd jdk-10+16 diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/make/data/jdwp/jdwp.spec --- a/jdk/make/data/jdwp/jdwp.spec Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/make/data/jdwp/jdwp.spec Thu Jul 27 12:36:49 2017 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -1378,7 +1378,7 @@ (Repeat lines "The number of entries in the line table for this method." (Group LineInfo (long lineCodeIndex "Initial code index of the line, " - "start <= lineCodeIndex < end") + "start <= lineCodeIndex < end") (int lineNumber "Line number.") ) ) @@ -1409,13 +1409,13 @@ "First code index at which the variable is visible (unsigned). " "Used in conjunction with length. " "The variable can be get or set only when the current " - "codeIndex <= current frame code index < codeIndex + length ") + "codeIndex <= current frame code index < codeIndex + length ") (string name "The variable's name.") (string signature "The variable type's JNI signature.") (int length "Unsigned value used in conjunction with codeIndex. " "The variable can be get or set only when the current " - "codeIndex <= current frame code index < code index + length ") + "codeIndex <= current frame code index < code index + length ") (int slot "The local variable's index in its frame") ) ) @@ -1502,7 +1502,7 @@ "First code index at which the variable is visible (unsigned). " "Used in conjunction with length. " "The variable can be get or set only when the current " - "codeIndex <= current frame code index < codeIndex + length ") + "codeIndex <= current frame code index < codeIndex + length ") (string name "The variable's name.") (string signature "The variable type's JNI signature.") (string genericSignature "The variable type's generic " @@ -1510,7 +1510,7 @@ (int length "Unsigned value used in conjunction with codeIndex. " "The variable can be get or set only when the current " - "codeIndex <= current frame code index < code index + length ") + "codeIndex <= current frame code index < code index + length ") (int slot "The local variable's index in its frame") ) ) diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/lang/System.java --- a/jdk/src/java.base/share/classes/java/lang/System.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/lang/System.java Thu Jul 27 12:36:49 2017 -0700 @@ -1960,10 +1960,6 @@ setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding"))); setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding"))); - // Load the zip library now in order to keep java.util.zip.ZipFile - // from trying to use itself to load this library later. - loadLibrary("zip"); - // Setup Java signal handlers for HUP, TERM, and INT (where available). Terminator.setup(); diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/util/ArrayDeque.java --- a/jdk/src/java.base/share/classes/java/util/ArrayDeque.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/util/ArrayDeque.java Thu Jul 27 12:36:49 2017 -0700 @@ -243,7 +243,7 @@ * Index i must be logically ahead of index j. * Precondition: 0 <= i < modulus, 0 <= j < modulus. * @return the "circular distance" from j to i; corner case i == j - * is diambiguated to "empty", returning 0. + * is disambiguated to "empty", returning 0. */ static final int sub(int i, int j, int modulus) { if ((i -= j) < 0) i += modulus; @@ -310,8 +310,7 @@ /** * Adds all of the elements in the specified collection at the end * of this deque, as if by calling {@link #addLast} on each one, - * in the order that they are returned by the collection's - * iterator. + * in the order that they are returned by the collection's iterator. * * @param c the elements to be inserted into this deque * @return {@code true} if this deque changed as a result of the call @@ -508,8 +507,8 @@ /** * Retrieves and removes the head of the queue represented by this deque. * - * This method differs from {@link #poll poll} only in that it throws an - * exception if this deque is empty. + * This method differs from {@link #poll() poll()} only in that it + * throws an exception if this deque is empty. * *

This method is equivalent to {@link #removeFirst}. * diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/util/ArrayList.java --- a/jdk/src/java.base/share/classes/java/util/ArrayList.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/util/ArrayList.java Thu Jul 27 12:36:49 2017 -0700 @@ -514,15 +514,10 @@ */ public E remove(int index) { Objects.checkIndex(index, size); - - modCount++; - E oldValue = elementData(index); + final Object[] es = elementData; - int numMoved = size - index - 1; - if (numMoved > 0) - System.arraycopy(elementData, index+1, elementData, index, - numMoved); - elementData[--size] = null; // clear to let GC do its work + @SuppressWarnings("unchecked") E oldValue = (E) es[index]; + fastRemove(es, index); return oldValue; } @@ -541,33 +536,35 @@ * @return {@code true} if this list contained the specified element */ public boolean remove(Object o) { - if (o == null) { - for (int index = 0; index < size; index++) - if (elementData[index] == null) { - fastRemove(index); - return true; - } - } else { - for (int index = 0; index < size; index++) - if (o.equals(elementData[index])) { - fastRemove(index); - return true; - } + final Object[] es = elementData; + final int size = this.size; + int i = 0; + found: { + if (o == null) { + for (; i < size; i++) + if (es[i] == null) + break found; + } else { + for (; i < size; i++) + if (o.equals(es[i])) + break found; + } + return false; } - return false; + fastRemove(es, i); + return true; } /** * Private remove method that skips bounds checking and does not * return the value removed. */ - private void fastRemove(int index) { + private void fastRemove(Object[] es, int i) { modCount++; - int numMoved = size - index - 1; - if (numMoved > 0) - System.arraycopy(elementData, index+1, elementData, index, - numMoved); - elementData[--size] = null; // clear to let GC do its work + final int newSize; + if ((newSize = size - 1) > i) + System.arraycopy(es, i + 1, es, i, newSize - i); + es[size = newSize] = null; } /** @@ -743,29 +740,30 @@ final int from, final int end) { Objects.requireNonNull(c); final Object[] es = elementData; - final boolean modified; int r; // Optimize for initial run of survivors - for (r = from; r < end && c.contains(es[r]) == complement; r++) - ; - if (modified = (r < end)) { - int w = r++; - try { - for (Object e; r < end; r++) - if (c.contains(e = es[r]) == complement) - es[w++] = e; - } catch (Throwable ex) { - // Preserve behavioral compatibility with AbstractCollection, - // even if c.contains() throws. - System.arraycopy(es, r, es, w, end - r); - w += end - r; - throw ex; - } finally { - modCount += end - w; - shiftTailOverGap(es, w, end); - } + for (r = from;; r++) { + if (r == end) + return false; + if (c.contains(es[r]) != complement) + break; } - return modified; + int w = r++; + try { + for (Object e; r < end; r++) + if (c.contains(e = es[r]) == complement) + es[w++] = e; + } catch (Throwable ex) { + // Preserve behavioral compatibility with AbstractCollection, + // even if c.contains() throws. + System.arraycopy(es, r, es, w, end - r); + w += end - r; + throw ex; + } finally { + modCount += end - w; + shiftTailOverGap(es, w, end); + } + return true; } /** @@ -784,7 +782,7 @@ int expectedModCount = modCount; s.defaultWriteObject(); - // Write out size as capacity for behavioural compatibility with clone() + // Write out size as capacity for behavioral compatibility with clone() s.writeInt(size); // Write out all elements in the proper order. diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/util/Queue.java --- a/jdk/src/java.base/share/classes/java/util/Queue.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/util/Queue.java Thu Jul 27 12:36:49 2017 -0700 @@ -37,15 +37,14 @@ /** * A collection designed for holding elements prior to processing. - * Besides basic {@link java.util.Collection Collection} operations, - * queues provide additional insertion, extraction, and inspection - * operations. Each of these methods exists in two forms: one throws - * an exception if the operation fails, the other returns a special - * value (either {@code null} or {@code false}, depending on the - * operation). The latter form of the insert operation is designed - * specifically for use with capacity-restricted {@code Queue} - * implementations; in most implementations, insert operations cannot - * fail. + * Besides basic {@link Collection} operations, queues provide + * additional insertion, extraction, and inspection operations. + * Each of these methods exists in two forms: one throws an exception + * if the operation fails, the other returns a special value (either + * {@code null} or {@code false}, depending on the operation). The + * latter form of the insert operation is designed specifically for + * use with capacity-restricted {@code Queue} implementations; in most + * implementations, insert operations cannot fail. * * * @@ -56,18 +55,18 @@ * * * - * - * + * + * * * * - * - * + * + * * * * - * - * + * + * * *
Summary of Queue methods
Insert{@link Queue#add add(e)}{@link Queue#offer offer(e)}{@link #add(Object) add(e)}{@link #offer(Object) offer(e)}
Remove{@link Queue#remove remove()}{@link Queue#poll poll()}{@link #remove() remove()}{@link #poll() poll()}
Examine{@link Queue#element element()}{@link Queue#peek peek()}{@link #element() element()}{@link #peek() peek()}
* @@ -77,7 +76,7 @@ * comparator, or the elements' natural ordering, and LIFO queues (or * stacks) which order the elements LIFO (last-in-first-out). * Whatever the ordering used, the head of the queue is that - * element which would be removed by a call to {@link #remove() } or + * element which would be removed by a call to {@link #remove()} or * {@link #poll()}. In a FIFO queue, all new elements are inserted at * the tail of the queue. Other kinds of queues may use * different placement rules. Every {@code Queue} implementation @@ -173,8 +172,8 @@ /** * Retrieves and removes the head of this queue. This method differs - * from {@link #poll poll} only in that it throws an exception if this - * queue is empty. + * from {@link #poll() poll()} only in that it throws an exception if + * this queue is empty. * * @return the head of this queue * @throws NoSuchElementException if this queue is empty diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java --- a/jdk/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java Thu Jul 27 12:36:49 2017 -0700 @@ -67,22 +67,22 @@ * * * Insert - * {@link #addFirst addFirst(e)} + * {@link #addFirst(Object) addFirst(e)} * {@link #offerFirst(Object) offerFirst(e)} - * {@link #putFirst putFirst(e)} + * {@link #putFirst(Object) putFirst(e)} * {@link #offerFirst(Object, long, TimeUnit) offerFirst(e, time, unit)} * * * Remove - * {@link #removeFirst removeFirst()} - * {@link #pollFirst pollFirst()} - * {@link #takeFirst takeFirst()} + * {@link #removeFirst() removeFirst()} + * {@link #pollFirst() pollFirst()} + * {@link #takeFirst() takeFirst()} * {@link #pollFirst(long, TimeUnit) pollFirst(time, unit)} * * * Examine - * {@link #getFirst getFirst()} - * {@link #peekFirst peekFirst()} + * {@link #getFirst() getFirst()} + * {@link #peekFirst() peekFirst()} * not applicable * not applicable * @@ -98,22 +98,22 @@ * * * Insert - * {@link #addLast addLast(e)} + * {@link #addLast(Object) addLast(e)} * {@link #offerLast(Object) offerLast(e)} - * {@link #putLast putLast(e)} + * {@link #putLast(Object) putLast(e)} * {@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)} * * * Remove * {@link #removeLast() removeLast()} * {@link #pollLast() pollLast()} - * {@link #takeLast takeLast()} + * {@link #takeLast() takeLast()} * {@link #pollLast(long, TimeUnit) pollLast(time, unit)} * * * Examine - * {@link #getLast getLast()} - * {@link #peekLast peekLast()} + * {@link #getLast() getLast()} + * {@link #peekLast() peekLast()} * not applicable * not applicable * @@ -512,7 +512,7 @@ /** * Retrieves and removes the head of the queue represented by this deque * (in other words, the first element of this deque). - * This method differs from {@link #poll poll} only in that it + * This method differs from {@link #poll() poll()} only in that it * throws an exception if this deque is empty. * *

This method is equivalent to {@link #removeFirst() removeFirst}. @@ -563,7 +563,7 @@ /** * Retrieves, but does not remove, the head of the queue represented by * this deque (in other words, the first element of this deque). - * This method differs from {@link #peek peek} only in that it throws an + * This method differs from {@link #peek() peek} only in that it throws an * exception if this deque is empty. * *

This method is equivalent to {@link #getFirst() getFirst}. diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java --- a/jdk/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java Thu Jul 27 12:36:49 2017 -0700 @@ -39,10 +39,9 @@ import java.util.Queue; /** - * A {@link java.util.Queue} that additionally supports operations - * that wait for the queue to become non-empty when retrieving an - * element, and wait for space to become available in the queue when - * storing an element. + * A {@link Queue} that additionally supports operations that wait for + * the queue to become non-empty when retrieving an element, and wait + * for space to become available in the queue when storing an element. * *

{@code BlockingQueue} methods come in four forms, with different ways * of handling operations that cannot be satisfied immediately, but may be @@ -64,22 +63,22 @@ * * * Insert - * {@link #add add(e)} - * {@link #offer offer(e)} - * {@link #put put(e)} + * {@link #add(Object) add(e)} + * {@link #offer(Object) offer(e)} + * {@link #put(Object) put(e)} * {@link #offer(Object, long, TimeUnit) offer(e, time, unit)} * * * Remove - * {@link #remove remove()} - * {@link #poll poll()} - * {@link #take take()} + * {@link #remove() remove()} + * {@link #poll() poll()} + * {@link #take() take()} * {@link #poll(long, TimeUnit) poll(time, unit)} * * * Examine - * {@link #element element()} - * {@link #peek peek()} + * {@link #element() element()} + * {@link #peek() peek()} * not applicable * not applicable * @@ -99,7 +98,7 @@ * *

{@code BlockingQueue} implementations are designed to be used * primarily for producer-consumer queues, but additionally support - * the {@link java.util.Collection} interface. So, for example, it is + * the {@link Collection} interface. So, for example, it is * possible to remove an arbitrary element from a queue using * {@code remove(x)}. However, such operations are in general * not performed very efficiently, and are intended for only diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Thu Jul 27 12:36:49 2017 -0700 @@ -159,8 +159,7 @@ * ordering, or on any other objects or values that may transiently * change while computation is in progress; and except for forEach * actions, should ideally be side-effect-free. Bulk operations on - * {@link java.util.Map.Entry} objects do not support method {@code - * setValue}. + * {@link Map.Entry} objects do not support method {@code setValue}. * *

* Subsequent executions are suppressed. Subsequent calls to * {@link Future#isDone isDone()} on the returned future will @@ -199,7 +198,7 @@ * abnormal termination of a task execution. * @throws RejectedExecutionException if the task cannot be * scheduled for execution - * @throws NullPointerException if command is null + * @throws NullPointerException if command or unit is null * @throws IllegalArgumentException if delay less than or equal to zero */ public ScheduledFuture scheduleWithFixedDelay(Runnable command, diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java --- a/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Thu Jul 27 12:36:49 2017 -0700 @@ -44,6 +44,7 @@ import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; @@ -87,6 +88,11 @@ * use {@code allowCoreThreadTimeOut} because this may leave the pool * without threads to handle tasks once they become eligible to run. * + *

As with {@code ThreadPoolExecutor}, if not otherwise specified, + * this class uses {@link Executors#defaultThreadFactory} as the + * default thread factory, and {@link ThreadPoolExecutor.AbortPolicy} + * as the default rejected execution handler. + * *

Extension notes: This class overrides the * {@link ThreadPoolExecutor#execute(Runnable) execute} and * {@link AbstractExecutorService#submit(Runnable) submit} @@ -161,7 +167,7 @@ private volatile boolean continueExistingPeriodicTasksAfterShutdown; /** - * False if should cancel non-periodic tasks on shutdown. + * False if should cancel non-periodic not-yet-expired tasks on shutdown. */ private volatile boolean executeExistingDelayedTasksAfterShutdown = true; @@ -292,10 +298,9 @@ * Overrides FutureTask version so as to reset/requeue if periodic. */ public void run() { - boolean periodic = isPeriodic(); - if (!canRunInCurrentRunState(periodic)) + if (!canRunInCurrentRunState(this)) cancel(false); - else if (!periodic) + else if (!isPeriodic()) super.run(); else if (super.runAndReset()) { setNextRunTime(); @@ -305,15 +310,18 @@ } /** - * Returns true if can run a task given current run state - * and run-after-shutdown parameters. - * - * @param periodic true if this task periodic, false if delayed + * Returns true if can run a task given current run state and + * run-after-shutdown parameters. */ - boolean canRunInCurrentRunState(boolean periodic) { - return isRunningOrShutdown(periodic ? - continueExistingPeriodicTasksAfterShutdown : - executeExistingDelayedTasksAfterShutdown); + boolean canRunInCurrentRunState(RunnableScheduledFuture task) { + if (!isShutdown()) + return true; + if (isStopped()) + return false; + return task.isPeriodic() + ? continueExistingPeriodicTasksAfterShutdown + : (executeExistingDelayedTasksAfterShutdown + || task.getDelay(NANOSECONDS) <= 0); } /** @@ -332,9 +340,7 @@ reject(task); else { super.getQueue().add(task); - if (isShutdown() && - !canRunInCurrentRunState(task.isPeriodic()) && - remove(task)) + if (!canRunInCurrentRunState(task) && remove(task)) task.cancel(false); else ensurePrestart(); @@ -348,13 +354,14 @@ * @param task the task */ void reExecutePeriodic(RunnableScheduledFuture task) { - if (canRunInCurrentRunState(true)) { + if (canRunInCurrentRunState(task)) { super.getQueue().add(task); - if (!canRunInCurrentRunState(true) && remove(task)) - task.cancel(false); - else + if (canRunInCurrentRunState(task) || !remove(task)) { ensurePrestart(); + return; + } } + task.cancel(false); } /** @@ -367,23 +374,18 @@ getExecuteExistingDelayedTasksAfterShutdownPolicy(); boolean keepPeriodic = getContinueExistingPeriodicTasksAfterShutdownPolicy(); - if (!keepDelayed && !keepPeriodic) { - for (Object e : q.toArray()) - if (e instanceof RunnableScheduledFuture) - ((RunnableScheduledFuture) e).cancel(false); - q.clear(); - } - else { - // Traverse snapshot to avoid iterator exceptions - for (Object e : q.toArray()) { - if (e instanceof RunnableScheduledFuture) { - RunnableScheduledFuture t = - (RunnableScheduledFuture)e; - if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) || - t.isCancelled()) { // also remove if already cancelled - if (q.remove(t)) - t.cancel(false); - } + // Traverse snapshot to avoid iterator exceptions + // TODO: implement and use efficient removeIf + // super.getQueue().removeIf(...); + for (Object e : q.toArray()) { + if (e instanceof RunnableScheduledFuture) { + RunnableScheduledFuture t = (RunnableScheduledFuture)e; + if ((t.isPeriodic() + ? !keepPeriodic + : (!keepDelayed && t.getDelay(NANOSECONDS) > 0)) + || t.isCancelled()) { // also remove if already cancelled + if (q.remove(t)) + t.cancel(false); } } } @@ -579,6 +581,34 @@ } /** + * Submits a periodic action that becomes enabled first after the + * given initial delay, and subsequently with the given period; + * that is, executions will commence after + * {@code initialDelay}, then {@code initialDelay + period}, then + * {@code initialDelay + 2 * period}, and so on. + * + *

The sequence of task executions continues indefinitely until + * one of the following exceptional completions occur: + *

+ * Subsequent executions are suppressed. Subsequent calls to + * {@link Future#isDone isDone()} on the returned future will + * return {@code true}. + * + *

If any execution of this task takes longer than its period, then + * subsequent executions may start late, but will not concurrently + * execute. + * * @throws RejectedExecutionException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} @@ -604,6 +634,29 @@ } /** + * Submits a periodic action that becomes enabled first after the + * given initial delay, and subsequently with the given delay + * between the termination of one execution and the commencement of + * the next. + * + *

The sequence of task executions continues indefinitely until + * one of the following exceptional completions occur: + *

+ * Subsequent executions are suppressed. Subsequent calls to + * {@link Future#isDone isDone()} on the returned future will + * return {@code true}. + * * @throws RejectedExecutionException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} @@ -681,9 +734,8 @@ /** * Sets the policy on whether to continue executing existing * periodic tasks even when this executor has been {@code shutdown}. - * In this case, these tasks will only terminate upon - * {@code shutdownNow} or after setting the policy to - * {@code false} when already shutdown. + * In this case, executions will continue until {@code shutdownNow} + * or the policy is set to {@code false} when already shutdown. * This value is by default {@code false}. * * @param value if {@code true}, continue after shutdown, else don't @@ -698,9 +750,8 @@ /** * Gets the policy on whether to continue executing existing * periodic tasks even when this executor has been {@code shutdown}. - * In this case, these tasks will only terminate upon - * {@code shutdownNow} or after setting the policy to - * {@code false} when already shutdown. + * In this case, executions will continue until {@code shutdownNow} + * or the policy is set to {@code false} when already shutdown. * This value is by default {@code false}. * * @return {@code true} if will continue after shutdown @@ -904,7 +955,7 @@ /** * Sets f's heapIndex if it is a ScheduledFutureTask. */ - private void setIndex(RunnableScheduledFuture f, int idx) { + private static void setIndex(RunnableScheduledFuture f, int idx) { if (f instanceof ScheduledFutureTask) ((ScheduledFutureTask)f).heapIndex = idx; } @@ -1202,41 +1253,12 @@ } } - /** - * Returns first element only if it is expired. - * Used only by drainTo. Call only when holding lock. - */ - private RunnableScheduledFuture peekExpired() { - // assert lock.isHeldByCurrentThread(); - RunnableScheduledFuture first = queue[0]; - return (first == null || first.getDelay(NANOSECONDS) > 0) ? - null : first; - } - public int drainTo(Collection c) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - final ReentrantLock lock = this.lock; - lock.lock(); - try { - RunnableScheduledFuture first; - int n = 0; - while ((first = peekExpired()) != null) { - c.add(first); // In this order, in case add() throws. - finishPoll(first); - ++n; - } - return n; - } finally { - lock.unlock(); - } + return drainTo(c, Integer.MAX_VALUE); } public int drainTo(Collection c, int maxElements) { - if (c == null) - throw new NullPointerException(); + Objects.requireNonNull(c); if (c == this) throw new IllegalArgumentException(); if (maxElements <= 0) @@ -1244,9 +1266,11 @@ final ReentrantLock lock = this.lock; lock.lock(); try { - RunnableScheduledFuture first; int n = 0; - while (n < maxElements && (first = peekExpired()) != null) { + for (RunnableScheduledFuture first; + n < maxElements + && (first = queue[0]) != null + && first.getDelay(NANOSECONDS) <= 0;) { c.add(first); // In this order, in case add() throws. finishPoll(first); ++n; @@ -1284,7 +1308,13 @@ } public Iterator iterator() { - return new Itr(Arrays.copyOf(queue, size)); + final ReentrantLock lock = this.lock; + lock.lock(); + try { + return new Itr(Arrays.copyOf(queue, size)); + } finally { + lock.unlock(); + } } /** diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java --- a/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java Thu Jul 27 12:36:49 2017 -0700 @@ -359,7 +359,7 @@ * This "barging" behavior can be useful in certain * circumstances, even though it breaks fairness. If you want to honor * the fairness setting, then use - * {@link #tryAcquire(long, TimeUnit) tryAcquire(0, TimeUnit.SECONDS) } + * {@link #tryAcquire(long, TimeUnit) tryAcquire(0, TimeUnit.SECONDS)} * which is almost equivalent (it also detects interruption). * * @return {@code true} if a permit was acquired and {@code false} @@ -523,7 +523,7 @@ * "barging" behavior can be useful in certain * circumstances, even though it breaks fairness. If you want to * honor the fairness setting, then use {@link #tryAcquire(int, - * long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SECONDS) } + * long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SECONDS)} * which is almost equivalent (it also detects interruption). * * @param permits the number of permits to acquire diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java --- a/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java Thu Jul 27 12:36:49 2017 -0700 @@ -1066,7 +1066,7 @@ /** * Returns an empty spliterator in which calls to - * {@link java.util.Spliterator#trySplit()} always return {@code null}. + * {@link Spliterator#trySplit() trySplit} always return {@code null}. * * @return an empty spliterator * @since 1.8 diff -r c9ac54d4acb4 -r e4003d3dc465 jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java --- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java Tue Jul 25 14:07:47 2017 -0700 +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java Thu Jul 27 12:36:49 2017 -0700 @@ -74,31 +74,28 @@ * *
Core and maximum pool sizes
* - *
- * A {@code ThreadPoolExecutor} will automatically adjust the + *
A {@code ThreadPoolExecutor} will automatically adjust the * pool size (see {@link #getPoolSize}) * according to the bounds set by * corePoolSize (see {@link #getCorePoolSize}) and * maximumPoolSize (see {@link #getMaximumPoolSize}). * * When a new task is submitted in method {@link #execute(Runnable)}, - * and fewer than corePoolSize threads are running, a new thread is + * if 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}.
+ * idle. Else if fewer than maximumPoolSize threads are running, a + * new thread will be created to handle the request 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}. * *
On-demand construction
* - *
- * By default, even core threads are initially created and + *
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 @@ -106,8 +103,7 @@ * *
Creating new threads
* - *
- * New threads are created using a {@link ThreadFactory}. If not + *
New threads are created using a {@link ThreadFactory}. If not * otherwise specified, a {@link Executors#defaultThreadFactory} is * used, that creates threads to all be in the same {@link * ThreadGroup} and with the same {@code NORM_PRIORITY} priority and @@ -124,8 +120,7 @@ * *
Keep-alive times
* - *
- * If the pool currently has more than corePoolSize threads, + *
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(TimeUnit)}). * This provides a means of reducing resource consumption when the @@ -142,8 +137,7 @@ * *
Queuing
* - *
- * Any {@link BlockingQueue} may be used to transfer and hold + *
Any {@link BlockingQueue} may be used to transfer and hold * submitted tasks. The use of this queue interacts with pool sizing: * *