feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
307
jdkSrc/jdk8/java/util/concurrent/AbstractExecutorService.java
Normal file
307
jdkSrc/jdk8/java/util/concurrent/AbstractExecutorService.java
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Provides default implementations of {@link ExecutorService}
|
||||
* 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 {@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
|
||||
* that customizes {@link ThreadPoolExecutor} to use
|
||||
* a {@code CustomTask} class instead of the default {@code FutureTask}:
|
||||
* <pre> {@code
|
||||
* public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
|
||||
*
|
||||
* static class CustomTask<V> implements RunnableFuture<V> {...}
|
||||
*
|
||||
* protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
|
||||
* return new CustomTask<V>(c);
|
||||
* }
|
||||
* protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
|
||||
* return new CustomTask<V>(r, v);
|
||||
* }
|
||||
* // ... add constructors, etc.
|
||||
* }}</pre>
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public abstract class AbstractExecutorService implements ExecutorService {
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param <T> the type of the given value
|
||||
* @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
|
||||
* @since 1.6
|
||||
*/
|
||||
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
|
||||
return new FutureTask<T>(runnable, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code RunnableFuture} for the given callable task.
|
||||
*
|
||||
* @param callable the callable task being wrapped
|
||||
* @param <T> the type of the callable's result
|
||||
* @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
|
||||
* @since 1.6
|
||||
*/
|
||||
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
|
||||
return new FutureTask<T>(callable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RejectedExecutionException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
*/
|
||||
public Future<?> submit(Runnable task) {
|
||||
if (task == null) throw new NullPointerException();
|
||||
RunnableFuture<Void> ftask = newTaskFor(task, null);
|
||||
execute(ftask);
|
||||
return ftask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RejectedExecutionException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
*/
|
||||
public <T> Future<T> submit(Runnable task, T result) {
|
||||
if (task == null) throw new NullPointerException();
|
||||
RunnableFuture<T> ftask = newTaskFor(task, result);
|
||||
execute(ftask);
|
||||
return ftask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RejectedExecutionException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
*/
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
if (task == null) throw new NullPointerException();
|
||||
RunnableFuture<T> ftask = newTaskFor(task);
|
||||
execute(ftask);
|
||||
return ftask;
|
||||
}
|
||||
|
||||
/**
|
||||
* the main mechanics of invokeAny.
|
||||
*/
|
||||
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
|
||||
boolean timed, long nanos)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
if (tasks == null)
|
||||
throw new NullPointerException();
|
||||
int ntasks = tasks.size();
|
||||
if (ntasks == 0)
|
||||
throw new IllegalArgumentException();
|
||||
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
|
||||
ExecutorCompletionService<T> ecs =
|
||||
new ExecutorCompletionService<T>(this);
|
||||
|
||||
// For efficiency, especially in executors with limited
|
||||
// parallelism, check to see if previously submitted tasks are
|
||||
// done before submitting more of them. This interleaving
|
||||
// plus the exception mechanics account for messiness of main
|
||||
// loop.
|
||||
|
||||
try {
|
||||
// Record exceptions so that if we fail to obtain any
|
||||
// result, we can throw the last exception we got.
|
||||
ExecutionException ee = null;
|
||||
final long deadline = timed ? System.nanoTime() + nanos : 0L;
|
||||
Iterator<? extends Callable<T>> it = tasks.iterator();
|
||||
|
||||
// Start one task for sure; the rest incrementally
|
||||
futures.add(ecs.submit(it.next()));
|
||||
--ntasks;
|
||||
int active = 1;
|
||||
|
||||
for (;;) {
|
||||
Future<T> f = ecs.poll();
|
||||
if (f == null) {
|
||||
if (ntasks > 0) {
|
||||
--ntasks;
|
||||
futures.add(ecs.submit(it.next()));
|
||||
++active;
|
||||
}
|
||||
else if (active == 0)
|
||||
break;
|
||||
else if (timed) {
|
||||
f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
|
||||
if (f == null)
|
||||
throw new TimeoutException();
|
||||
nanos = deadline - System.nanoTime();
|
||||
}
|
||||
else
|
||||
f = ecs.take();
|
||||
}
|
||||
if (f != null) {
|
||||
--active;
|
||||
try {
|
||||
return f.get();
|
||||
} catch (ExecutionException eex) {
|
||||
ee = eex;
|
||||
} catch (RuntimeException rex) {
|
||||
ee = new ExecutionException(rex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ee == null)
|
||||
ee = new ExecutionException();
|
||||
throw ee;
|
||||
|
||||
} finally {
|
||||
for (int i = 0, size = futures.size(); i < size; i++)
|
||||
futures.get(i).cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
|
||||
throws InterruptedException, ExecutionException {
|
||||
try {
|
||||
return doInvokeAny(tasks, false, 0);
|
||||
} catch (TimeoutException cannotHappen) {
|
||||
assert false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
|
||||
long timeout, TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
return doInvokeAny(tasks, true, unit.toNanos(timeout));
|
||||
}
|
||||
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
|
||||
throws InterruptedException {
|
||||
if (tasks == null)
|
||||
throw new NullPointerException();
|
||||
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
|
||||
boolean done = false;
|
||||
try {
|
||||
for (Callable<T> t : tasks) {
|
||||
RunnableFuture<T> f = newTaskFor(t);
|
||||
futures.add(f);
|
||||
execute(f);
|
||||
}
|
||||
for (int i = 0, size = futures.size(); i < size; i++) {
|
||||
Future<T> f = futures.get(i);
|
||||
if (!f.isDone()) {
|
||||
try {
|
||||
f.get();
|
||||
} catch (CancellationException ignore) {
|
||||
} catch (ExecutionException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
return futures;
|
||||
} finally {
|
||||
if (!done)
|
||||
for (int i = 0, size = futures.size(); i < size; i++)
|
||||
futures.get(i).cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
|
||||
long timeout, TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
if (tasks == null)
|
||||
throw new NullPointerException();
|
||||
long nanos = unit.toNanos(timeout);
|
||||
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.
|
||||
for (int i = 0; i < size; i++) {
|
||||
execute((Runnable)futures.get(i));
|
||||
nanos = deadline - System.nanoTime();
|
||||
if (nanos <= 0L)
|
||||
return futures;
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
Future<T> f = futures.get(i);
|
||||
if (!f.isDone()) {
|
||||
if (nanos <= 0L)
|
||||
return futures;
|
||||
try {
|
||||
f.get(nanos, TimeUnit.NANOSECONDS);
|
||||
} catch (CancellationException ignore) {
|
||||
} catch (ExecutionException ignore) {
|
||||
} catch (TimeoutException toe) {
|
||||
return futures;
|
||||
}
|
||||
nanos = deadline - System.nanoTime();
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
return futures;
|
||||
} finally {
|
||||
if (!done)
|
||||
for (int i = 0, size = futures.size(); i < size; i++)
|
||||
futures.get(i).cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1443
jdkSrc/jdk8/java/util/concurrent/ArrayBlockingQueue.java
Normal file
1443
jdkSrc/jdk8/java/util/concurrent/ArrayBlockingQueue.java
Normal file
File diff suppressed because it is too large
Load Diff
651
jdkSrc/jdk8/java/util/concurrent/BlockingDeque.java
Normal file
651
jdkSrc/jdk8/java/util/concurrent/BlockingDeque.java
Normal file
@@ -0,0 +1,651 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A {@link Deque} that additionally supports blocking operations that wait
|
||||
* for the deque to become non-empty when retrieving an element, and wait for
|
||||
* space to become available in the deque when storing an element.
|
||||
*
|
||||
* <p>{@code BlockingDeque} methods come in four forms, with different ways
|
||||
* of handling operations that cannot be satisfied immediately, but may be
|
||||
* satisfied at some point in the future:
|
||||
* one throws an exception, the second returns a special value (either
|
||||
* {@code null} or {@code false}, depending on the operation), the third
|
||||
* blocks the current thread indefinitely until the operation can succeed,
|
||||
* and the fourth blocks for only a given maximum time limit before giving
|
||||
* up. These methods are summarized in the following table:
|
||||
*
|
||||
* <table BORDER CELLPADDING=3 CELLSPACING=1>
|
||||
* <caption>Summary of BlockingDeque methods</caption>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER COLSPAN = 5> <b>First Element (Head)</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td ALIGN=CENTER><em>Throws exception</em></td>
|
||||
* <td ALIGN=CENTER><em>Special value</em></td>
|
||||
* <td ALIGN=CENTER><em>Blocks</em></td>
|
||||
* <td ALIGN=CENTER><em>Times out</em></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Insert</b></td>
|
||||
* <td>{@link #addFirst addFirst(e)}</td>
|
||||
* <td>{@link #offerFirst(Object) offerFirst(e)}</td>
|
||||
* <td>{@link #putFirst putFirst(e)}</td>
|
||||
* <td>{@link #offerFirst(Object, long, TimeUnit) offerFirst(e, time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Remove</b></td>
|
||||
* <td>{@link #removeFirst removeFirst()}</td>
|
||||
* <td>{@link #pollFirst pollFirst()}</td>
|
||||
* <td>{@link #takeFirst takeFirst()}</td>
|
||||
* <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Examine</b></td>
|
||||
* <td>{@link #getFirst getFirst()}</td>
|
||||
* <td>{@link #peekFirst peekFirst()}</td>
|
||||
* <td><em>not applicable</em></td>
|
||||
* <td><em>not applicable</em></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER COLSPAN = 5> <b>Last Element (Tail)</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td ALIGN=CENTER><em>Throws exception</em></td>
|
||||
* <td ALIGN=CENTER><em>Special value</em></td>
|
||||
* <td ALIGN=CENTER><em>Blocks</em></td>
|
||||
* <td ALIGN=CENTER><em>Times out</em></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Insert</b></td>
|
||||
* <td>{@link #addLast addLast(e)}</td>
|
||||
* <td>{@link #offerLast(Object) offerLast(e)}</td>
|
||||
* <td>{@link #putLast putLast(e)}</td>
|
||||
* <td>{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Remove</b></td>
|
||||
* <td>{@link #removeLast() removeLast()}</td>
|
||||
* <td>{@link #pollLast() pollLast()}</td>
|
||||
* <td>{@link #takeLast takeLast()}</td>
|
||||
* <td>{@link #pollLast(long, TimeUnit) pollLast(time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Examine</b></td>
|
||||
* <td>{@link #getLast getLast()}</td>
|
||||
* <td>{@link #peekLast peekLast()}</td>
|
||||
* <td><em>not applicable</em></td>
|
||||
* <td><em>not applicable</em></td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>Like any {@link BlockingQueue}, a {@code BlockingDeque} is thread safe,
|
||||
* does not permit null elements, and may (or may not) be
|
||||
* capacity-constrained.
|
||||
*
|
||||
* <p>A {@code BlockingDeque} implementation may be used directly as a FIFO
|
||||
* {@code BlockingQueue}. The methods inherited from the
|
||||
* {@code BlockingQueue} interface are precisely equivalent to
|
||||
* {@code BlockingDeque} methods as indicated in the following table:
|
||||
*
|
||||
* <table BORDER CELLPADDING=3 CELLSPACING=1>
|
||||
* <caption>Comparison of BlockingQueue and BlockingDeque methods</caption>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER> <b>{@code BlockingQueue} Method</b></td>
|
||||
* <td ALIGN=CENTER> <b>Equivalent {@code BlockingDeque} Method</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER COLSPAN = 2> <b>Insert</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #add(Object) add(e)}</td>
|
||||
* <td>{@link #addLast(Object) addLast(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #offer(Object) offer(e)}</td>
|
||||
* <td>{@link #offerLast(Object) offerLast(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #put(Object) put(e)}</td>
|
||||
* <td>{@link #putLast(Object) putLast(e)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td>
|
||||
* <td>{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER COLSPAN = 2> <b>Remove</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #remove() remove()}</td>
|
||||
* <td>{@link #removeFirst() removeFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #poll() poll()}</td>
|
||||
* <td>{@link #pollFirst() pollFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #take() take()}</td>
|
||||
* <td>{@link #takeFirst() takeFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
|
||||
* <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td ALIGN=CENTER COLSPAN = 2> <b>Examine</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #element() element()}</td>
|
||||
* <td>{@link #getFirst() getFirst()}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>{@link #peek() peek()}</td>
|
||||
* <td>{@link #peekFirst() peekFirst()}</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>Memory consistency effects: As with other concurrent
|
||||
* collections, actions in a thread prior to placing an object into a
|
||||
* {@code BlockingDeque}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* actions subsequent to the access or removal of that element from
|
||||
* the {@code BlockingDeque} in another thread.
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Doug Lea
|
||||
* @param <E> the type of elements held in this collection
|
||||
*/
|
||||
public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
|
||||
/*
|
||||
* We have "diamond" multiple interface inheritance here, and that
|
||||
* introduces ambiguities. Methods might end up with different
|
||||
* specs depending on the branch chosen by javadoc. Thus a lot of
|
||||
* methods specs here are copied from superinterfaces.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque if it is
|
||||
* possible to do so immediately without violating capacity restrictions,
|
||||
* throwing an {@code IllegalStateException} if no space is currently
|
||||
* available. When using a capacity-restricted deque, it is generally
|
||||
* preferable to use {@link #offerFirst(Object) offerFirst}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws IllegalStateException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
void addFirst(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque if it is
|
||||
* possible to do so immediately without violating capacity restrictions,
|
||||
* throwing an {@code IllegalStateException} if no space is currently
|
||||
* available. When using a capacity-restricted deque, it is generally
|
||||
* preferable to use {@link #offerLast(Object) offerLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws IllegalStateException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
void addLast(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque if it is
|
||||
* possible to do so immediately without violating capacity restrictions,
|
||||
* returning {@code true} upon success and {@code false} if no space is
|
||||
* currently available.
|
||||
* When using a capacity-restricted deque, this method is generally
|
||||
* preferable to the {@link #addFirst(Object) addFirst} method, which can
|
||||
* fail to insert an element only by throwing an exception.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
boolean offerFirst(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque if it is
|
||||
* possible to do so immediately without violating capacity restrictions,
|
||||
* returning {@code true} upon success and {@code false} if no space is
|
||||
* currently available.
|
||||
* When using a capacity-restricted deque, this method is generally
|
||||
* preferable to the {@link #addLast(Object) addLast} method, which can
|
||||
* fail to insert an element only by throwing an exception.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
boolean offerLast(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque,
|
||||
* waiting if necessary for space to become available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
void putFirst(E e) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque,
|
||||
* waiting if necessary for space to become available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
void putLast(E e) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque,
|
||||
* waiting up to the specified wait time if necessary for space to
|
||||
* become available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* {@code unit}
|
||||
* @param unit a {@code TimeUnit} determining how to interpret the
|
||||
* {@code timeout} parameter
|
||||
* @return {@code true} if successful, or {@code false} if
|
||||
* the specified waiting time elapses before space is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offerFirst(E e, long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque,
|
||||
* waiting up to the specified wait time if necessary for space to
|
||||
* become available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* {@code unit}
|
||||
* @param unit a {@code TimeUnit} determining how to interpret the
|
||||
* {@code timeout} parameter
|
||||
* @return {@code true} if successful, or {@code false} if
|
||||
* the specified waiting time elapses before space is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offerLast(E e, long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque, waiting
|
||||
* if necessary until an element becomes available.
|
||||
*
|
||||
* @return the head of this deque
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E takeFirst() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque, waiting
|
||||
* if necessary until an element becomes available.
|
||||
*
|
||||
* @return the tail of this deque
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E takeLast() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque, waiting
|
||||
* up to the specified wait time if necessary for an element to
|
||||
* become available.
|
||||
*
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* {@code unit}
|
||||
* @param unit a {@code TimeUnit} determining how to interpret the
|
||||
* {@code timeout} parameter
|
||||
* @return the head of this deque, or {@code null} if the specified
|
||||
* waiting time elapses before an element is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E pollFirst(long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque, waiting
|
||||
* up to the specified wait time if necessary for an element to
|
||||
* become available.
|
||||
*
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* {@code unit}
|
||||
* @param unit a {@code TimeUnit} determining how to interpret the
|
||||
* {@code timeout} parameter
|
||||
* @return the tail of this deque, or {@code null} if the specified
|
||||
* waiting time elapses before an element is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E pollLast(long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of the specified element from this deque.
|
||||
* If the deque does not contain the element, it is unchanged.
|
||||
* More formally, removes the first element {@code e} such that
|
||||
* {@code o.equals(e)} (if such an element exists).
|
||||
* Returns {@code true} if this deque contained the specified element
|
||||
* (or equivalently, if this deque changed as a result of the call).
|
||||
*
|
||||
* @param o element to be removed from this deque, if present
|
||||
* @return {@code true} if an element was removed as a result of this call
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
*/
|
||||
boolean removeFirstOccurrence(Object o);
|
||||
|
||||
/**
|
||||
* Removes the last occurrence of the specified element from this deque.
|
||||
* If the deque does not contain the element, it is unchanged.
|
||||
* More formally, removes the last element {@code e} such that
|
||||
* {@code o.equals(e)} (if such an element exists).
|
||||
* Returns {@code true} if this deque contained the specified element
|
||||
* (or equivalently, if this deque changed as a result of the call).
|
||||
*
|
||||
* @param o element to be removed from this deque, if present
|
||||
* @return {@code true} if an element was removed as a result of this call
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
*/
|
||||
boolean removeLastOccurrence(Object o);
|
||||
|
||||
// *** BlockingQueue methods ***
|
||||
|
||||
/**
|
||||
* Inserts the specified element into the queue represented by this deque
|
||||
* (in other words, at the tail of this deque) if it is possible to do so
|
||||
* immediately without violating capacity restrictions, returning
|
||||
* {@code true} upon success and throwing an
|
||||
* {@code IllegalStateException} if no space is currently available.
|
||||
* When using a capacity-restricted deque, it is generally preferable to
|
||||
* use {@link #offer(Object) offer}.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #addLast(Object) addLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws IllegalStateException {@inheritDoc}
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean add(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element into the queue represented by this deque
|
||||
* (in other words, at the tail of this deque) if it is possible to do so
|
||||
* immediately without violating capacity restrictions, returning
|
||||
* {@code true} upon success and {@code false} if no space is currently
|
||||
* available. When using a capacity-restricted deque, this method is
|
||||
* generally preferable to the {@link #add} method, which can fail to
|
||||
* insert an element only by throwing an exception.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #offerLast(Object) offerLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offer(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element into the queue represented by this deque
|
||||
* (in other words, at the tail of this deque), waiting if necessary for
|
||||
* space to become available.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #putLast(Object) putLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws InterruptedException {@inheritDoc}
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
void put(E e) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Inserts the specified element into the queue represented by this deque
|
||||
* (in other words, at the tail of this deque), waiting up to the
|
||||
* specified wait time if necessary for space to become available.
|
||||
*
|
||||
* <p>This method is equivalent to
|
||||
* {@link #offerLast(Object,long,TimeUnit) offerLast}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @return {@code true} if the element was added to this deque, else
|
||||
* {@code false}
|
||||
* @throws InterruptedException {@inheritDoc}
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this deque
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this deque
|
||||
*/
|
||||
boolean offer(E e, long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* throws an exception if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #removeFirst() removeFirst}.
|
||||
*
|
||||
* @return the head of the queue represented by this deque
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E remove();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of the queue represented by this deque
|
||||
* (in other words, the first element of this deque), or returns
|
||||
* {@code null} if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #pollFirst()}.
|
||||
*
|
||||
* @return the head of this deque, or {@code null} if this deque is empty
|
||||
*/
|
||||
E poll();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of the queue represented by this deque
|
||||
* (in other words, the first element of this deque), waiting if
|
||||
* necessary until an element becomes available.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #takeFirst() takeFirst}.
|
||||
*
|
||||
* @return the head of this deque
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E take() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of the queue represented by this deque
|
||||
* (in other words, the first element of this deque), waiting up to the
|
||||
* specified wait time if necessary for an element to become available.
|
||||
*
|
||||
* <p>This method is equivalent to
|
||||
* {@link #pollFirst(long,TimeUnit) pollFirst}.
|
||||
*
|
||||
* @return the head of this deque, or {@code null} if the
|
||||
* specified waiting time elapses before an element is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E poll(long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* exception if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #getFirst() getFirst}.
|
||||
*
|
||||
* @return the head of this deque
|
||||
* @throws NoSuchElementException if this deque is empty
|
||||
*/
|
||||
E element();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of the queue represented by
|
||||
* this deque (in other words, the first element of this deque), or
|
||||
* returns {@code null} if this deque is empty.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #peekFirst() peekFirst}.
|
||||
*
|
||||
* @return the head of this deque, or {@code null} if this deque is empty
|
||||
*/
|
||||
E peek();
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of the specified element from this deque.
|
||||
* If the deque does not contain the element, it is unchanged.
|
||||
* More formally, removes the first element {@code e} such that
|
||||
* {@code o.equals(e)} (if such an element exists).
|
||||
* Returns {@code true} if this deque contained the specified element
|
||||
* (or equivalently, if this deque changed as a result of the call).
|
||||
*
|
||||
* <p>This method is equivalent to
|
||||
* {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
|
||||
*
|
||||
* @param o element to be removed from this deque, if present
|
||||
* @return {@code true} if this deque changed as a result of the call
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
*/
|
||||
boolean remove(Object o);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this deque contains the specified element.
|
||||
* More formally, returns {@code true} if and only if this deque contains
|
||||
* at least one element {@code e} such that {@code o.equals(e)}.
|
||||
*
|
||||
* @param o object to be checked for containment in this deque
|
||||
* @return {@code true} if this deque contains the specified element
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this deque
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
*/
|
||||
public boolean contains(Object o);
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this deque.
|
||||
*
|
||||
* @return the number of elements in this deque
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this deque in proper sequence.
|
||||
* The elements will be returned in order from first (head) to last (tail).
|
||||
*
|
||||
* @return an iterator over the elements in this deque in proper sequence
|
||||
*/
|
||||
Iterator<E> iterator();
|
||||
|
||||
// *** Stack methods ***
|
||||
|
||||
/**
|
||||
* Pushes an element onto the stack represented by this deque (in other
|
||||
* words, at the head of this deque) if it is possible to do so
|
||||
* immediately without violating capacity restrictions, throwing an
|
||||
* {@code IllegalStateException} if no space is currently available.
|
||||
*
|
||||
* <p>This method is equivalent to {@link #addFirst(Object) addFirst}.
|
||||
*
|
||||
* @throws IllegalStateException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
void push(E e);
|
||||
}
|
||||
376
jdkSrc/jdk8/java/util/concurrent/BlockingQueue.java
Normal file
376
jdkSrc/jdk8/java/util/concurrent/BlockingQueue.java
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
import java.util.Collection;
|
||||
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.
|
||||
*
|
||||
* <p>{@code BlockingQueue} methods come in four forms, with different ways
|
||||
* of handling operations that cannot be satisfied immediately, but may be
|
||||
* satisfied at some point in the future:
|
||||
* one throws an exception, the second returns a special value (either
|
||||
* {@code null} or {@code false}, depending on the operation), the third
|
||||
* blocks the current thread indefinitely until the operation can succeed,
|
||||
* and the fourth blocks for only a given maximum time limit before giving
|
||||
* up. These methods are summarized in the following table:
|
||||
*
|
||||
* <table BORDER CELLPADDING=3 CELLSPACING=1>
|
||||
* <caption>Summary of BlockingQueue methods</caption>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td ALIGN=CENTER><em>Throws exception</em></td>
|
||||
* <td ALIGN=CENTER><em>Special value</em></td>
|
||||
* <td ALIGN=CENTER><em>Blocks</em></td>
|
||||
* <td ALIGN=CENTER><em>Times out</em></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Insert</b></td>
|
||||
* <td>{@link #add add(e)}</td>
|
||||
* <td>{@link #offer offer(e)}</td>
|
||||
* <td>{@link #put put(e)}</td>
|
||||
* <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Remove</b></td>
|
||||
* <td>{@link #remove remove()}</td>
|
||||
* <td>{@link #poll poll()}</td>
|
||||
* <td>{@link #take take()}</td>
|
||||
* <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Examine</b></td>
|
||||
* <td>{@link #element element()}</td>
|
||||
* <td>{@link #peek peek()}</td>
|
||||
* <td><em>not applicable</em></td>
|
||||
* <td><em>not applicable</em></td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>A {@code BlockingQueue} does not accept {@code null} elements.
|
||||
* Implementations throw {@code NullPointerException} on attempts
|
||||
* to {@code add}, {@code put} or {@code offer} a {@code null}. A
|
||||
* {@code null} is used as a sentinel value to indicate failure of
|
||||
* {@code poll} operations.
|
||||
*
|
||||
* <p>A {@code BlockingQueue} may be capacity bounded. At any given
|
||||
* time it may have a {@code remainingCapacity} beyond which no
|
||||
* additional elements can be {@code put} without blocking.
|
||||
* A {@code BlockingQueue} without any intrinsic capacity constraints always
|
||||
* reports a remaining capacity of {@code Integer.MAX_VALUE}.
|
||||
*
|
||||
* <p>{@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
|
||||
* possible to remove an arbitrary element from a queue using
|
||||
* {@code remove(x)}. However, such operations are in general
|
||||
* <em>not</em> performed very efficiently, and are intended for only
|
||||
* occasional use, such as when a queued message is cancelled.
|
||||
*
|
||||
* <p>{@code BlockingQueue} implementations are thread-safe. All
|
||||
* queuing methods achieve their effects atomically using internal
|
||||
* locks or other forms of concurrency control. However, the
|
||||
* <em>bulk</em> Collection operations {@code addAll},
|
||||
* {@code containsAll}, {@code retainAll} and {@code removeAll} are
|
||||
* <em>not</em> necessarily performed atomically unless specified
|
||||
* otherwise in an implementation. So it is possible, for example, for
|
||||
* {@code addAll(c)} to fail (throwing an exception) after adding
|
||||
* only some of the elements in {@code c}.
|
||||
*
|
||||
* <p>A {@code BlockingQueue} does <em>not</em> intrinsically support
|
||||
* any kind of "close" or "shutdown" operation to
|
||||
* indicate that no more items will be added. The needs and usage of
|
||||
* such features tend to be implementation-dependent. For example, a
|
||||
* common tactic is for producers to insert special
|
||||
* <em>end-of-stream</em> or <em>poison</em> objects, that are
|
||||
* interpreted accordingly when taken by consumers.
|
||||
*
|
||||
* <p>
|
||||
* Usage example, based on a typical producer-consumer scenario.
|
||||
* Note that a {@code BlockingQueue} can safely be used with multiple
|
||||
* producers and multiple consumers.
|
||||
* <pre> {@code
|
||||
* class Producer implements Runnable {
|
||||
* private final BlockingQueue queue;
|
||||
* Producer(BlockingQueue q) { queue = q; }
|
||||
* public void run() {
|
||||
* try {
|
||||
* while (true) { queue.put(produce()); }
|
||||
* } catch (InterruptedException ex) { ... handle ...}
|
||||
* }
|
||||
* Object produce() { ... }
|
||||
* }
|
||||
*
|
||||
* class Consumer implements Runnable {
|
||||
* private final BlockingQueue queue;
|
||||
* Consumer(BlockingQueue q) { queue = q; }
|
||||
* public void run() {
|
||||
* try {
|
||||
* while (true) { consume(queue.take()); }
|
||||
* } catch (InterruptedException ex) { ... handle ...}
|
||||
* }
|
||||
* void consume(Object x) { ... }
|
||||
* }
|
||||
*
|
||||
* class Setup {
|
||||
* void main() {
|
||||
* BlockingQueue q = new SomeQueueImplementation();
|
||||
* Producer p = new Producer(q);
|
||||
* Consumer c1 = new Consumer(q);
|
||||
* Consumer c2 = new Consumer(q);
|
||||
* new Thread(p).start();
|
||||
* new Thread(c1).start();
|
||||
* new Thread(c2).start();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>Memory consistency effects: As with other concurrent
|
||||
* collections, actions in a thread prior to placing an object into a
|
||||
* {@code BlockingQueue}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* actions subsequent to the access or removal of that element from
|
||||
* the {@code BlockingQueue} in another thread.
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <E> the type of elements held in this collection
|
||||
*/
|
||||
public interface BlockingQueue<E> extends Queue<E> {
|
||||
/**
|
||||
* Inserts the specified element into this queue if it is possible to do
|
||||
* so immediately without violating capacity restrictions, returning
|
||||
* {@code true} upon success and throwing an
|
||||
* {@code IllegalStateException} if no space is currently available.
|
||||
* When using a capacity-restricted queue, it is generally preferable to
|
||||
* use {@link #offer(Object) offer}.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @return {@code true} (as specified by {@link Collection#add})
|
||||
* @throws IllegalStateException if the element cannot be added at this
|
||||
* time due to capacity restrictions
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this queue
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this queue
|
||||
*/
|
||||
boolean add(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this queue if it is possible to do
|
||||
* so immediately without violating capacity restrictions, returning
|
||||
* {@code true} upon success and {@code false} if no space is currently
|
||||
* available. When using a capacity-restricted queue, this method is
|
||||
* generally preferable to {@link #add}, which can fail to insert an
|
||||
* element only by throwing an exception.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @return {@code true} if the element was added to this queue, else
|
||||
* {@code false}
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this queue
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this queue
|
||||
*/
|
||||
boolean offer(E e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this queue, waiting if necessary
|
||||
* for space to become available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this queue
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this queue
|
||||
*/
|
||||
void put(E e) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this queue, waiting up to the
|
||||
* specified wait time if necessary for space to become available.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* {@code unit}
|
||||
* @param unit a {@code TimeUnit} determining how to interpret the
|
||||
* {@code timeout} parameter
|
||||
* @return {@code true} if successful, or {@code false} if
|
||||
* the specified waiting time elapses before space is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this queue
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this queue
|
||||
*/
|
||||
boolean offer(E e, long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue, waiting if necessary
|
||||
* until an element becomes available.
|
||||
*
|
||||
* @return the head of this queue
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E take() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue, waiting up to the
|
||||
* specified wait time if necessary for an element to become available.
|
||||
*
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* {@code unit}
|
||||
* @param unit a {@code TimeUnit} determining how to interpret the
|
||||
* {@code timeout} parameter
|
||||
* @return the head of this queue, or {@code null} if the
|
||||
* specified waiting time elapses before an element is available
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
E poll(long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Returns the number of additional elements that this queue can ideally
|
||||
* (in the absence of memory or resource constraints) accept without
|
||||
* blocking, or {@code Integer.MAX_VALUE} if there is no intrinsic
|
||||
* limit.
|
||||
*
|
||||
* <p>Note that you <em>cannot</em> always tell if an attempt to insert
|
||||
* an element will succeed by inspecting {@code remainingCapacity}
|
||||
* because it may be the case that another thread is about to
|
||||
* insert or remove an element.
|
||||
*
|
||||
* @return the remaining capacity
|
||||
*/
|
||||
int remainingCapacity();
|
||||
|
||||
/**
|
||||
* Removes a single instance of the specified element from this queue,
|
||||
* if it is present. More formally, removes an element {@code e} such
|
||||
* that {@code o.equals(e)}, if this queue contains one or more such
|
||||
* elements.
|
||||
* Returns {@code true} if this queue contained the specified element
|
||||
* (or equivalently, if this queue changed as a result of the call).
|
||||
*
|
||||
* @param o element to be removed from this queue, if present
|
||||
* @return {@code true} if this queue changed as a result of the call
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this queue
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
*/
|
||||
boolean remove(Object o);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this queue contains the specified element.
|
||||
* More formally, returns {@code true} if and only if this queue contains
|
||||
* at least one element {@code e} such that {@code o.equals(e)}.
|
||||
*
|
||||
* @param o object to be checked for containment in this queue
|
||||
* @return {@code true} if this queue contains the specified element
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* is incompatible with this queue
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
*/
|
||||
public boolean contains(Object o);
|
||||
|
||||
/**
|
||||
* Removes all available elements from this queue and adds them
|
||||
* to the given collection. This operation may be more
|
||||
* efficient than repeatedly polling this queue. A failure
|
||||
* encountered while attempting to add elements to
|
||||
* collection {@code c} may result in elements being in neither,
|
||||
* either or both collections when the associated exception is
|
||||
* thrown. Attempts to drain a queue to itself result in
|
||||
* {@code IllegalArgumentException}. Further, the behavior of
|
||||
* this operation is undefined if the specified collection is
|
||||
* modified while the operation is in progress.
|
||||
*
|
||||
* @param c the collection to transfer elements into
|
||||
* @return the number of elements transferred
|
||||
* @throws UnsupportedOperationException if addition of elements
|
||||
* is not supported by the specified collection
|
||||
* @throws ClassCastException if the class of an element of this queue
|
||||
* prevents it from being added to the specified collection
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
* @throws IllegalArgumentException if the specified collection is this
|
||||
* queue, or some property of an element of this queue prevents
|
||||
* it from being added to the specified collection
|
||||
*/
|
||||
int drainTo(Collection<? super E> c);
|
||||
|
||||
/**
|
||||
* Removes at most the given number of available elements from
|
||||
* this queue and adds them to the given collection. A failure
|
||||
* encountered while attempting to add elements to
|
||||
* collection {@code c} may result in elements being in neither,
|
||||
* either or both collections when the associated exception is
|
||||
* thrown. Attempts to drain a queue to itself result in
|
||||
* {@code IllegalArgumentException}. Further, the behavior of
|
||||
* this operation is undefined if the specified collection is
|
||||
* modified while the operation is in progress.
|
||||
*
|
||||
* @param c the collection to transfer elements into
|
||||
* @param maxElements the maximum number of elements to transfer
|
||||
* @return the number of elements transferred
|
||||
* @throws UnsupportedOperationException if addition of elements
|
||||
* is not supported by the specified collection
|
||||
* @throws ClassCastException if the class of an element of this queue
|
||||
* prevents it from being added to the specified collection
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
* @throws IllegalArgumentException if the specified collection is this
|
||||
* queue, or some property of an element of this queue prevents
|
||||
* it from being added to the specified collection
|
||||
*/
|
||||
int drainTo(Collection<? super E> c, int maxElements);
|
||||
}
|
||||
66
jdkSrc/jdk8/java/util/concurrent/BrokenBarrierException.java
Normal file
66
jdkSrc/jdk8/java/util/concurrent/BrokenBarrierException.java
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* Exception thrown when a thread tries to wait upon a barrier that is
|
||||
* in a broken state, or which enters the broken state while the thread
|
||||
* is waiting.
|
||||
*
|
||||
* @see CyclicBarrier
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class BrokenBarrierException extends Exception {
|
||||
private static final long serialVersionUID = 7117394618823254244L;
|
||||
|
||||
/**
|
||||
* Constructs a {@code BrokenBarrierException} with no specified detail
|
||||
* message.
|
||||
*/
|
||||
public BrokenBarrierException() {}
|
||||
|
||||
/**
|
||||
* Constructs a {@code BrokenBarrierException} with the specified
|
||||
* detail message.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public BrokenBarrierException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
66
jdkSrc/jdk8/java/util/concurrent/Callable.java
Normal file
66
jdkSrc/jdk8/java/util/concurrent/Callable.java
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A task that returns a result and may throw an exception.
|
||||
* Implementors define a single method with no arguments called
|
||||
* {@code call}.
|
||||
*
|
||||
* <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
|
||||
* {@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 {@code Callable} classes.
|
||||
*
|
||||
* @see Executor
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <V> the result type of method {@code call}
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Callable<V> {
|
||||
/**
|
||||
* Computes a result, or throws an exception if unable to do so.
|
||||
*
|
||||
* @return computed result
|
||||
* @throws Exception if unable to compute a result
|
||||
*/
|
||||
V call() throws Exception;
|
||||
}
|
||||
63
jdkSrc/jdk8/java/util/concurrent/CancellationException.java
Normal file
63
jdkSrc/jdk8/java/util/concurrent/CancellationException.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* Exception indicating that the result of a value-producing task,
|
||||
* such as a {@link FutureTask}, cannot be retrieved because the task
|
||||
* was cancelled.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class CancellationException extends IllegalStateException {
|
||||
private static final long serialVersionUID = -9202173006928992231L;
|
||||
|
||||
/**
|
||||
* Constructs a {@code CancellationException} with no detail message.
|
||||
*/
|
||||
public CancellationException() {}
|
||||
|
||||
/**
|
||||
* Constructs a {@code CancellationException} with the specified detail
|
||||
* message.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public CancellationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
2398
jdkSrc/jdk8/java/util/concurrent/CompletableFuture.java
Normal file
2398
jdkSrc/jdk8/java/util/concurrent/CompletableFuture.java
Normal file
File diff suppressed because it is too large
Load Diff
90
jdkSrc/jdk8/java/util/concurrent/CompletionException.java
Normal file
90
jdkSrc/jdk8/java/util/concurrent/CompletionException.java
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* Exception thrown when an error or other exception is encountered
|
||||
* in the course of completing a result or task.
|
||||
*
|
||||
* @since 1.8
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class CompletionException extends RuntimeException {
|
||||
private static final long serialVersionUID = 7830266012832686185L;
|
||||
|
||||
/**
|
||||
* Constructs a {@code CompletionException} with no detail message.
|
||||
* The cause is not initialized, and may subsequently be
|
||||
* initialized by a call to {@link #initCause(Throwable) initCause}.
|
||||
*/
|
||||
protected CompletionException() { }
|
||||
|
||||
/**
|
||||
* Constructs a {@code CompletionException} with the specified detail
|
||||
* message. The cause is not initialized, and may subsequently be
|
||||
* initialized by a call to {@link #initCause(Throwable) initCause}.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
protected CompletionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@code CompletionException} with the specified detail
|
||||
* message and cause.
|
||||
*
|
||||
* @param message the detail message
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link #getCause()} method)
|
||||
*/
|
||||
public CompletionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@code CompletionException} 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}).
|
||||
*
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link #getCause()} method)
|
||||
*/
|
||||
public CompletionException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
124
jdkSrc/jdk8/java/util/concurrent/CompletionService.java
Normal file
124
jdkSrc/jdk8/java/util/concurrent/CompletionService.java
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A service that decouples the production of new asynchronous tasks
|
||||
* from the consumption of the results of completed tasks. Producers
|
||||
* {@code submit} tasks for execution. Consumers {@code take}
|
||||
* completed tasks and process their results in the order they
|
||||
* 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 {@code CompletionService} relies on a separate
|
||||
* {@link Executor} to actually execute the tasks, in which case the
|
||||
* {@code CompletionService} only manages an internal completion
|
||||
* queue. The {@link ExecutorCompletionService} class provides an
|
||||
* implementation of this approach.
|
||||
*
|
||||
* <p>Memory consistency effects: Actions in a thread prior to
|
||||
* submitting a task to a {@code CompletionService}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* actions taken by that task, which in turn <i>happen-before</i>
|
||||
* actions following a successful return from the corresponding {@code take()}.
|
||||
*/
|
||||
public interface CompletionService<V> {
|
||||
/**
|
||||
* Submits a value-returning task for execution and returns a Future
|
||||
* representing the pending results of the task. Upon completion,
|
||||
* this task may be taken or polled.
|
||||
*
|
||||
* @param task the task to submit
|
||||
* @return a Future representing pending completion of the task
|
||||
* @throws RejectedExecutionException if the task cannot be
|
||||
* scheduled for execution
|
||||
* @throws NullPointerException if the task is null
|
||||
*/
|
||||
Future<V> submit(Callable<V> task);
|
||||
|
||||
/**
|
||||
* Submits a Runnable task for execution and returns a Future
|
||||
* representing that task. Upon completion, this task may be
|
||||
* taken or polled.
|
||||
*
|
||||
* @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 {@code get()} method will return the given
|
||||
* result value upon completion
|
||||
* @throws RejectedExecutionException if the task cannot be
|
||||
* scheduled for execution
|
||||
* @throws NullPointerException if the task is null
|
||||
*/
|
||||
Future<V> submit(Runnable task, V result);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the Future representing the next
|
||||
* completed task, waiting if none are yet present.
|
||||
*
|
||||
* @return the Future representing the next completed task
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
Future<V> take() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the Future representing the next
|
||||
* completed task, or {@code null} if none are present.
|
||||
*
|
||||
* @return the Future representing the next completed task, or
|
||||
* {@code null} if none are present
|
||||
*/
|
||||
Future<V> poll();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the Future representing the next
|
||||
* completed task, waiting if necessary up to the specified wait
|
||||
* time if none are yet present.
|
||||
*
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* {@code unit}
|
||||
* @param unit a {@code TimeUnit} determining how to interpret the
|
||||
* {@code timeout} parameter
|
||||
* @return the Future representing the next completed task or
|
||||
* {@code null} if the specified waiting time elapses
|
||||
* before one is present
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;
|
||||
}
|
||||
780
jdkSrc/jdk8/java/util/concurrent/CompletionStage.java
Normal file
780
jdkSrc/jdk8/java/util/concurrent/CompletionStage.java
Normal file
@@ -0,0 +1,780 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* A stage of a possibly asynchronous computation, that performs an
|
||||
* action or computes a value when another CompletionStage completes.
|
||||
* A stage completes upon termination of its computation, but this may
|
||||
* in turn trigger other dependent stages. The functionality defined
|
||||
* in this interface takes only a few basic forms, which expand out to
|
||||
* a larger set of methods to capture a range of usage styles: <ul>
|
||||
*
|
||||
* <li>The computation performed by a stage may be expressed as a
|
||||
* Function, Consumer, or Runnable (using methods with names including
|
||||
* <em>apply</em>, <em>accept</em>, or <em>run</em>, respectively)
|
||||
* depending on whether it requires arguments and/or produces results.
|
||||
* For example, {@code stage.thenApply(x -> square(x)).thenAccept(x ->
|
||||
* System.out.print(x)).thenRun(() -> System.out.println())}. An
|
||||
* additional form (<em>compose</em>) applies functions of stages
|
||||
* themselves, rather than their results. </li>
|
||||
*
|
||||
* <li> One stage's execution may be triggered by completion of a
|
||||
* single stage, or both of two stages, or either of two stages.
|
||||
* Dependencies on a single stage are arranged using methods with
|
||||
* prefix <em>then</em>. Those triggered by completion of
|
||||
* <em>both</em> of two stages may <em>combine</em> their results or
|
||||
* effects, using correspondingly named methods. Those triggered by
|
||||
* <em>either</em> of two stages make no guarantees about which of the
|
||||
* results or effects are used for the dependent stage's
|
||||
* computation.</li>
|
||||
*
|
||||
* <li> Dependencies among stages control the triggering of
|
||||
* computations, but do not otherwise guarantee any particular
|
||||
* ordering. Additionally, execution of a new stage's computations may
|
||||
* be arranged in any of three ways: default execution, default
|
||||
* asynchronous execution (using methods with suffix <em>async</em>
|
||||
* that employ the stage's default asynchronous execution facility),
|
||||
* or custom (via a supplied {@link Executor}). The execution
|
||||
* properties of default and async modes are specified by
|
||||
* CompletionStage implementations, not this interface. Methods with
|
||||
* explicit Executor arguments may have arbitrary execution
|
||||
* properties, and might not even support concurrent execution, but
|
||||
* are arranged for processing in a way that accommodates asynchrony.
|
||||
*
|
||||
* <li> Two method forms support processing whether the triggering
|
||||
* stage completed normally or exceptionally: Method {@link
|
||||
* #whenComplete whenComplete} allows injection of an action
|
||||
* regardless of outcome, otherwise preserving the outcome in its
|
||||
* completion. Method {@link #handle handle} additionally allows the
|
||||
* stage to compute a replacement result that may enable further
|
||||
* processing by other dependent stages. In all other cases, if a
|
||||
* stage's computation terminates abruptly with an (unchecked)
|
||||
* exception or error, then all dependent stages requiring its
|
||||
* completion complete exceptionally as well, with a {@link
|
||||
* CompletionException} holding the exception as its cause. If a
|
||||
* stage is dependent on <em>both</em> of two stages, and both
|
||||
* complete exceptionally, then the CompletionException may correspond
|
||||
* to either one of these exceptions. If a stage is dependent on
|
||||
* <em>either</em> of two others, and only one of them completes
|
||||
* exceptionally, no guarantees are made about whether the dependent
|
||||
* stage completes normally or exceptionally. In the case of method
|
||||
* {@code whenComplete}, when the supplied action itself encounters an
|
||||
* exception, then the stage exceptionally completes with this
|
||||
* exception if not already completed exceptionally.</li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p>All methods adhere to the above triggering, execution, and
|
||||
* exceptional completion specifications (which are not repeated in
|
||||
* individual method specifications). Additionally, while arguments
|
||||
* used to pass a completion result (that is, for parameters of type
|
||||
* {@code T}) for methods accepting them may be null, passing a null
|
||||
* value for any other parameter will result in a {@link
|
||||
* NullPointerException} being thrown.
|
||||
*
|
||||
* <p>This interface does not define methods for initially creating,
|
||||
* forcibly completing normally or exceptionally, probing completion
|
||||
* status or results, or awaiting completion of a stage.
|
||||
* Implementations of CompletionStage may provide means of achieving
|
||||
* such effects, as appropriate. Method {@link #toCompletableFuture}
|
||||
* enables interoperability among different implementations of this
|
||||
* interface by providing a common conversion type.
|
||||
*
|
||||
* @author Doug Lea
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface CompletionStage<T> {
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, is executed with this stage's result as the argument
|
||||
* to the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param fn the function to use to compute the value of
|
||||
* the returned CompletionStage
|
||||
* @param <U> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, is executed using this stage's default asynchronous
|
||||
* execution facility, with this stage's result as the argument to
|
||||
* the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param fn the function to use to compute the value of
|
||||
* the returned CompletionStage
|
||||
* @param <U> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> thenApplyAsync
|
||||
(Function<? super T,? extends U> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, is executed using the supplied Executor, with this
|
||||
* stage's result as the argument to the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param fn the function to use to compute the value of
|
||||
* the returned CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @param <U> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> thenApplyAsync
|
||||
(Function<? super T,? extends U> fn,
|
||||
Executor executor);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, is executed with this stage's result as the argument
|
||||
* to the supplied action.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> thenAccept(Consumer<? super T> action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, is executed using this stage's default asynchronous
|
||||
* execution facility, with this stage's result as the argument to
|
||||
* the supplied action.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, is executed using the supplied Executor, with this
|
||||
* stage's result as the argument to the supplied action.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,
|
||||
Executor executor);
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, executes the given action.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> thenRun(Runnable action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, executes the given action using this stage's default
|
||||
* asynchronous execution facility.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> thenRunAsync(Runnable action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, executes the given action using the supplied Executor.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> thenRunAsync(Runnable action,
|
||||
Executor executor);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this and the other
|
||||
* given stage both complete normally, is executed with the two
|
||||
* results as arguments to the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param fn the function to use to compute the value of
|
||||
* the returned CompletionStage
|
||||
* @param <U> the type of the other CompletionStage's result
|
||||
* @param <V> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U,V> CompletionStage<V> thenCombine
|
||||
(CompletionStage<? extends U> other,
|
||||
BiFunction<? super T,? super U,? extends V> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this and the other
|
||||
* given stage complete normally, is executed using this stage's
|
||||
* default asynchronous execution facility, with the two results
|
||||
* as arguments to the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param fn the function to use to compute the value of
|
||||
* the returned CompletionStage
|
||||
* @param <U> the type of the other CompletionStage's result
|
||||
* @param <V> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U,V> CompletionStage<V> thenCombineAsync
|
||||
(CompletionStage<? extends U> other,
|
||||
BiFunction<? super T,? super U,? extends V> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this and the other
|
||||
* given stage complete normally, is executed using the supplied
|
||||
* executor, with the two results as arguments to the supplied
|
||||
* function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param fn the function to use to compute the value of
|
||||
* the returned CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @param <U> the type of the other CompletionStage's result
|
||||
* @param <V> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U,V> CompletionStage<V> thenCombineAsync
|
||||
(CompletionStage<? extends U> other,
|
||||
BiFunction<? super T,? super U,? extends V> fn,
|
||||
Executor executor);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this and the other
|
||||
* given stage both complete normally, is executed with the two
|
||||
* results as arguments to the supplied action.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @param <U> the type of the other CompletionStage's result
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<Void> thenAcceptBoth
|
||||
(CompletionStage<? extends U> other,
|
||||
BiConsumer<? super T, ? super U> action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this and the other
|
||||
* given stage complete normally, is executed using this stage's
|
||||
* default asynchronous execution facility, with the two results
|
||||
* as arguments to the supplied action.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @param <U> the type of the other CompletionStage's result
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<Void> thenAcceptBothAsync
|
||||
(CompletionStage<? extends U> other,
|
||||
BiConsumer<? super T, ? super U> action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this and the other
|
||||
* given stage complete normally, is executed using the supplied
|
||||
* executor, with the two results as arguments to the supplied
|
||||
* function.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @param <U> the type of the other CompletionStage's result
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<Void> thenAcceptBothAsync
|
||||
(CompletionStage<? extends U> other,
|
||||
BiConsumer<? super T, ? super U> action,
|
||||
Executor executor);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this and the other
|
||||
* given stage both complete normally, executes the given action.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,
|
||||
Runnable action);
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this and the other
|
||||
* given stage complete normally, executes the given action using
|
||||
* this stage's default asynchronous execution facility.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,
|
||||
Runnable action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this and the other
|
||||
* given stage complete normally, executes the given action using
|
||||
* the supplied executor.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,
|
||||
Runnable action,
|
||||
Executor executor);
|
||||
/**
|
||||
* Returns a new CompletionStage that, when either this or the
|
||||
* other given stage complete normally, is executed with the
|
||||
* corresponding result as argument to the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param fn the function to use to compute the value of
|
||||
* the returned CompletionStage
|
||||
* @param <U> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> applyToEither
|
||||
(CompletionStage<? extends T> other,
|
||||
Function<? super T, U> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when either this or the
|
||||
* other given stage complete normally, is executed using this
|
||||
* stage's default asynchronous execution facility, with the
|
||||
* corresponding result as argument to the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param fn the function to use to compute the value of
|
||||
* the returned CompletionStage
|
||||
* @param <U> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> applyToEitherAsync
|
||||
(CompletionStage<? extends T> other,
|
||||
Function<? super T, U> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when either this or the
|
||||
* other given stage complete normally, is executed using the
|
||||
* supplied executor, with the corresponding result as argument to
|
||||
* the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param fn the function to use to compute the value of
|
||||
* the returned CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @param <U> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> applyToEitherAsync
|
||||
(CompletionStage<? extends T> other,
|
||||
Function<? super T, U> fn,
|
||||
Executor executor);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when either this or the
|
||||
* other given stage complete normally, is executed with the
|
||||
* corresponding result as argument to the supplied action.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> acceptEither
|
||||
(CompletionStage<? extends T> other,
|
||||
Consumer<? super T> action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when either this or the
|
||||
* other given stage complete normally, is executed using this
|
||||
* stage's default asynchronous execution facility, with the
|
||||
* corresponding result as argument to the supplied action.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> acceptEitherAsync
|
||||
(CompletionStage<? extends T> other,
|
||||
Consumer<? super T> action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when either this or the
|
||||
* other given stage complete normally, is executed using the
|
||||
* supplied executor, with the corresponding result as argument to
|
||||
* the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> acceptEitherAsync
|
||||
(CompletionStage<? extends T> other,
|
||||
Consumer<? super T> action,
|
||||
Executor executor);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when either this or the
|
||||
* other given stage complete normally, executes the given action.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> runAfterEither(CompletionStage<?> other,
|
||||
Runnable action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when either this or the
|
||||
* other given stage complete normally, executes the given action
|
||||
* using this stage's default asynchronous execution facility.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> runAfterEitherAsync
|
||||
(CompletionStage<?> other,
|
||||
Runnable action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when either this or the
|
||||
* other given stage complete normally, executes the given action
|
||||
* using the supplied executor.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param other the other CompletionStage
|
||||
* @param action the action to perform before completing the
|
||||
* returned CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<Void> runAfterEitherAsync
|
||||
(CompletionStage<?> other,
|
||||
Runnable action,
|
||||
Executor executor);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, is executed with this stage as the argument
|
||||
* to the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param fn the function returning a new CompletionStage
|
||||
* @param <U> the type of the returned CompletionStage's result
|
||||
* @return the CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> thenCompose
|
||||
(Function<? super T, ? extends CompletionStage<U>> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, is executed using this stage's default asynchronous
|
||||
* execution facility, with this stage as the argument to the
|
||||
* supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param fn the function returning a new CompletionStage
|
||||
* @param <U> the type of the returned CompletionStage's result
|
||||
* @return the CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> thenComposeAsync
|
||||
(Function<? super T, ? extends CompletionStage<U>> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* normally, is executed using the supplied Executor, with this
|
||||
* stage's result as the argument to the supplied function.
|
||||
*
|
||||
* See the {@link CompletionStage} documentation for rules
|
||||
* covering exceptional completion.
|
||||
*
|
||||
* @param fn the function returning a new CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @param <U> the type of the returned CompletionStage's result
|
||||
* @return the CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> thenComposeAsync
|
||||
(Function<? super T, ? extends CompletionStage<U>> fn,
|
||||
Executor executor);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* exceptionally, is executed with this stage's exception as the
|
||||
* argument to the supplied function. Otherwise, if this stage
|
||||
* completes normally, then the returned stage also completes
|
||||
* normally with the same value.
|
||||
*
|
||||
* @param fn the function to use to compute the value of the
|
||||
* returned CompletionStage if this CompletionStage completed
|
||||
* exceptionally
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<T> exceptionally
|
||||
(Function<Throwable, ? extends T> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage with the same result or exception as
|
||||
* this stage, that executes the given action when this stage completes.
|
||||
*
|
||||
* <p>When this stage is complete, the given action is invoked with the
|
||||
* result (or {@code null} if none) and the exception (or {@code null}
|
||||
* if none) of this stage as arguments. The returned stage is completed
|
||||
* when the action returns. If the supplied action itself encounters an
|
||||
* exception, then the returned stage exceptionally completes with this
|
||||
* exception unless this stage also completed exceptionally.
|
||||
*
|
||||
* @param action the action to perform
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<T> whenComplete
|
||||
(BiConsumer<? super T, ? super Throwable> action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage with the same result or exception as
|
||||
* this stage, that executes the given action using this stage's
|
||||
* default asynchronous execution facility when this stage completes.
|
||||
*
|
||||
* <p>When this stage is complete, the given action is invoked with the
|
||||
* result (or {@code null} if none) and the exception (or {@code null}
|
||||
* if none) of this stage as arguments. The returned stage is completed
|
||||
* when the action returns. If the supplied action itself encounters an
|
||||
* exception, then the returned stage exceptionally completes with this
|
||||
* exception unless this stage also completed exceptionally.
|
||||
*
|
||||
* @param action the action to perform
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<T> whenCompleteAsync
|
||||
(BiConsumer<? super T, ? super Throwable> action);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage with the same result or exception as
|
||||
* this stage, that executes the given action using the supplied
|
||||
* Executor when this stage completes.
|
||||
*
|
||||
* <p>When this stage is complete, the given action is invoked with the
|
||||
* result (or {@code null} if none) and the exception (or {@code null}
|
||||
* if none) of this stage as arguments. The returned stage is completed
|
||||
* when the action returns. If the supplied action itself encounters an
|
||||
* exception, then the returned stage exceptionally completes with this
|
||||
* exception unless this stage also completed exceptionally.
|
||||
*
|
||||
* @param action the action to perform
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public CompletionStage<T> whenCompleteAsync
|
||||
(BiConsumer<? super T, ? super Throwable> action,
|
||||
Executor executor);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* either normally or exceptionally, is executed with this stage's
|
||||
* result and exception as arguments to the supplied function.
|
||||
*
|
||||
* <p>When this stage is complete, the given function is invoked
|
||||
* with the result (or {@code null} if none) and the exception (or
|
||||
* {@code null} if none) of this stage as arguments, and the
|
||||
* function's result is used to complete the returned stage.
|
||||
*
|
||||
* @param fn the function to use to compute the value of the
|
||||
* returned CompletionStage
|
||||
* @param <U> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> handle
|
||||
(BiFunction<? super T, Throwable, ? extends U> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* either normally or exceptionally, is executed using this stage's
|
||||
* default asynchronous execution facility, with this stage's
|
||||
* result and exception as arguments to the supplied function.
|
||||
*
|
||||
* <p>When this stage is complete, the given function is invoked
|
||||
* with the result (or {@code null} if none) and the exception (or
|
||||
* {@code null} if none) of this stage as arguments, and the
|
||||
* function's result is used to complete the returned stage.
|
||||
*
|
||||
* @param fn the function to use to compute the value of the
|
||||
* returned CompletionStage
|
||||
* @param <U> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> handleAsync
|
||||
(BiFunction<? super T, Throwable, ? extends U> fn);
|
||||
|
||||
/**
|
||||
* Returns a new CompletionStage that, when this stage completes
|
||||
* either normally or exceptionally, is executed using the
|
||||
* supplied executor, with this stage's result and exception as
|
||||
* arguments to the supplied function.
|
||||
*
|
||||
* <p>When this stage is complete, the given function is invoked
|
||||
* with the result (or {@code null} if none) and the exception (or
|
||||
* {@code null} if none) of this stage as arguments, and the
|
||||
* function's result is used to complete the returned stage.
|
||||
*
|
||||
* @param fn the function to use to compute the value of the
|
||||
* returned CompletionStage
|
||||
* @param executor the executor to use for asynchronous execution
|
||||
* @param <U> the function's return type
|
||||
* @return the new CompletionStage
|
||||
*/
|
||||
public <U> CompletionStage<U> handleAsync
|
||||
(BiFunction<? super T, Throwable, ? extends U> fn,
|
||||
Executor executor);
|
||||
|
||||
/**
|
||||
* Returns a {@link CompletableFuture} maintaining the same
|
||||
* completion properties as this stage. If this stage is already a
|
||||
* CompletableFuture, this method may return this stage itself.
|
||||
* Otherwise, invocation of this method may be equivalent in
|
||||
* effect to {@code thenApply(x -> x)}, but returning an instance
|
||||
* of type {@code CompletableFuture}. A CompletionStage
|
||||
* implementation that does not choose to interoperate with others
|
||||
* may throw {@code UnsupportedOperationException}.
|
||||
*
|
||||
* @return the CompletableFuture
|
||||
* @throws UnsupportedOperationException if this implementation
|
||||
* does not interoperate with CompletableFuture
|
||||
*/
|
||||
public CompletableFuture<T> toCompletableFuture();
|
||||
|
||||
}
|
||||
6310
jdkSrc/jdk8/java/util/concurrent/ConcurrentHashMap.java
Normal file
6310
jdkSrc/jdk8/java/util/concurrent/ConcurrentHashMap.java
Normal file
File diff suppressed because it is too large
Load Diff
1586
jdkSrc/jdk8/java/util/concurrent/ConcurrentLinkedDeque.java
Normal file
1586
jdkSrc/jdk8/java/util/concurrent/ConcurrentLinkedDeque.java
Normal file
File diff suppressed because it is too large
Load Diff
948
jdkSrc/jdk8/java/util/concurrent/ConcurrentLinkedQueue.java
Normal file
948
jdkSrc/jdk8/java/util/concurrent/ConcurrentLinkedQueue.java
Normal file
@@ -0,0 +1,948 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea and Martin Buchholz with assistance from members of
|
||||
* JCP JSR-166 Expert Group and released to the public domain, as explained
|
||||
* at http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
import java.util.AbstractQueue;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Queue;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
|
||||
* This queue orders elements FIFO (first-in-first-out).
|
||||
* The <em>head</em> of the queue is that element that has been on the
|
||||
* queue the longest time.
|
||||
* The <em>tail</em> of the queue is that element that has been on the
|
||||
* queue the shortest time. New elements
|
||||
* are inserted at the tail of the queue, and the queue retrieval
|
||||
* operations obtain elements at the head of the queue.
|
||||
* A {@code ConcurrentLinkedQueue} is an appropriate choice when
|
||||
* many threads will share access to a common collection.
|
||||
* Like most other concurrent collection implementations, this class
|
||||
* does not permit the use of {@code null} elements.
|
||||
*
|
||||
* <p>This implementation employs an efficient <em>non-blocking</em>
|
||||
* algorithm based on one described in <a
|
||||
* href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
|
||||
* Fast, and Practical Non-Blocking and Blocking Concurrent Queue
|
||||
* Algorithms</a> by Maged M. Michael and Michael L. Scott.
|
||||
*
|
||||
* <p>Iterators are <i>weakly consistent</i>, returning elements
|
||||
* reflecting the state of the queue at some point at or since the
|
||||
* creation of the iterator. They do <em>not</em> throw {@link
|
||||
* java.util.ConcurrentModificationException}, and may proceed concurrently
|
||||
* with other operations. Elements contained in the queue since the creation
|
||||
* of the iterator will be returned exactly once.
|
||||
*
|
||||
* <p>Beware that, unlike in most collections, the {@code size} method
|
||||
* is <em>NOT</em> a constant-time operation. Because of the
|
||||
* asynchronous nature of these queues, determining the current number
|
||||
* of elements requires a traversal of the elements, and so may report
|
||||
* inaccurate results if this collection is modified during traversal.
|
||||
* Additionally, the bulk operations {@code addAll},
|
||||
* {@code removeAll}, {@code retainAll}, {@code containsAll},
|
||||
* {@code equals}, and {@code toArray} are <em>not</em> guaranteed
|
||||
* to be performed atomically. For example, an iterator operating
|
||||
* concurrently with an {@code addAll} operation might view only some
|
||||
* of the added elements.
|
||||
*
|
||||
* <p>This class and its iterator implement all of the <em>optional</em>
|
||||
* methods of the {@link Queue} and {@link Iterator} interfaces.
|
||||
*
|
||||
* <p>Memory consistency effects: As with other concurrent
|
||||
* collections, actions in a thread prior to placing an object into a
|
||||
* {@code ConcurrentLinkedQueue}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* actions subsequent to the access or removal of that element from
|
||||
* the {@code ConcurrentLinkedQueue} in another thread.
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <E> the type of elements held in this collection
|
||||
*/
|
||||
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
|
||||
implements Queue<E>, java.io.Serializable {
|
||||
private static final long serialVersionUID = 196745693267521676L;
|
||||
|
||||
/*
|
||||
* This is a modification of the Michael & Scott algorithm,
|
||||
* adapted for a garbage-collected environment, with support for
|
||||
* interior node deletion (to support remove(Object)). For
|
||||
* explanation, read the paper.
|
||||
*
|
||||
* Note that like most non-blocking algorithms in this package,
|
||||
* this implementation relies on the fact that in garbage
|
||||
* collected systems, there is no possibility of ABA problems due
|
||||
* to recycled nodes, so there is no need to use "counted
|
||||
* pointers" or related techniques seen in versions used in
|
||||
* non-GC'ed settings.
|
||||
*
|
||||
* The fundamental invariants are:
|
||||
* - There is exactly one (last) Node with a null next reference,
|
||||
* which is CASed when enqueueing. This last Node can be
|
||||
* reached in O(1) time from tail, but tail is merely an
|
||||
* optimization - it can always be reached in O(N) time from
|
||||
* head as well.
|
||||
* - The elements contained in the queue are the non-null items in
|
||||
* Nodes that are reachable from head. CASing the item
|
||||
* reference of a Node to null atomically removes it from the
|
||||
* queue. Reachability of all elements from head must remain
|
||||
* true even in the case of concurrent modifications that cause
|
||||
* head to advance. A dequeued Node may remain in use
|
||||
* indefinitely due to creation of an Iterator or simply a
|
||||
* poll() that has lost its time slice.
|
||||
*
|
||||
* The above might appear to imply that all Nodes are GC-reachable
|
||||
* from a predecessor dequeued Node. That would cause two problems:
|
||||
* - allow a rogue Iterator to cause unbounded memory retention
|
||||
* - cause cross-generational linking of old Nodes to new Nodes if
|
||||
* a Node was tenured while live, which generational GCs have a
|
||||
* hard time dealing with, causing repeated major collections.
|
||||
* However, only non-deleted Nodes need to be reachable from
|
||||
* dequeued Nodes, and reachability does not necessarily have to
|
||||
* be of the kind understood by the GC. We use the trick of
|
||||
* linking a Node that has just been dequeued to itself. Such a
|
||||
* self-link implicitly means to advance to head.
|
||||
*
|
||||
* Both head and tail are permitted to lag. In fact, failing to
|
||||
* update them every time one could is a significant optimization
|
||||
* (fewer CASes). As with LinkedTransferQueue (see the internal
|
||||
* documentation for that class), we use a slack threshold of two;
|
||||
* that is, we update head/tail when the current pointer appears
|
||||
* to be two or more steps away from the first/last node.
|
||||
*
|
||||
* Since head and tail are updated concurrently and independently,
|
||||
* it is possible for tail to lag behind head (why not)?
|
||||
*
|
||||
* CASing a Node's item reference to null atomically removes the
|
||||
* element from the queue. Iterators skip over Nodes with null
|
||||
* items. Prior implementations of this class had a race between
|
||||
* poll() and remove(Object) where the same element would appear
|
||||
* to be successfully removed by two concurrent operations. The
|
||||
* method remove(Object) also lazily unlinks deleted Nodes, but
|
||||
* this is merely an optimization.
|
||||
*
|
||||
* When constructing a Node (before enqueuing it) we avoid paying
|
||||
* for a volatile write to item by using Unsafe.putObject instead
|
||||
* of a normal write. This allows the cost of enqueue to be
|
||||
* "one-and-a-half" CASes.
|
||||
*
|
||||
* Both head and tail may or may not point to a Node with a
|
||||
* non-null item. If the queue is empty, all items must of course
|
||||
* be null. Upon creation, both head and tail refer to a dummy
|
||||
* Node with null item. Both head and tail are only updated using
|
||||
* CAS, so they never regress, although again this is merely an
|
||||
* optimization.
|
||||
*/
|
||||
|
||||
private static class Node<E> {
|
||||
volatile E item;
|
||||
volatile Node<E> next;
|
||||
|
||||
/**
|
||||
* Constructs a new node. Uses relaxed write because item can
|
||||
* only be seen after publication via casNext.
|
||||
*/
|
||||
Node(E item) {
|
||||
UNSAFE.putObject(this, itemOffset, item);
|
||||
}
|
||||
|
||||
boolean casItem(E cmp, E val) {
|
||||
return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
|
||||
}
|
||||
|
||||
void lazySetNext(Node<E> val) {
|
||||
UNSAFE.putOrderedObject(this, nextOffset, val);
|
||||
}
|
||||
|
||||
boolean casNext(Node<E> cmp, Node<E> val) {
|
||||
return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long itemOffset;
|
||||
private static final long nextOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class<?> k = Node.class;
|
||||
itemOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("item"));
|
||||
nextOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("next"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node from which the first live (non-deleted) node (if any)
|
||||
* can be reached in O(1) time.
|
||||
* Invariants:
|
||||
* - all live nodes are reachable from head via succ()
|
||||
* - head != null
|
||||
* - (tmp = head).next != tmp || tmp != head
|
||||
* Non-invariants:
|
||||
* - head.item may or may not be null.
|
||||
* - it is permitted for tail to lag behind head, that is, for tail
|
||||
* to not be reachable from head!
|
||||
*/
|
||||
private transient volatile Node<E> head;
|
||||
|
||||
/**
|
||||
* A node from which the last node on list (that is, the unique
|
||||
* node with node.next == null) can be reached in O(1) time.
|
||||
* Invariants:
|
||||
* - the last node is always reachable from tail via succ()
|
||||
* - tail != null
|
||||
* Non-invariants:
|
||||
* - tail.item may or may not be null.
|
||||
* - it is permitted for tail to lag behind head, that is, for tail
|
||||
* to not be reachable from head!
|
||||
* - tail.next may or may not be self-pointing to tail.
|
||||
*/
|
||||
private transient volatile Node<E> tail;
|
||||
|
||||
/**
|
||||
* Creates a {@code ConcurrentLinkedQueue} that is initially empty.
|
||||
*/
|
||||
public ConcurrentLinkedQueue() {
|
||||
head = tail = new Node<E>(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code ConcurrentLinkedQueue}
|
||||
* initially containing the elements of the given collection,
|
||||
* added in traversal order of the collection's iterator.
|
||||
*
|
||||
* @param c the collection of elements to initially contain
|
||||
* @throws NullPointerException if the specified collection or any
|
||||
* of its elements are null
|
||||
*/
|
||||
public ConcurrentLinkedQueue(Collection<? extends E> c) {
|
||||
Node<E> h = null, t = null;
|
||||
for (E e : c) {
|
||||
checkNotNull(e);
|
||||
Node<E> newNode = new Node<E>(e);
|
||||
if (h == null)
|
||||
h = t = newNode;
|
||||
else {
|
||||
t.lazySetNext(newNode);
|
||||
t = newNode;
|
||||
}
|
||||
}
|
||||
if (h == null)
|
||||
h = t = new Node<E>(null);
|
||||
head = h;
|
||||
tail = t;
|
||||
}
|
||||
|
||||
// Have to override just to update the javadoc
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the tail of this queue.
|
||||
* As the queue is unbounded, this method will never throw
|
||||
* {@link IllegalStateException} or return {@code false}.
|
||||
*
|
||||
* @return {@code true} (as specified by {@link Collection#add})
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public boolean add(E e) {
|
||||
return offer(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to CAS head to p. If successful, repoint old head to itself
|
||||
* as sentinel for succ(), below.
|
||||
*/
|
||||
final void updateHead(Node<E> h, Node<E> p) {
|
||||
if (h != p && casHead(h, p))
|
||||
h.lazySetNext(h);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the successor of p, or the head node if p.next has been
|
||||
* linked to self, which will only be true if traversing with a
|
||||
* stale pointer that is now off the list.
|
||||
*/
|
||||
final Node<E> succ(Node<E> p) {
|
||||
Node<E> next = p.next;
|
||||
return (p == next) ? head : next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the tail of this queue.
|
||||
* As the queue is unbounded, this method will never return {@code false}.
|
||||
*
|
||||
* @return {@code true} (as specified by {@link Queue#offer})
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public boolean offer(E e) {
|
||||
checkNotNull(e);
|
||||
final Node<E> newNode = new Node<E>(e);
|
||||
|
||||
for (Node<E> t = tail, p = t;;) {
|
||||
Node<E> q = p.next;
|
||||
if (q == null) {
|
||||
// p is last node
|
||||
if (p.casNext(null, newNode)) {
|
||||
// Successful CAS is the linearization point
|
||||
// for e to become an element of this queue,
|
||||
// and for newNode to become "live".
|
||||
if (p != t) // hop two nodes at a time
|
||||
casTail(t, newNode); // Failure is OK.
|
||||
return true;
|
||||
}
|
||||
// Lost CAS race to another thread; re-read next
|
||||
}
|
||||
else if (p == q)
|
||||
// We have fallen off list. If tail is unchanged, it
|
||||
// will also be off-list, in which case we need to
|
||||
// jump to head, from which all live nodes are always
|
||||
// reachable. Else the new tail is a better bet.
|
||||
p = (t != (t = tail)) ? t : head;
|
||||
else
|
||||
// Check for tail updates after two hops.
|
||||
p = (p != t && t != (t = tail)) ? t : q;
|
||||
}
|
||||
}
|
||||
|
||||
public E poll() {
|
||||
restartFromHead:
|
||||
for (;;) {
|
||||
for (Node<E> h = head, p = h, q;;) {
|
||||
E item = p.item;
|
||||
|
||||
if (item != null && p.casItem(item, null)) {
|
||||
// Successful CAS is the linearization point
|
||||
// for item to be removed from this queue.
|
||||
if (p != h) // hop two nodes at a time
|
||||
updateHead(h, ((q = p.next) != null) ? q : p);
|
||||
return item;
|
||||
}
|
||||
else if ((q = p.next) == null) {
|
||||
updateHead(h, p);
|
||||
return null;
|
||||
}
|
||||
else if (p == q)
|
||||
continue restartFromHead;
|
||||
else
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public E peek() {
|
||||
restartFromHead:
|
||||
for (;;) {
|
||||
for (Node<E> h = head, p = h, q;;) {
|
||||
E item = p.item;
|
||||
if (item != null || (q = p.next) == null) {
|
||||
updateHead(h, p);
|
||||
return item;
|
||||
}
|
||||
else if (p == q)
|
||||
continue restartFromHead;
|
||||
else
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first live (non-deleted) node on list, or null if none.
|
||||
* This is yet another variant of poll/peek; here returning the
|
||||
* first node, not element. We could make peek() a wrapper around
|
||||
* first(), but that would cost an extra volatile read of item,
|
||||
* and the need to add a retry loop to deal with the possibility
|
||||
* of losing a race to a concurrent poll().
|
||||
*/
|
||||
Node<E> first() {
|
||||
restartFromHead:
|
||||
for (;;) {
|
||||
for (Node<E> h = head, p = h, q;;) {
|
||||
boolean hasItem = (p.item != null);
|
||||
if (hasItem || (q = p.next) == null) {
|
||||
updateHead(h, p);
|
||||
return hasItem ? p : null;
|
||||
}
|
||||
else if (p == q)
|
||||
continue restartFromHead;
|
||||
else
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this queue contains no elements.
|
||||
*
|
||||
* @return {@code true} if this queue contains no elements
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return first() == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this queue. If this queue
|
||||
* contains more than {@code Integer.MAX_VALUE} elements, returns
|
||||
* {@code Integer.MAX_VALUE}.
|
||||
*
|
||||
* <p>Beware that, unlike in most collections, this method is
|
||||
* <em>NOT</em> a constant-time operation. Because of the
|
||||
* asynchronous nature of these queues, determining the current
|
||||
* number of elements requires an O(n) traversal.
|
||||
* Additionally, if elements are added or removed during execution
|
||||
* of this method, the returned result may be inaccurate. Thus,
|
||||
* this method is typically not very useful in concurrent
|
||||
* applications.
|
||||
*
|
||||
* @return the number of elements in this queue
|
||||
*/
|
||||
public int size() {
|
||||
int count = 0;
|
||||
for (Node<E> p = first(); p != null; p = succ(p))
|
||||
if (p.item != null)
|
||||
// Collection.size() spec says to max out
|
||||
if (++count == Integer.MAX_VALUE)
|
||||
break;
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this queue contains the specified element.
|
||||
* More formally, returns {@code true} if and only if this queue contains
|
||||
* at least one element {@code e} such that {@code o.equals(e)}.
|
||||
*
|
||||
* @param o object to be checked for containment in this queue
|
||||
* @return {@code true} if this queue contains the specified element
|
||||
*/
|
||||
public boolean contains(Object o) {
|
||||
if (o == null) return false;
|
||||
for (Node<E> p = first(); p != null; p = succ(p)) {
|
||||
E item = p.item;
|
||||
if (item != null && o.equals(item))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a single instance of the specified element from this queue,
|
||||
* if it is present. More formally, removes an element {@code e} such
|
||||
* that {@code o.equals(e)}, if this queue contains one or more such
|
||||
* elements.
|
||||
* Returns {@code true} if this queue contained the specified element
|
||||
* (or equivalently, if this queue changed as a result of the call).
|
||||
*
|
||||
* @param o element to be removed from this queue, if present
|
||||
* @return {@code true} if this queue changed as a result of the call
|
||||
*/
|
||||
public boolean remove(Object o) {
|
||||
if (o != null) {
|
||||
Node<E> next, pred = null;
|
||||
for (Node<E> p = first(); p != null; pred = p, p = next) {
|
||||
boolean removed = false;
|
||||
E item = p.item;
|
||||
if (item != null) {
|
||||
if (!o.equals(item)) {
|
||||
next = succ(p);
|
||||
continue;
|
||||
}
|
||||
removed = p.casItem(item, null);
|
||||
}
|
||||
|
||||
next = succ(p);
|
||||
if (pred != null && next != null) // unlink
|
||||
pred.casNext(p, next);
|
||||
if (removed)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends all of the elements in the specified collection to the end of
|
||||
* this queue, in the order that they are returned by the specified
|
||||
* collection's iterator. Attempts to {@code addAll} of a queue to
|
||||
* itself result in {@code IllegalArgumentException}.
|
||||
*
|
||||
* @param c the elements to be inserted into this queue
|
||||
* @return {@code true} if this queue changed as a result of the call
|
||||
* @throws NullPointerException if the specified collection or any
|
||||
* of its elements are null
|
||||
* @throws IllegalArgumentException if the collection is this queue
|
||||
*/
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
if (c == this)
|
||||
// As historically specified in AbstractQueue#addAll
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
// Copy c into a private chain of Nodes
|
||||
Node<E> beginningOfTheEnd = null, last = null;
|
||||
for (E e : c) {
|
||||
checkNotNull(e);
|
||||
Node<E> newNode = new Node<E>(e);
|
||||
if (beginningOfTheEnd == null)
|
||||
beginningOfTheEnd = last = newNode;
|
||||
else {
|
||||
last.lazySetNext(newNode);
|
||||
last = newNode;
|
||||
}
|
||||
}
|
||||
if (beginningOfTheEnd == null)
|
||||
return false;
|
||||
|
||||
// Atomically append the chain at the tail of this collection
|
||||
for (Node<E> t = tail, p = t;;) {
|
||||
Node<E> q = p.next;
|
||||
if (q == null) {
|
||||
// p is last node
|
||||
if (p.casNext(null, beginningOfTheEnd)) {
|
||||
// Successful CAS is the linearization point
|
||||
// for all elements to be added to this queue.
|
||||
if (!casTail(t, last)) {
|
||||
// Try a little harder to update tail,
|
||||
// since we may be adding many elements.
|
||||
t = tail;
|
||||
if (last.next == null)
|
||||
casTail(t, last);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Lost CAS race to another thread; re-read next
|
||||
}
|
||||
else if (p == q)
|
||||
// We have fallen off list. If tail is unchanged, it
|
||||
// will also be off-list, in which case we need to
|
||||
// jump to head, from which all live nodes are always
|
||||
// reachable. Else the new tail is a better bet.
|
||||
p = (t != (t = tail)) ? t : head;
|
||||
else
|
||||
// Check for tail updates after two hops.
|
||||
p = (p != t && t != (t = tail)) ? t : q;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all of the elements in this queue, in
|
||||
* proper sequence.
|
||||
*
|
||||
* <p>The returned array will be "safe" in that no references to it are
|
||||
* maintained by this queue. (In other words, this method must allocate
|
||||
* a new array). The caller is thus free to modify the returned array.
|
||||
*
|
||||
* <p>This method acts as bridge between array-based and collection-based
|
||||
* APIs.
|
||||
*
|
||||
* @return an array containing all of the elements in this queue
|
||||
*/
|
||||
public Object[] toArray() {
|
||||
// Use ArrayList to deal with resizing.
|
||||
ArrayList<E> al = new ArrayList<E>();
|
||||
for (Node<E> p = first(); p != null; p = succ(p)) {
|
||||
E item = p.item;
|
||||
if (item != null)
|
||||
al.add(item);
|
||||
}
|
||||
return al.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all of the elements in this queue, in
|
||||
* proper sequence; the runtime type of the returned array is that of
|
||||
* the specified array. If the queue fits in the specified array, it
|
||||
* is returned therein. Otherwise, a new array is allocated with the
|
||||
* runtime type of the specified array and the size of this queue.
|
||||
*
|
||||
* <p>If this queue fits in the specified array with room to spare
|
||||
* (i.e., the array has more elements than this queue), the element in
|
||||
* the array immediately following the end of the queue is set to
|
||||
* {@code null}.
|
||||
*
|
||||
* <p>Like the {@link #toArray()} method, this method acts as bridge between
|
||||
* array-based and collection-based APIs. Further, this method allows
|
||||
* precise control over the runtime type of the output array, and may,
|
||||
* under certain circumstances, be used to save allocation costs.
|
||||
*
|
||||
* <p>Suppose {@code x} is a queue known to contain only strings.
|
||||
* The following code can be used to dump the queue into a newly
|
||||
* allocated array of {@code String}:
|
||||
*
|
||||
* <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
|
||||
*
|
||||
* Note that {@code toArray(new Object[0])} is identical in function to
|
||||
* {@code toArray()}.
|
||||
*
|
||||
* @param a the array into which the elements of the queue are to
|
||||
* be stored, if it is big enough; otherwise, a new array of the
|
||||
* same runtime type is allocated for this purpose
|
||||
* @return an array containing all of the elements in this queue
|
||||
* @throws ArrayStoreException if the runtime type of the specified array
|
||||
* is not a supertype of the runtime type of every element in
|
||||
* this queue
|
||||
* @throws NullPointerException if the specified array is null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T[] toArray(T[] a) {
|
||||
// try to use sent-in array
|
||||
int k = 0;
|
||||
Node<E> p;
|
||||
for (p = first(); p != null && k < a.length; p = succ(p)) {
|
||||
E item = p.item;
|
||||
if (item != null)
|
||||
a[k++] = (T)item;
|
||||
}
|
||||
if (p == null) {
|
||||
if (k < a.length)
|
||||
a[k] = null;
|
||||
return a;
|
||||
}
|
||||
|
||||
// If won't fit, use ArrayList version
|
||||
ArrayList<E> al = new ArrayList<E>();
|
||||
for (Node<E> q = first(); q != null; q = succ(q)) {
|
||||
E item = q.item;
|
||||
if (item != null)
|
||||
al.add(item);
|
||||
}
|
||||
return al.toArray(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this queue in proper sequence.
|
||||
* The elements will be returned in order from first (head) to last (tail).
|
||||
*
|
||||
* <p>The returned iterator is
|
||||
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
|
||||
*
|
||||
* @return an iterator over the elements in this queue in proper sequence
|
||||
*/
|
||||
public Iterator<E> iterator() {
|
||||
return new Itr();
|
||||
}
|
||||
|
||||
private class Itr implements Iterator<E> {
|
||||
/**
|
||||
* Next node to return item for.
|
||||
*/
|
||||
private Node<E> nextNode;
|
||||
|
||||
/**
|
||||
* nextItem holds on to item fields because once we claim
|
||||
* that an element exists in hasNext(), we must return it in
|
||||
* the following next() call even if it was in the process of
|
||||
* being removed when hasNext() was called.
|
||||
*/
|
||||
private E nextItem;
|
||||
|
||||
/**
|
||||
* Node of the last returned item, to support remove.
|
||||
*/
|
||||
private Node<E> lastRet;
|
||||
|
||||
Itr() {
|
||||
advance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves to next valid node and returns item to return for
|
||||
* next(), or null if no such.
|
||||
*/
|
||||
private E advance() {
|
||||
lastRet = nextNode;
|
||||
E x = nextItem;
|
||||
|
||||
Node<E> pred, p;
|
||||
if (nextNode == null) {
|
||||
p = first();
|
||||
pred = null;
|
||||
} else {
|
||||
pred = nextNode;
|
||||
p = succ(nextNode);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (p == null) {
|
||||
nextNode = null;
|
||||
nextItem = null;
|
||||
return x;
|
||||
}
|
||||
E item = p.item;
|
||||
if (item != null) {
|
||||
nextNode = p;
|
||||
nextItem = item;
|
||||
return x;
|
||||
} else {
|
||||
// skip over nulls
|
||||
Node<E> next = succ(p);
|
||||
if (pred != null && next != null)
|
||||
pred.casNext(p, next);
|
||||
p = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return nextNode != null;
|
||||
}
|
||||
|
||||
public E next() {
|
||||
if (nextNode == null) throw new NoSuchElementException();
|
||||
return advance();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
Node<E> l = lastRet;
|
||||
if (l == null) throw new IllegalStateException();
|
||||
// rely on a future traversal to relink.
|
||||
l.item = null;
|
||||
lastRet = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this queue to a stream (that is, serializes it).
|
||||
*
|
||||
* @param s the stream
|
||||
* @throws java.io.IOException if an I/O error occurs
|
||||
* @serialData All of the elements (each an {@code E}) in
|
||||
* the proper order, followed by a null
|
||||
*/
|
||||
private void writeObject(java.io.ObjectOutputStream s)
|
||||
throws java.io.IOException {
|
||||
|
||||
// Write out any hidden stuff
|
||||
s.defaultWriteObject();
|
||||
|
||||
// Write out all elements in the proper order.
|
||||
for (Node<E> p = first(); p != null; p = succ(p)) {
|
||||
Object item = p.item;
|
||||
if (item != null)
|
||||
s.writeObject(item);
|
||||
}
|
||||
|
||||
// Use trailing null as sentinel
|
||||
s.writeObject(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitutes this queue from a stream (that is, deserializes it).
|
||||
* @param s the stream
|
||||
* @throws ClassNotFoundException if the class of a serialized object
|
||||
* could not be found
|
||||
* @throws java.io.IOException if an I/O error occurs
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
s.defaultReadObject();
|
||||
|
||||
// Read in elements until trailing null sentinel found
|
||||
Node<E> h = null, t = null;
|
||||
Object item;
|
||||
while ((item = s.readObject()) != null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Node<E> newNode = new Node<E>((E) item);
|
||||
if (h == null)
|
||||
h = t = newNode;
|
||||
else {
|
||||
t.lazySetNext(newNode);
|
||||
t = newNode;
|
||||
}
|
||||
}
|
||||
if (h == null)
|
||||
h = t = new Node<E>(null);
|
||||
head = h;
|
||||
tail = t;
|
||||
}
|
||||
|
||||
/** A customized variant of Spliterators.IteratorSpliterator */
|
||||
static final class CLQSpliterator<E> implements Spliterator<E> {
|
||||
static final int MAX_BATCH = 1 << 25; // max batch array size;
|
||||
final ConcurrentLinkedQueue<E> queue;
|
||||
Node<E> current; // current node; null until initialized
|
||||
int batch; // batch size for splits
|
||||
boolean exhausted; // true when no more nodes
|
||||
CLQSpliterator(ConcurrentLinkedQueue<E> queue) {
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
public Spliterator<E> trySplit() {
|
||||
Node<E> p;
|
||||
final ConcurrentLinkedQueue<E> q = this.queue;
|
||||
int b = batch;
|
||||
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
|
||||
if (!exhausted &&
|
||||
((p = current) != null || (p = q.first()) != null) &&
|
||||
p.next != null) {
|
||||
Object[] a = new Object[n];
|
||||
int i = 0;
|
||||
do {
|
||||
if ((a[i] = p.item) != null)
|
||||
++i;
|
||||
if (p == (p = p.next))
|
||||
p = q.first();
|
||||
} while (p != null && i < n);
|
||||
if ((current = p) == null)
|
||||
exhausted = true;
|
||||
if (i > 0) {
|
||||
batch = i;
|
||||
return Spliterators.spliterator
|
||||
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
|
||||
Spliterator.CONCURRENT);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void forEachRemaining(Consumer<? super E> action) {
|
||||
Node<E> p;
|
||||
if (action == null) throw new NullPointerException();
|
||||
final ConcurrentLinkedQueue<E> q = this.queue;
|
||||
if (!exhausted &&
|
||||
((p = current) != null || (p = q.first()) != null)) {
|
||||
exhausted = true;
|
||||
do {
|
||||
E e = p.item;
|
||||
if (p == (p = p.next))
|
||||
p = q.first();
|
||||
if (e != null)
|
||||
action.accept(e);
|
||||
} while (p != null);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tryAdvance(Consumer<? super E> action) {
|
||||
Node<E> p;
|
||||
if (action == null) throw new NullPointerException();
|
||||
final ConcurrentLinkedQueue<E> q = this.queue;
|
||||
if (!exhausted &&
|
||||
((p = current) != null || (p = q.first()) != null)) {
|
||||
E e;
|
||||
do {
|
||||
e = p.item;
|
||||
if (p == (p = p.next))
|
||||
p = q.first();
|
||||
} while (e == null && p != null);
|
||||
if ((current = p) == null)
|
||||
exhausted = true;
|
||||
if (e != null) {
|
||||
action.accept(e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public long estimateSize() { return Long.MAX_VALUE; }
|
||||
|
||||
public int characteristics() {
|
||||
return Spliterator.ORDERED | Spliterator.NONNULL |
|
||||
Spliterator.CONCURRENT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Spliterator} over the elements in this queue.
|
||||
*
|
||||
* <p>The returned spliterator is
|
||||
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
|
||||
*
|
||||
* <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
|
||||
* {@link Spliterator#ORDERED}, and {@link Spliterator#NONNULL}.
|
||||
*
|
||||
* @implNote
|
||||
* The {@code Spliterator} implements {@code trySplit} to permit limited
|
||||
* parallelism.
|
||||
*
|
||||
* @return a {@code Spliterator} over the elements in this queue
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
public Spliterator<E> spliterator() {
|
||||
return new CLQSpliterator<E>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws NullPointerException if argument is null.
|
||||
*
|
||||
* @param v the element
|
||||
*/
|
||||
private static void checkNotNull(Object v) {
|
||||
if (v == null)
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
private boolean casTail(Node<E> cmp, Node<E> val) {
|
||||
return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
|
||||
}
|
||||
|
||||
private boolean casHead(Node<E> cmp, Node<E> val) {
|
||||
return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long headOffset;
|
||||
private static final long tailOffset;
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class<?> k = ConcurrentLinkedQueue.class;
|
||||
headOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("head"));
|
||||
tailOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("tail"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
517
jdkSrc/jdk8/java/util/concurrent/ConcurrentMap.java
Normal file
517
jdkSrc/jdk8/java/util/concurrent/ConcurrentMap.java
Normal file
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A {@link java.util.Map} providing thread safety and atomicity
|
||||
* guarantees.
|
||||
*
|
||||
* <p>Memory consistency effects: As with other concurrent
|
||||
* collections, actions in a thread prior to placing an object into a
|
||||
* {@code ConcurrentMap} as a key or value
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* actions subsequent to the access or removal of that object from
|
||||
* the {@code ConcurrentMap} in another thread.
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <K> the type of keys maintained by this map
|
||||
* @param <V> the type of mapped values
|
||||
*/
|
||||
public interface ConcurrentMap<K, V> extends Map<K, V> {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implNote This implementation assumes that the ConcurrentMap cannot
|
||||
* contain null values and {@code get()} returning null unambiguously means
|
||||
* the key is absent. Implementations which support null values
|
||||
* <strong>must</strong> override this default implementation.
|
||||
*
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
default V getOrDefault(Object key, V defaultValue) {
|
||||
V v;
|
||||
return ((v = get(key)) != null) ? v : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec The default implementation is equivalent to, for this
|
||||
* {@code map}:
|
||||
* <pre> {@code
|
||||
* for ((Map.Entry<K, V> entry : map.entrySet())
|
||||
* action.accept(entry.getKey(), entry.getValue());
|
||||
* }</pre>
|
||||
*
|
||||
* @implNote The default implementation assumes that
|
||||
* {@code IllegalStateException} thrown by {@code getKey()} or
|
||||
* {@code getValue()} indicates that the entry has been removed and cannot
|
||||
* be processed. Operation continues for subsequent entries.
|
||||
*
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
default void forEach(BiConsumer<? super K, ? super V> action) {
|
||||
Objects.requireNonNull(action);
|
||||
for (Map.Entry<K, V> entry : entrySet()) {
|
||||
K k;
|
||||
V v;
|
||||
try {
|
||||
k = entry.getKey();
|
||||
v = entry.getValue();
|
||||
} catch(IllegalStateException ise) {
|
||||
// this usually means the entry is no longer in the map.
|
||||
continue;
|
||||
}
|
||||
action.accept(k, v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated
|
||||
* with a value, associate it with the given value.
|
||||
* This is equivalent to
|
||||
* <pre> {@code
|
||||
* if (!map.containsKey(key))
|
||||
* return map.put(key, value);
|
||||
* else
|
||||
* return map.get(key);
|
||||
* }</pre>
|
||||
*
|
||||
* except that the action is performed atomically.
|
||||
*
|
||||
* @implNote This implementation intentionally re-abstracts the
|
||||
* inappropriate default provided in {@code Map}.
|
||||
*
|
||||
* @param key key with which the specified value is to be associated
|
||||
* @param value value to be associated with the specified key
|
||||
* @return the previous value associated with the specified key, or
|
||||
* {@code null} if there was no mapping for the key.
|
||||
* (A {@code null} return can also indicate that the map
|
||||
* previously associated {@code null} with the key,
|
||||
* if the implementation supports null values.)
|
||||
* @throws UnsupportedOperationException if the {@code put} operation
|
||||
* is not supported by this map
|
||||
* @throws ClassCastException if the class of the specified key or value
|
||||
* prevents it from being stored in this map
|
||||
* @throws NullPointerException if the specified key or value is null,
|
||||
* and this map does not permit null keys or values
|
||||
* @throws IllegalArgumentException if some property of the specified key
|
||||
* or value prevents it from being stored in this map
|
||||
*/
|
||||
V putIfAbsent(K key, V value);
|
||||
|
||||
/**
|
||||
* Removes the entry for a key only if currently mapped to a given value.
|
||||
* This is equivalent to
|
||||
* <pre> {@code
|
||||
* if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
|
||||
* map.remove(key);
|
||||
* return true;
|
||||
* } else
|
||||
* return false;
|
||||
* }</pre>
|
||||
*
|
||||
* except that the action is performed atomically.
|
||||
*
|
||||
* @implNote This implementation intentionally re-abstracts the
|
||||
* inappropriate default provided in {@code Map}.
|
||||
*
|
||||
* @param key key with which the specified value is associated
|
||||
* @param value value expected to be associated with the specified key
|
||||
* @return {@code true} if the value was removed
|
||||
* @throws UnsupportedOperationException if the {@code remove} operation
|
||||
* is not supported by this map
|
||||
* @throws ClassCastException if the key or value is of an inappropriate
|
||||
* type for this map
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
* @throws NullPointerException if the specified key or value is null,
|
||||
* and this map does not permit null keys or values
|
||||
* (<a href="../Collection.html#optional-restrictions">optional</a>)
|
||||
*/
|
||||
boolean remove(Object key, Object value);
|
||||
|
||||
/**
|
||||
* Replaces the entry for a key only if currently mapped to a given value.
|
||||
* This is equivalent to
|
||||
* <pre> {@code
|
||||
* if (map.containsKey(key) && Objects.equals(map.get(key), oldValue)) {
|
||||
* map.put(key, newValue);
|
||||
* return true;
|
||||
* } else
|
||||
* return false;
|
||||
* }</pre>
|
||||
*
|
||||
* except that the action is performed atomically.
|
||||
*
|
||||
* @implNote This implementation intentionally re-abstracts the
|
||||
* inappropriate default provided in {@code Map}.
|
||||
*
|
||||
* @param key key with which the specified value is associated
|
||||
* @param oldValue value expected to be associated with the specified key
|
||||
* @param newValue value to be associated with the specified key
|
||||
* @return {@code true} if the value was replaced
|
||||
* @throws UnsupportedOperationException if the {@code put} operation
|
||||
* is not supported by this map
|
||||
* @throws ClassCastException if the class of a specified key or value
|
||||
* prevents it from being stored in this map
|
||||
* @throws NullPointerException if a specified key or value is null,
|
||||
* and this map does not permit null keys or values
|
||||
* @throws IllegalArgumentException if some property of a specified key
|
||||
* or value prevents it from being stored in this map
|
||||
*/
|
||||
boolean replace(K key, V oldValue, V newValue);
|
||||
|
||||
/**
|
||||
* Replaces the entry for a key only if currently mapped to some value.
|
||||
* This is equivalent to
|
||||
* <pre> {@code
|
||||
* if (map.containsKey(key)) {
|
||||
* return map.put(key, value);
|
||||
* } else
|
||||
* return null;
|
||||
* }</pre>
|
||||
*
|
||||
* except that the action is performed atomically.
|
||||
*
|
||||
* @implNote This implementation intentionally re-abstracts the
|
||||
* inappropriate default provided in {@code Map}.
|
||||
*
|
||||
* @param key key with which the specified value is associated
|
||||
* @param value value to be associated with the specified key
|
||||
* @return the previous value associated with the specified key, or
|
||||
* {@code null} if there was no mapping for the key.
|
||||
* (A {@code null} return can also indicate that the map
|
||||
* previously associated {@code null} with the key,
|
||||
* if the implementation supports null values.)
|
||||
* @throws UnsupportedOperationException if the {@code put} operation
|
||||
* is not supported by this map
|
||||
* @throws ClassCastException if the class of the specified key or value
|
||||
* prevents it from being stored in this map
|
||||
* @throws NullPointerException if the specified key or value is null,
|
||||
* and this map does not permit null keys or values
|
||||
* @throws IllegalArgumentException if some property of the specified key
|
||||
* or value prevents it from being stored in this map
|
||||
*/
|
||||
V replace(K key, V value);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec
|
||||
* <p>The default implementation is equivalent to, for this {@code map}:
|
||||
* <pre> {@code
|
||||
* for ((Map.Entry<K, V> entry : map.entrySet())
|
||||
* do {
|
||||
* K k = entry.getKey();
|
||||
* V v = entry.getValue();
|
||||
* } while(!replace(k, v, function.apply(k, v)));
|
||||
* }</pre>
|
||||
*
|
||||
* The default implementation may retry these steps when multiple
|
||||
* threads attempt updates including potentially calling the function
|
||||
* repeatedly for a given key.
|
||||
*
|
||||
* <p>This implementation assumes that the ConcurrentMap cannot contain null
|
||||
* values and {@code get()} returning null unambiguously means the key is
|
||||
* absent. Implementations which support null values <strong>must</strong>
|
||||
* override this default implementation.
|
||||
*
|
||||
* @throws UnsupportedOperationException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
|
||||
Objects.requireNonNull(function);
|
||||
forEach((k,v) -> {
|
||||
while(!replace(k, v, function.apply(k, v))) {
|
||||
// v changed or k is gone
|
||||
if ( (v = get(k)) == null) {
|
||||
// k is no longer in the map.
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation is equivalent to the following steps for this
|
||||
* {@code map}, then returning the current value or {@code null} if now
|
||||
* absent:
|
||||
*
|
||||
* <pre> {@code
|
||||
* if (map.get(key) == null) {
|
||||
* V newValue = mappingFunction.apply(key);
|
||||
* if (newValue != null)
|
||||
* return map.putIfAbsent(key, newValue);
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* The default implementation may retry these steps when multiple
|
||||
* threads attempt updates including potentially calling the mapping
|
||||
* function multiple times.
|
||||
*
|
||||
* <p>This implementation assumes that the ConcurrentMap cannot contain null
|
||||
* values and {@code get()} returning null unambiguously means the key is
|
||||
* absent. Implementations which support null values <strong>must</strong>
|
||||
* override this default implementation.
|
||||
*
|
||||
* @throws UnsupportedOperationException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
default V computeIfAbsent(K key,
|
||||
Function<? super K, ? extends V> mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
V v, newValue;
|
||||
return ((v = get(key)) == null &&
|
||||
(newValue = mappingFunction.apply(key)) != null &&
|
||||
(v = putIfAbsent(key, newValue)) == null) ? newValue : v;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation is equivalent to performing the following
|
||||
* steps for this {@code map}, then returning the current value or
|
||||
* {@code null} if now absent. :
|
||||
*
|
||||
* <pre> {@code
|
||||
* if (map.get(key) != null) {
|
||||
* V oldValue = map.get(key);
|
||||
* V newValue = remappingFunction.apply(key, oldValue);
|
||||
* if (newValue != null)
|
||||
* map.replace(key, oldValue, newValue);
|
||||
* else
|
||||
* map.remove(key, oldValue);
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* The default implementation may retry these steps when multiple threads
|
||||
* attempt updates including potentially calling the remapping function
|
||||
* multiple times.
|
||||
*
|
||||
* <p>This implementation assumes that the ConcurrentMap cannot contain null
|
||||
* values and {@code get()} returning null unambiguously means the key is
|
||||
* absent. Implementations which support null values <strong>must</strong>
|
||||
* override this default implementation.
|
||||
*
|
||||
* @throws UnsupportedOperationException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
default V computeIfPresent(K key,
|
||||
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||
Objects.requireNonNull(remappingFunction);
|
||||
V oldValue;
|
||||
while((oldValue = get(key)) != null) {
|
||||
V newValue = remappingFunction.apply(key, oldValue);
|
||||
if (newValue != null) {
|
||||
if (replace(key, oldValue, newValue))
|
||||
return newValue;
|
||||
} else if (remove(key, oldValue))
|
||||
return null;
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation is equivalent to performing the following
|
||||
* steps for this {@code map}, then returning the current value or
|
||||
* {@code null} if absent:
|
||||
*
|
||||
* <pre> {@code
|
||||
* V oldValue = map.get(key);
|
||||
* V newValue = remappingFunction.apply(key, oldValue);
|
||||
* if (oldValue != null ) {
|
||||
* if (newValue != null)
|
||||
* map.replace(key, oldValue, newValue);
|
||||
* else
|
||||
* map.remove(key, oldValue);
|
||||
* } else {
|
||||
* if (newValue != null)
|
||||
* map.putIfAbsent(key, newValue);
|
||||
* else
|
||||
* return null;
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* The default implementation may retry these steps when multiple
|
||||
* threads attempt updates including potentially calling the remapping
|
||||
* function multiple times.
|
||||
*
|
||||
* <p>This implementation assumes that the ConcurrentMap cannot contain null
|
||||
* values and {@code get()} returning null unambiguously means the key is
|
||||
* absent. Implementations which support null values <strong>must</strong>
|
||||
* override this default implementation.
|
||||
*
|
||||
* @throws UnsupportedOperationException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
default V compute(K key,
|
||||
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||
Objects.requireNonNull(remappingFunction);
|
||||
V oldValue = get(key);
|
||||
for(;;) {
|
||||
V newValue = remappingFunction.apply(key, oldValue);
|
||||
if (newValue == null) {
|
||||
// delete mapping
|
||||
if (oldValue != null || containsKey(key)) {
|
||||
// something to remove
|
||||
if (remove(key, oldValue)) {
|
||||
// removed the old value as expected
|
||||
return null;
|
||||
}
|
||||
|
||||
// some other value replaced old value. try again.
|
||||
oldValue = get(key);
|
||||
} else {
|
||||
// nothing to do. Leave things as they were.
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// add or replace old mapping
|
||||
if (oldValue != null) {
|
||||
// replace
|
||||
if (replace(key, oldValue, newValue)) {
|
||||
// replaced as expected.
|
||||
return newValue;
|
||||
}
|
||||
|
||||
// some other value replaced old value. try again.
|
||||
oldValue = get(key);
|
||||
} else {
|
||||
// add (replace if oldValue was null)
|
||||
if ((oldValue = putIfAbsent(key, newValue)) == null) {
|
||||
// replaced
|
||||
return newValue;
|
||||
}
|
||||
|
||||
// some other value replaced old value. try again.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation is equivalent to performing the following
|
||||
* steps for this {@code map}, then returning the current value or
|
||||
* {@code null} if absent:
|
||||
*
|
||||
* <pre> {@code
|
||||
* V oldValue = map.get(key);
|
||||
* V newValue = (oldValue == null) ? value :
|
||||
* remappingFunction.apply(oldValue, value);
|
||||
* if (newValue == null)
|
||||
* map.remove(key);
|
||||
* else
|
||||
* map.put(key, newValue);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The default implementation may retry these steps when multiple
|
||||
* threads attempt updates including potentially calling the remapping
|
||||
* function multiple times.
|
||||
*
|
||||
* <p>This implementation assumes that the ConcurrentMap cannot contain null
|
||||
* values and {@code get()} returning null unambiguously means the key is
|
||||
* absent. Implementations which support null values <strong>must</strong>
|
||||
* override this default implementation.
|
||||
*
|
||||
* @throws UnsupportedOperationException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
default V merge(K key, V value,
|
||||
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
|
||||
Objects.requireNonNull(remappingFunction);
|
||||
Objects.requireNonNull(value);
|
||||
V oldValue = get(key);
|
||||
for (;;) {
|
||||
if (oldValue != null) {
|
||||
V newValue = remappingFunction.apply(oldValue, value);
|
||||
if (newValue != null) {
|
||||
if (replace(key, oldValue, newValue))
|
||||
return newValue;
|
||||
} else if (remove(key, oldValue)) {
|
||||
return null;
|
||||
}
|
||||
oldValue = get(key);
|
||||
} else {
|
||||
if ((oldValue = putIfAbsent(key, value)) == null) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
167
jdkSrc/jdk8/java/util/concurrent/ConcurrentNavigableMap.java
Normal file
167
jdkSrc/jdk8/java/util/concurrent/ConcurrentNavigableMap.java
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A {@link ConcurrentMap} supporting {@link NavigableMap} operations,
|
||||
* and recursively so for its navigable sub-maps.
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @author Doug Lea
|
||||
* @param <K> the type of keys maintained by this map
|
||||
* @param <V> the type of mapped values
|
||||
* @since 1.6
|
||||
*/
|
||||
public interface ConcurrentNavigableMap<K,V>
|
||||
extends ConcurrentMap<K,V>, NavigableMap<K,V>
|
||||
{
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
ConcurrentNavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
|
||||
K toKey, boolean toInclusive);
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
ConcurrentNavigableMap<K,V> headMap(K toKey, boolean inclusive);
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
ConcurrentNavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
ConcurrentNavigableMap<K,V> subMap(K fromKey, K toKey);
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
ConcurrentNavigableMap<K,V> headMap(K toKey);
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
ConcurrentNavigableMap<K,V> tailMap(K fromKey);
|
||||
|
||||
/**
|
||||
* Returns a reverse order view of the mappings contained in this map.
|
||||
* The descending map is backed by this map, so changes to the map are
|
||||
* reflected in the descending map, and vice-versa.
|
||||
*
|
||||
* <p>The returned map has an ordering equivalent to
|
||||
* {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
|
||||
* The expression {@code m.descendingMap().descendingMap()} returns a
|
||||
* view of {@code m} essentially equivalent to {@code m}.
|
||||
*
|
||||
* @return a reverse order view of this map
|
||||
*/
|
||||
ConcurrentNavigableMap<K,V> descendingMap();
|
||||
|
||||
/**
|
||||
* Returns a {@link NavigableSet} view of the keys contained in this map.
|
||||
* The set's iterator returns the keys in ascending order.
|
||||
* The set is backed by the map, so changes to the map are
|
||||
* reflected in the set, and vice-versa. The set supports element
|
||||
* removal, which removes the corresponding mapping from the map,
|
||||
* via the {@code Iterator.remove}, {@code Set.remove},
|
||||
* {@code removeAll}, {@code retainAll}, and {@code clear}
|
||||
* operations. It does not support the {@code add} or {@code addAll}
|
||||
* operations.
|
||||
*
|
||||
* <p>The view's iterators and spliterators are
|
||||
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
|
||||
*
|
||||
* @return a navigable set view of the keys in this map
|
||||
*/
|
||||
public NavigableSet<K> navigableKeySet();
|
||||
|
||||
/**
|
||||
* Returns a {@link NavigableSet} view of the keys contained in this map.
|
||||
* The set's iterator returns the keys in ascending order.
|
||||
* The set is backed by the map, so changes to the map are
|
||||
* reflected in the set, and vice-versa. The set supports element
|
||||
* removal, which removes the corresponding mapping from the map,
|
||||
* via the {@code Iterator.remove}, {@code Set.remove},
|
||||
* {@code removeAll}, {@code retainAll}, and {@code clear}
|
||||
* operations. It does not support the {@code add} or {@code addAll}
|
||||
* operations.
|
||||
*
|
||||
* <p>The view's iterators and spliterators are
|
||||
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
|
||||
*
|
||||
* <p>This method is equivalent to method {@code navigableKeySet}.
|
||||
*
|
||||
* @return a navigable set view of the keys in this map
|
||||
*/
|
||||
NavigableSet<K> keySet();
|
||||
|
||||
/**
|
||||
* Returns a reverse order {@link NavigableSet} view of the keys contained in this map.
|
||||
* The set's iterator returns the keys in descending order.
|
||||
* The set is backed by the map, so changes to the map are
|
||||
* reflected in the set, and vice-versa. The set supports element
|
||||
* removal, which removes the corresponding mapping from the map,
|
||||
* via the {@code Iterator.remove}, {@code Set.remove},
|
||||
* {@code removeAll}, {@code retainAll}, and {@code clear}
|
||||
* operations. It does not support the {@code add} or {@code addAll}
|
||||
* operations.
|
||||
*
|
||||
* <p>The view's iterators and spliterators are
|
||||
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
|
||||
*
|
||||
* @return a reverse order navigable set view of the keys in this map
|
||||
*/
|
||||
public NavigableSet<K> descendingKeySet();
|
||||
}
|
||||
3615
jdkSrc/jdk8/java/util/concurrent/ConcurrentSkipListMap.java
Normal file
3615
jdkSrc/jdk8/java/util/concurrent/ConcurrentSkipListMap.java
Normal file
File diff suppressed because it is too large
Load Diff
526
jdkSrc/jdk8/java/util/concurrent/ConcurrentSkipListSet.java
Normal file
526
jdkSrc/jdk8/java/util/concurrent/ConcurrentSkipListSet.java
Normal file
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.Spliterator;
|
||||
|
||||
/**
|
||||
* A scalable concurrent {@link NavigableSet} implementation based on
|
||||
* a {@link ConcurrentSkipListMap}. The elements of the set are kept
|
||||
* sorted according to their {@linkplain Comparable natural ordering},
|
||||
* or by a {@link Comparator} provided at set creation time, depending
|
||||
* on which constructor is used.
|
||||
*
|
||||
* <p>This implementation provides expected average <i>log(n)</i> time
|
||||
* cost for the {@code contains}, {@code add}, and {@code remove}
|
||||
* operations and their variants. Insertion, removal, and access
|
||||
* operations safely execute concurrently by multiple threads.
|
||||
*
|
||||
* <p>Iterators and spliterators are
|
||||
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
|
||||
*
|
||||
* <p>Ascending ordered views and their iterators are faster than
|
||||
* descending ones.
|
||||
*
|
||||
* <p>Beware that, unlike in most collections, the {@code size}
|
||||
* method is <em>not</em> a constant-time operation. Because of the
|
||||
* asynchronous nature of these sets, determining the current number
|
||||
* of elements requires a traversal of the elements, and so may report
|
||||
* inaccurate results if this collection is modified during traversal.
|
||||
* Additionally, the bulk operations {@code addAll},
|
||||
* {@code removeAll}, {@code retainAll}, {@code containsAll},
|
||||
* {@code equals}, and {@code toArray} are <em>not</em> guaranteed
|
||||
* to be performed atomically. For example, an iterator operating
|
||||
* concurrently with an {@code addAll} operation might view only some
|
||||
* of the added elements.
|
||||
*
|
||||
* <p>This class and its iterators implement all of the
|
||||
* <em>optional</em> methods of the {@link Set} and {@link Iterator}
|
||||
* interfaces. Like most other concurrent collection implementations,
|
||||
* this class does not permit the use of {@code null} elements,
|
||||
* because {@code null} arguments and return values cannot be reliably
|
||||
* distinguished from the absence of elements.
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @author Doug Lea
|
||||
* @param <E> the type of elements maintained by this set
|
||||
* @since 1.6
|
||||
*/
|
||||
public class ConcurrentSkipListSet<E>
|
||||
extends AbstractSet<E>
|
||||
implements NavigableSet<E>, Cloneable, java.io.Serializable {
|
||||
|
||||
private static final long serialVersionUID = -2479143111061671589L;
|
||||
|
||||
/**
|
||||
* The underlying map. Uses Boolean.TRUE as value for each
|
||||
* element. This field is declared final for the sake of thread
|
||||
* safety, which entails some ugliness in clone().
|
||||
*/
|
||||
private final ConcurrentNavigableMap<E,Object> m;
|
||||
|
||||
/**
|
||||
* Constructs a new, empty set that orders its elements according to
|
||||
* their {@linkplain Comparable natural ordering}.
|
||||
*/
|
||||
public ConcurrentSkipListSet() {
|
||||
m = new ConcurrentSkipListMap<E,Object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, empty set that orders its elements according to
|
||||
* the specified comparator.
|
||||
*
|
||||
* @param comparator the comparator that will be used to order this set.
|
||||
* If {@code null}, the {@linkplain Comparable natural
|
||||
* ordering} of the elements will be used.
|
||||
*/
|
||||
public ConcurrentSkipListSet(Comparator<? super E> comparator) {
|
||||
m = new ConcurrentSkipListMap<E,Object>(comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new set containing the elements in the specified
|
||||
* collection, that orders its elements according to their
|
||||
* {@linkplain Comparable natural ordering}.
|
||||
*
|
||||
* @param c The elements that will comprise the new set
|
||||
* @throws ClassCastException if the elements in {@code c} are
|
||||
* not {@link Comparable}, or are not mutually comparable
|
||||
* @throws NullPointerException if the specified collection or any
|
||||
* of its elements are null
|
||||
*/
|
||||
public ConcurrentSkipListSet(Collection<? extends E> c) {
|
||||
m = new ConcurrentSkipListMap<E,Object>();
|
||||
addAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new set containing the same elements and using the
|
||||
* same ordering as the specified sorted set.
|
||||
*
|
||||
* @param s sorted set whose elements will comprise the new set
|
||||
* @throws NullPointerException if the specified sorted set or any
|
||||
* of its elements are null
|
||||
*/
|
||||
public ConcurrentSkipListSet(SortedSet<E> s) {
|
||||
m = new ConcurrentSkipListMap<E,Object>(s.comparator());
|
||||
addAll(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* For use by submaps
|
||||
*/
|
||||
ConcurrentSkipListSet(ConcurrentNavigableMap<E,Object> m) {
|
||||
this.m = m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shallow copy of this {@code ConcurrentSkipListSet}
|
||||
* instance. (The elements themselves are not cloned.)
|
||||
*
|
||||
* @return a shallow copy of this set
|
||||
*/
|
||||
public ConcurrentSkipListSet<E> clone() {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
ConcurrentSkipListSet<E> clone =
|
||||
(ConcurrentSkipListSet<E>) super.clone();
|
||||
clone.setMap(new ConcurrentSkipListMap<E,Object>(m));
|
||||
return clone;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------- Set operations -------------- */
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this set. If this set
|
||||
* contains more than {@code Integer.MAX_VALUE} elements, it
|
||||
* returns {@code Integer.MAX_VALUE}.
|
||||
*
|
||||
* <p>Beware that, unlike in most collections, this method is
|
||||
* <em>NOT</em> a constant-time operation. Because of the
|
||||
* asynchronous nature of these sets, determining the current
|
||||
* number of elements requires traversing them all to count them.
|
||||
* Additionally, it is possible for the size to change during
|
||||
* execution of this method, in which case the returned result
|
||||
* will be inaccurate. Thus, this method is typically not very
|
||||
* useful in concurrent applications.
|
||||
*
|
||||
* @return the number of elements in this set
|
||||
*/
|
||||
public int size() {
|
||||
return m.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this set contains no elements.
|
||||
* @return {@code true} if this set contains no elements
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return m.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this set contains the specified element.
|
||||
* More formally, returns {@code true} if and only if this set
|
||||
* contains an element {@code e} such that {@code o.equals(e)}.
|
||||
*
|
||||
* @param o object to be checked for containment in this set
|
||||
* @return {@code true} if this set contains the specified element
|
||||
* @throws ClassCastException if the specified element cannot be
|
||||
* compared with the elements currently in this set
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public boolean contains(Object o) {
|
||||
return m.containsKey(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified element to this set if it is not already present.
|
||||
* More formally, adds the specified element {@code e} to this set if
|
||||
* the set contains no element {@code e2} such that {@code e.equals(e2)}.
|
||||
* If this set already contains the element, the call leaves the set
|
||||
* unchanged and returns {@code false}.
|
||||
*
|
||||
* @param e element to be added to this set
|
||||
* @return {@code true} if this set did not already contain the
|
||||
* specified element
|
||||
* @throws ClassCastException if {@code e} cannot be compared
|
||||
* with the elements currently in this set
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public boolean add(E e) {
|
||||
return m.putIfAbsent(e, Boolean.TRUE) == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified element from this set if it is present.
|
||||
* More formally, removes an element {@code e} such that
|
||||
* {@code o.equals(e)}, if this set contains such an element.
|
||||
* Returns {@code true} if this set contained the element (or
|
||||
* equivalently, if this set changed as a result of the call).
|
||||
* (This set will not contain the element once the call returns.)
|
||||
*
|
||||
* @param o object to be removed from this set, if present
|
||||
* @return {@code true} if this set contained the specified element
|
||||
* @throws ClassCastException if {@code o} cannot be compared
|
||||
* with the elements currently in this set
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public boolean remove(Object o) {
|
||||
return m.remove(o, Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the elements from this set.
|
||||
*/
|
||||
public void clear() {
|
||||
m.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this set in ascending order.
|
||||
*
|
||||
* @return an iterator over the elements in this set in ascending order
|
||||
*/
|
||||
public Iterator<E> iterator() {
|
||||
return m.navigableKeySet().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this set in descending order.
|
||||
*
|
||||
* @return an iterator over the elements in this set in descending order
|
||||
*/
|
||||
public Iterator<E> descendingIterator() {
|
||||
return m.descendingKeySet().iterator();
|
||||
}
|
||||
|
||||
|
||||
/* ---------------- AbstractSet Overrides -------------- */
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns
|
||||
* {@code true} if the specified object is also a set, the two sets
|
||||
* have the same size, and every member of the specified set is
|
||||
* contained in this set (or equivalently, every member of this set is
|
||||
* contained in the specified set). This definition ensures that the
|
||||
* equals method works properly across different implementations of the
|
||||
* set interface.
|
||||
*
|
||||
* @param o the object to be compared for equality with this set
|
||||
* @return {@code true} if the specified object is equal to this set
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
// Override AbstractSet version to avoid calling size()
|
||||
if (o == this)
|
||||
return true;
|
||||
if (!(o instanceof Set))
|
||||
return false;
|
||||
Collection<?> c = (Collection<?>) o;
|
||||
try {
|
||||
return containsAll(c) && c.containsAll(this);
|
||||
} catch (ClassCastException unused) {
|
||||
return false;
|
||||
} catch (NullPointerException unused) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes from this set all of its elements that are contained in
|
||||
* the specified collection. If the specified collection is also
|
||||
* a set, this operation effectively modifies this set so that its
|
||||
* value is the <i>asymmetric set difference</i> of the two sets.
|
||||
*
|
||||
* @param c collection containing elements to be removed from this set
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws ClassCastException if the types of one or more elements in this
|
||||
* set are incompatible with the specified collection
|
||||
* @throws NullPointerException if the specified collection or any
|
||||
* of its elements are null
|
||||
*/
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
// Override AbstractSet version to avoid unnecessary call to size()
|
||||
boolean modified = false;
|
||||
for (Object e : c)
|
||||
if (remove(e))
|
||||
modified = true;
|
||||
return modified;
|
||||
}
|
||||
|
||||
/* ---------------- Relational operations -------------- */
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public E lower(E e) {
|
||||
return m.lowerKey(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public E floor(E e) {
|
||||
return m.floorKey(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public E ceiling(E e) {
|
||||
return m.ceilingKey(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public E higher(E e) {
|
||||
return m.higherKey(e);
|
||||
}
|
||||
|
||||
public E pollFirst() {
|
||||
Map.Entry<E,Object> e = m.pollFirstEntry();
|
||||
return (e == null) ? null : e.getKey();
|
||||
}
|
||||
|
||||
public E pollLast() {
|
||||
Map.Entry<E,Object> e = m.pollLastEntry();
|
||||
return (e == null) ? null : e.getKey();
|
||||
}
|
||||
|
||||
|
||||
/* ---------------- SortedSet operations -------------- */
|
||||
|
||||
|
||||
public Comparator<? super E> comparator() {
|
||||
return m.comparator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws java.util.NoSuchElementException {@inheritDoc}
|
||||
*/
|
||||
public E first() {
|
||||
return m.firstKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws java.util.NoSuchElementException {@inheritDoc}
|
||||
*/
|
||||
public E last() {
|
||||
return m.lastKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code fromElement} or
|
||||
* {@code toElement} is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public NavigableSet<E> subSet(E fromElement,
|
||||
boolean fromInclusive,
|
||||
E toElement,
|
||||
boolean toInclusive) {
|
||||
return new ConcurrentSkipListSet<E>
|
||||
(m.subMap(fromElement, fromInclusive,
|
||||
toElement, toInclusive));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code toElement} is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
|
||||
return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code fromElement} is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
|
||||
return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code fromElement} or
|
||||
* {@code toElement} is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public NavigableSet<E> subSet(E fromElement, E toElement) {
|
||||
return subSet(fromElement, true, toElement, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code toElement} is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public NavigableSet<E> headSet(E toElement) {
|
||||
return headSet(toElement, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException if {@code fromElement} is null
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public NavigableSet<E> tailSet(E fromElement) {
|
||||
return tailSet(fromElement, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reverse order view of the elements contained in this set.
|
||||
* The descending set is backed by this set, so changes to the set are
|
||||
* reflected in the descending set, and vice-versa.
|
||||
*
|
||||
* <p>The returned set has an ordering equivalent to
|
||||
* {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
|
||||
* The expression {@code s.descendingSet().descendingSet()} returns a
|
||||
* view of {@code s} essentially equivalent to {@code s}.
|
||||
*
|
||||
* @return a reverse order view of this set
|
||||
*/
|
||||
public NavigableSet<E> descendingSet() {
|
||||
return new ConcurrentSkipListSet<E>(m.descendingMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Spliterator} over the elements in this set.
|
||||
*
|
||||
* <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
|
||||
* {@link Spliterator#NONNULL}, {@link Spliterator#DISTINCT},
|
||||
* {@link Spliterator#SORTED} and {@link Spliterator#ORDERED}, with an
|
||||
* encounter order that is ascending order. Overriding implementations
|
||||
* should document the reporting of additional characteristic values.
|
||||
*
|
||||
* <p>The spliterator's comparator (see
|
||||
* {@link java.util.Spliterator#getComparator()}) is {@code null} if
|
||||
* the set's comparator (see {@link #comparator()}) is {@code null}.
|
||||
* Otherwise, the spliterator's comparator is the same as or imposes the
|
||||
* same total ordering as the set's comparator.
|
||||
*
|
||||
* @return a {@code Spliterator} over the elements in this set
|
||||
* @since 1.8
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Spliterator<E> spliterator() {
|
||||
if (m instanceof ConcurrentSkipListMap)
|
||||
return ((ConcurrentSkipListMap<E,?>)m).keySpliterator();
|
||||
else
|
||||
return (Spliterator<E>)((ConcurrentSkipListMap.SubMap<E,?>)m).keyIterator();
|
||||
}
|
||||
|
||||
// Support for resetting map in clone
|
||||
private void setMap(ConcurrentNavigableMap<E,Object> map) {
|
||||
UNSAFE.putObjectVolatile(this, mapOffset, map);
|
||||
}
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long mapOffset;
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class<?> k = ConcurrentSkipListSet.class;
|
||||
mapOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("m"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
1692
jdkSrc/jdk8/java/util/concurrent/CopyOnWriteArrayList.java
Normal file
1692
jdkSrc/jdk8/java/util/concurrent/CopyOnWriteArrayList.java
Normal file
File diff suppressed because it is too large
Load Diff
433
jdkSrc/jdk8/java/util/concurrent/CopyOnWriteArraySet.java
Normal file
433
jdkSrc/jdk8/java/util/concurrent/CopyOnWriteArraySet.java
Normal file
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A {@link java.util.Set} that uses an internal {@link CopyOnWriteArrayList}
|
||||
* for all of its operations. Thus, it shares the same basic properties:
|
||||
* <ul>
|
||||
* <li>It is best suited for applications in which set sizes generally
|
||||
* stay small, read-only operations
|
||||
* vastly outnumber mutative operations, and you need
|
||||
* to prevent interference among threads during traversal.
|
||||
* <li>It is thread-safe.
|
||||
* <li>Mutative operations ({@code add}, {@code set}, {@code remove}, etc.)
|
||||
* are expensive since they usually entail copying the entire underlying
|
||||
* array.
|
||||
* <li>Iterators do not support the mutative {@code remove} operation.
|
||||
* <li>Traversal via iterators is fast and cannot encounter
|
||||
* interference from other threads. Iterators rely on
|
||||
* unchanging snapshots of the array at the time the iterators were
|
||||
* constructed.
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>Sample Usage.</b> The following code sketch uses a
|
||||
* copy-on-write set to maintain a set of Handler objects that
|
||||
* perform some action upon state updates.
|
||||
*
|
||||
* <pre> {@code
|
||||
* class Handler { void handle(); ... }
|
||||
*
|
||||
* class X {
|
||||
* private final CopyOnWriteArraySet<Handler> handlers
|
||||
* = new CopyOnWriteArraySet<Handler>();
|
||||
* public void addHandler(Handler h) { handlers.add(h); }
|
||||
*
|
||||
* private long internalState;
|
||||
* private synchronized void changeState() { internalState = ...; }
|
||||
*
|
||||
* public void update() {
|
||||
* changeState();
|
||||
* for (Handler handler : handlers)
|
||||
* handler.handle();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @see CopyOnWriteArrayList
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <E> the type of elements held in this collection
|
||||
*/
|
||||
public class CopyOnWriteArraySet<E> extends AbstractSet<E>
|
||||
implements java.io.Serializable {
|
||||
private static final long serialVersionUID = 5457747651344034263L;
|
||||
|
||||
private final CopyOnWriteArrayList<E> al;
|
||||
|
||||
/**
|
||||
* Creates an empty set.
|
||||
*/
|
||||
public CopyOnWriteArraySet() {
|
||||
al = new CopyOnWriteArrayList<E>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a set containing all of the elements of the specified
|
||||
* collection.
|
||||
*
|
||||
* @param c the collection of elements to initially contain
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
*/
|
||||
public CopyOnWriteArraySet(Collection<? extends E> c) {
|
||||
if (c.getClass() == CopyOnWriteArraySet.class) {
|
||||
@SuppressWarnings("unchecked") CopyOnWriteArraySet<E> cc =
|
||||
(CopyOnWriteArraySet<E>)c;
|
||||
al = new CopyOnWriteArrayList<E>(cc.al);
|
||||
}
|
||||
else {
|
||||
al = new CopyOnWriteArrayList<E>();
|
||||
al.addAllAbsent(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this set.
|
||||
*
|
||||
* @return the number of elements in this set
|
||||
*/
|
||||
public int size() {
|
||||
return al.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this set contains no elements.
|
||||
*
|
||||
* @return {@code true} if this set contains no elements
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return al.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this set contains the specified element.
|
||||
* More formally, returns {@code true} if and only if this set
|
||||
* contains an element {@code e} such that
|
||||
* <tt>(o==null ? e==null : o.equals(e))</tt>.
|
||||
*
|
||||
* @param o element whose presence in this set is to be tested
|
||||
* @return {@code true} if this set contains the specified element
|
||||
*/
|
||||
public boolean contains(Object o) {
|
||||
return al.contains(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all of the elements in this set.
|
||||
* If this set makes any guarantees as to what order its elements
|
||||
* are returned by its iterator, this method must return the
|
||||
* elements in the same order.
|
||||
*
|
||||
* <p>The returned array will be "safe" in that no references to it
|
||||
* are maintained by this set. (In other words, this method must
|
||||
* allocate a new array even if this set is backed by an array).
|
||||
* The caller is thus free to modify the returned array.
|
||||
*
|
||||
* <p>This method acts as bridge between array-based and collection-based
|
||||
* APIs.
|
||||
*
|
||||
* @return an array containing all the elements in this set
|
||||
*/
|
||||
public Object[] toArray() {
|
||||
return al.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all of the elements in this set; the
|
||||
* runtime type of the returned array is that of the specified array.
|
||||
* If the set fits in the specified array, it is returned therein.
|
||||
* Otherwise, a new array is allocated with the runtime type of the
|
||||
* specified array and the size of this set.
|
||||
*
|
||||
* <p>If this set fits in the specified array with room to spare
|
||||
* (i.e., the array has more elements than this set), the element in
|
||||
* the array immediately following the end of the set is set to
|
||||
* {@code null}. (This is useful in determining the length of this
|
||||
* set <i>only</i> if the caller knows that this set does not contain
|
||||
* any null elements.)
|
||||
*
|
||||
* <p>If this set makes any guarantees as to what order its elements
|
||||
* are returned by its iterator, this method must return the elements
|
||||
* in the same order.
|
||||
*
|
||||
* <p>Like the {@link #toArray()} method, this method acts as bridge between
|
||||
* array-based and collection-based APIs. Further, this method allows
|
||||
* precise control over the runtime type of the output array, and may,
|
||||
* under certain circumstances, be used to save allocation costs.
|
||||
*
|
||||
* <p>Suppose {@code x} is a set known to contain only strings.
|
||||
* The following code can be used to dump the set into a newly allocated
|
||||
* array of {@code String}:
|
||||
*
|
||||
* <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
|
||||
*
|
||||
* Note that {@code toArray(new Object[0])} is identical in function to
|
||||
* {@code toArray()}.
|
||||
*
|
||||
* @param a the array into which the elements of this set are to be
|
||||
* stored, if it is big enough; otherwise, a new array of the same
|
||||
* runtime type is allocated for this purpose.
|
||||
* @return an array containing all the elements in this set
|
||||
* @throws ArrayStoreException if the runtime type of the specified array
|
||||
* is not a supertype of the runtime type of every element in this
|
||||
* set
|
||||
* @throws NullPointerException if the specified array is null
|
||||
*/
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return al.toArray(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the elements from this set.
|
||||
* The set will be empty after this call returns.
|
||||
*/
|
||||
public void clear() {
|
||||
al.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified element from this set if it is present.
|
||||
* More formally, removes an element {@code e} such that
|
||||
* <tt>(o==null ? e==null : o.equals(e))</tt>,
|
||||
* if this set contains such an element. Returns {@code true} if
|
||||
* this set contained the element (or equivalently, if this set
|
||||
* changed as a result of the call). (This set will not contain the
|
||||
* element once the call returns.)
|
||||
*
|
||||
* @param o object to be removed from this set, if present
|
||||
* @return {@code true} if this set contained the specified element
|
||||
*/
|
||||
public boolean remove(Object o) {
|
||||
return al.remove(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified element to this set if it is not already present.
|
||||
* More formally, adds the specified element {@code e} to this set if
|
||||
* the set contains no element {@code e2} such that
|
||||
* <tt>(e==null ? e2==null : e.equals(e2))</tt>.
|
||||
* If this set already contains the element, the call leaves the set
|
||||
* unchanged and returns {@code false}.
|
||||
*
|
||||
* @param e element to be added to this set
|
||||
* @return {@code true} if this set did not already contain the specified
|
||||
* element
|
||||
*/
|
||||
public boolean add(E e) {
|
||||
return al.addIfAbsent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this set contains all of the elements of the
|
||||
* specified collection. If the specified collection is also a set, this
|
||||
* method returns {@code true} if it is a <i>subset</i> of this set.
|
||||
*
|
||||
* @param c collection to be checked for containment in this set
|
||||
* @return {@code true} if this set contains all of the elements of the
|
||||
* specified collection
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
* @see #contains(Object)
|
||||
*/
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return al.containsAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all of the elements in the specified collection to this set if
|
||||
* they're not already present. If the specified collection is also a
|
||||
* set, the {@code addAll} operation effectively modifies this set so
|
||||
* that its value is the <i>union</i> of the two sets. The behavior of
|
||||
* this operation is undefined if the specified collection is modified
|
||||
* while the operation is in progress.
|
||||
*
|
||||
* @param c collection containing elements to be added to this set
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
* @see #add(Object)
|
||||
*/
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
return al.addAllAbsent(c) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes from this set all of its elements that are contained in the
|
||||
* specified collection. If the specified collection is also a set,
|
||||
* this operation effectively modifies this set so that its value is the
|
||||
* <i>asymmetric set difference</i> of the two sets.
|
||||
*
|
||||
* @param c collection containing elements to be removed from this set
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws ClassCastException if the class of an element of this set
|
||||
* is incompatible with the specified collection (optional)
|
||||
* @throws NullPointerException if this set contains a null element and the
|
||||
* specified collection does not permit null elements (optional),
|
||||
* or if the specified collection is null
|
||||
* @see #remove(Object)
|
||||
*/
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
return al.removeAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retains only the elements in this set that are contained in the
|
||||
* specified collection. In other words, removes from this set all of
|
||||
* its elements that are not contained in the specified collection. If
|
||||
* the specified collection is also a set, this operation effectively
|
||||
* modifies this set so that its value is the <i>intersection</i> of the
|
||||
* two sets.
|
||||
*
|
||||
* @param c collection containing elements to be retained in this set
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws ClassCastException if the class of an element of this set
|
||||
* is incompatible with the specified collection (optional)
|
||||
* @throws NullPointerException if this set contains a null element and the
|
||||
* specified collection does not permit null elements (optional),
|
||||
* or if the specified collection is null
|
||||
* @see #remove(Object)
|
||||
*/
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
return al.retainAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements contained in this set
|
||||
* in the order in which these elements were added.
|
||||
*
|
||||
* <p>The returned iterator provides a snapshot of the state of the set
|
||||
* when the iterator was constructed. No synchronization is needed while
|
||||
* traversing the iterator. The iterator does <em>NOT</em> support the
|
||||
* {@code remove} method.
|
||||
*
|
||||
* @return an iterator over the elements in this set
|
||||
*/
|
||||
public Iterator<E> iterator() {
|
||||
return al.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality.
|
||||
* Returns {@code true} if the specified object is the same object
|
||||
* as this object, or if it is also a {@link Set} and the elements
|
||||
* returned by an {@linkplain Set#iterator() iterator} over the
|
||||
* specified set are the same as the elements returned by an
|
||||
* iterator over this set. More formally, the two iterators are
|
||||
* considered to return the same elements if they return the same
|
||||
* number of elements and for every element {@code e1} returned by
|
||||
* the iterator over the specified set, there is an element
|
||||
* {@code e2} returned by the iterator over this set such that
|
||||
* {@code (e1==null ? e2==null : e1.equals(e2))}.
|
||||
*
|
||||
* @param o object to be compared for equality with this set
|
||||
* @return {@code true} if the specified object is equal to this set
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o == this)
|
||||
return true;
|
||||
if (!(o instanceof Set))
|
||||
return false;
|
||||
Set<?> set = (Set<?>)(o);
|
||||
Iterator<?> it = set.iterator();
|
||||
|
||||
// Uses O(n^2) algorithm that is only appropriate
|
||||
// for small sets, which CopyOnWriteArraySets should be.
|
||||
|
||||
// Use a single snapshot of underlying array
|
||||
Object[] elements = al.getArray();
|
||||
int len = elements.length;
|
||||
// Mark matched elements to avoid re-checking
|
||||
boolean[] matched = new boolean[len];
|
||||
int k = 0;
|
||||
outer: while (it.hasNext()) {
|
||||
if (++k > len)
|
||||
return false;
|
||||
Object x = it.next();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (!matched[i] && eq(x, elements[i])) {
|
||||
matched[i] = true;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return k == len;
|
||||
}
|
||||
|
||||
public boolean removeIf(Predicate<? super E> filter) {
|
||||
return al.removeIf(filter);
|
||||
}
|
||||
|
||||
public void forEach(Consumer<? super E> action) {
|
||||
al.forEach(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Spliterator} over the elements in this set in the order
|
||||
* in which these elements were added.
|
||||
*
|
||||
* <p>The {@code Spliterator} reports {@link Spliterator#IMMUTABLE},
|
||||
* {@link Spliterator#DISTINCT}, {@link Spliterator#SIZED}, and
|
||||
* {@link Spliterator#SUBSIZED}.
|
||||
*
|
||||
* <p>The spliterator provides a snapshot of the state of the set
|
||||
* when the spliterator was constructed. No synchronization is needed while
|
||||
* operating on the spliterator.
|
||||
*
|
||||
* @return a {@code Spliterator} over the elements in this set
|
||||
* @since 1.8
|
||||
*/
|
||||
public Spliterator<E> spliterator() {
|
||||
return Spliterators.spliterator
|
||||
(al.getArray(), Spliterator.IMMUTABLE | Spliterator.DISTINCT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for equality, coping with nulls.
|
||||
*/
|
||||
private static boolean eq(Object o1, Object o2) {
|
||||
return (o1 == null) ? o2 == null : o1.equals(o2);
|
||||
}
|
||||
}
|
||||
315
jdkSrc/jdk8/java/util/concurrent/CountDownLatch.java
Normal file
315
jdkSrc/jdk8/java/util/concurrent/CountDownLatch.java
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
|
||||
|
||||
/**
|
||||
* A synchronization aid that allows one or more threads to wait until
|
||||
* a set of operations being performed in other threads completes.
|
||||
*
|
||||
* <p>A {@code CountDownLatch} is initialized with a given <em>count</em>.
|
||||
* The {@link #await await} methods block until the current count reaches
|
||||
* zero due to invocations of the {@link #countDown} method, after which
|
||||
* all waiting threads are released and any subsequent invocations of
|
||||
* {@link #await await} return immediately. This is a one-shot phenomenon
|
||||
* -- the count cannot be reset. If you need a version that resets the
|
||||
* count, consider using a {@link CyclicBarrier}.
|
||||
*
|
||||
* <p>A {@code CountDownLatch} is a versatile synchronization tool
|
||||
* and can be used for a number of purposes. A
|
||||
* {@code CountDownLatch} initialized with a count of one serves as a
|
||||
* simple on/off latch, or gate: all threads invoking {@link #await await}
|
||||
* wait at the gate until it is opened by a thread invoking {@link
|
||||
* #countDown}. A {@code CountDownLatch} initialized to <em>N</em>
|
||||
* can be used to make one thread wait until <em>N</em> threads have
|
||||
* completed some action, or some action has been completed N times.
|
||||
*
|
||||
* <p>A useful property of a {@code CountDownLatch} is that it
|
||||
* doesn't require that threads calling {@code countDown} wait for
|
||||
* the count to reach zero before proceeding, it simply prevents any
|
||||
* thread from proceeding past an {@link #await await} until all
|
||||
* threads could pass.
|
||||
*
|
||||
* <p><b>Sample usage:</b> Here is a pair of classes in which a group
|
||||
* of worker threads use two countdown latches:
|
||||
* <ul>
|
||||
* <li>The first is a start signal that prevents any worker from proceeding
|
||||
* until the driver is ready for them to proceed;
|
||||
* <li>The second is a completion signal that allows the driver to wait
|
||||
* until all workers have completed.
|
||||
* </ul>
|
||||
*
|
||||
* <pre> {@code
|
||||
* class Driver { // ...
|
||||
* void main() throws InterruptedException {
|
||||
* CountDownLatch startSignal = new CountDownLatch(1);
|
||||
* CountDownLatch doneSignal = new CountDownLatch(N);
|
||||
*
|
||||
* for (int i = 0; i < N; ++i) // create and start threads
|
||||
* new Thread(new Worker(startSignal, doneSignal)).start();
|
||||
*
|
||||
* doSomethingElse(); // don't let run yet
|
||||
* startSignal.countDown(); // let all threads proceed
|
||||
* doSomethingElse();
|
||||
* doneSignal.await(); // wait for all to finish
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* class Worker implements Runnable {
|
||||
* private final CountDownLatch startSignal;
|
||||
* private final CountDownLatch doneSignal;
|
||||
* Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
|
||||
* this.startSignal = startSignal;
|
||||
* this.doneSignal = doneSignal;
|
||||
* }
|
||||
* public void run() {
|
||||
* try {
|
||||
* startSignal.await();
|
||||
* doWork();
|
||||
* doneSignal.countDown();
|
||||
* } catch (InterruptedException ex) {} // return;
|
||||
* }
|
||||
*
|
||||
* void doWork() { ... }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>Another typical usage would be to divide a problem into N parts,
|
||||
* describe each part with a Runnable that executes that portion and
|
||||
* counts down on the latch, and queue all the Runnables to an
|
||||
* Executor. When all sub-parts are complete, the coordinating thread
|
||||
* will be able to pass through await. (When threads must repeatedly
|
||||
* count down in this way, instead use a {@link CyclicBarrier}.)
|
||||
*
|
||||
* <pre> {@code
|
||||
* class Driver2 { // ...
|
||||
* void main() throws InterruptedException {
|
||||
* CountDownLatch doneSignal = new CountDownLatch(N);
|
||||
* Executor e = ...
|
||||
*
|
||||
* for (int i = 0; i < N; ++i) // create and start threads
|
||||
* e.execute(new WorkerRunnable(doneSignal, i));
|
||||
*
|
||||
* doneSignal.await(); // wait for all to finish
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* class WorkerRunnable implements Runnable {
|
||||
* private final CountDownLatch doneSignal;
|
||||
* private final int i;
|
||||
* WorkerRunnable(CountDownLatch doneSignal, int i) {
|
||||
* this.doneSignal = doneSignal;
|
||||
* this.i = i;
|
||||
* }
|
||||
* public void run() {
|
||||
* try {
|
||||
* doWork(i);
|
||||
* doneSignal.countDown();
|
||||
* } catch (InterruptedException ex) {} // return;
|
||||
* }
|
||||
*
|
||||
* void doWork() { ... }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>Memory consistency effects: Until the count reaches
|
||||
* zero, actions in a thread prior to calling
|
||||
* {@code countDown()}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* actions following a successful return from a corresponding
|
||||
* {@code await()} in another thread.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class CountDownLatch {
|
||||
/**
|
||||
* Synchronization control For CountDownLatch.
|
||||
* Uses AQS state to represent count.
|
||||
*/
|
||||
private static final class Sync extends AbstractQueuedSynchronizer {
|
||||
private static final long serialVersionUID = 4982264981922014374L;
|
||||
|
||||
Sync(int count) {
|
||||
setState(count);
|
||||
}
|
||||
|
||||
int getCount() {
|
||||
return getState();
|
||||
}
|
||||
|
||||
protected int tryAcquireShared(int acquires) {
|
||||
return (getState() == 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
protected boolean tryReleaseShared(int releases) {
|
||||
// Decrement count; signal when transition to zero
|
||||
for (;;) {
|
||||
int c = getState();
|
||||
if (c == 0)
|
||||
return false;
|
||||
int nextc = c-1;
|
||||
if (compareAndSetState(c, nextc))
|
||||
return nextc == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final Sync sync;
|
||||
|
||||
/**
|
||||
* Constructs a {@code CountDownLatch} initialized with the given count.
|
||||
*
|
||||
* @param count the number of times {@link #countDown} must be invoked
|
||||
* before threads can pass through {@link #await}
|
||||
* @throws IllegalArgumentException if {@code count} is negative
|
||||
*/
|
||||
public CountDownLatch(int count) {
|
||||
if (count < 0) throw new IllegalArgumentException("count < 0");
|
||||
this.sync = new Sync(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until the latch has counted down to
|
||||
* zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>If the current count is zero then this method returns immediately.
|
||||
*
|
||||
* <p>If the current count is greater than zero then the current
|
||||
* thread becomes disabled for thread scheduling purposes and lies
|
||||
* dormant until one of two things happen:
|
||||
* <ul>
|
||||
* <li>The count reaches zero due to invocations of the
|
||||
* {@link #countDown} method; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread.
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* while waiting
|
||||
*/
|
||||
public void await() throws InterruptedException {
|
||||
sync.acquireSharedInterruptibly(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until the latch has counted down to
|
||||
* zero, unless the thread is {@linkplain Thread#interrupt interrupted},
|
||||
* or the specified waiting time elapses.
|
||||
*
|
||||
* <p>If the current count is zero then this method returns immediately
|
||||
* with the value {@code true}.
|
||||
*
|
||||
* <p>If the current count is greater than zero then the current
|
||||
* thread becomes disabled for thread scheduling purposes and lies
|
||||
* dormant until one of three things happen:
|
||||
* <ul>
|
||||
* <li>The count reaches zero due to invocations of the
|
||||
* {@link #countDown} method; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
* <li>The specified waiting time elapses.
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the count reaches zero then the method returns with the
|
||||
* value {@code true}.
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* <p>If the specified waiting time elapses then the value {@code false}
|
||||
* is returned. If the time is less than or equal to zero, the method
|
||||
* will not wait at all.
|
||||
*
|
||||
* @param timeout the maximum time to wait
|
||||
* @param unit the time unit of the {@code timeout} argument
|
||||
* @return {@code true} if the count reached zero and {@code false}
|
||||
* if the waiting time elapsed before the count reached zero
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* while waiting
|
||||
*/
|
||||
public boolean await(long timeout, TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrements the count of the latch, releasing all waiting threads if
|
||||
* the count reaches zero.
|
||||
*
|
||||
* <p>If the current count is greater than zero then it is decremented.
|
||||
* If the new count is zero then all waiting threads are re-enabled for
|
||||
* thread scheduling purposes.
|
||||
*
|
||||
* <p>If the current count equals zero then nothing happens.
|
||||
*/
|
||||
public void countDown() {
|
||||
sync.releaseShared(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current count.
|
||||
*
|
||||
* <p>This method is typically used for debugging and testing purposes.
|
||||
*
|
||||
* @return the current count
|
||||
*/
|
||||
public long getCount() {
|
||||
return sync.getCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string identifying this latch, as well as its state.
|
||||
* The state, in brackets, includes the String {@code "Count ="}
|
||||
* followed by the current count.
|
||||
*
|
||||
* @return a string identifying this latch, as well as its state
|
||||
*/
|
||||
public String toString() {
|
||||
return super.toString() + "[Count = " + sync.getCount() + "]";
|
||||
}
|
||||
}
|
||||
767
jdkSrc/jdk8/java/util/concurrent/CountedCompleter.java
Normal file
767
jdkSrc/jdk8/java/util/concurrent/CountedCompleter.java
Normal file
@@ -0,0 +1,767 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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(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
|
||||
* {@link #compareAndSetPendingCount}. Upon invocation of {@link
|
||||
* #tryComplete}, if the pending action count is nonzero, it is
|
||||
* decremented; otherwise, the completion action is performed, and if
|
||||
* this completer itself has a completer, the process is continued
|
||||
* with its completer. As is the case with related synchronization
|
||||
* components such as {@link java.util.concurrent.Phaser Phaser} and
|
||||
* {@link java.util.concurrent.Semaphore Semaphore}, these methods
|
||||
* affect only internal counts; they do not establish any further
|
||||
* internal bookkeeping. In particular, the identities of pending
|
||||
* tasks are not maintained. As illustrated below, you can create
|
||||
* subclasses that do record some or all pending tasks or their
|
||||
* results when needed. As illustrated below, utility methods
|
||||
* supporting customization of completion traversals are also
|
||||
* provided. However, because CountedCompleters provide only basic
|
||||
* synchronization mechanisms, it may be useful to create further
|
||||
* abstract subclasses that maintain linkages, fields, and additional
|
||||
* support methods appropriate for a set of related usages.
|
||||
*
|
||||
* <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(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
|
||||
* will always return {@code null} as a result value. In other cases,
|
||||
* you should override method {@link #getRawResult} to provide a
|
||||
* result from {@code join(), invoke()}, and related methods. In
|
||||
* general, this method should return the value of a field (or a
|
||||
* function of one or more fields) of the CountedCompleter object that
|
||||
* holds the result upon completion. Method {@link #setRawResult} by
|
||||
* default plays no role in CountedCompleters. It is possible, but
|
||||
* rarely applicable, to override this method to maintain other
|
||||
* objects or fields holding result data.
|
||||
*
|
||||
* <p>A CountedCompleter that does not itself have a completer (i.e.,
|
||||
* one for which {@link #getCompleter} returns {@code null}) can be
|
||||
* used as a regular ForkJoinTask with this added functionality.
|
||||
* However, any completer that in turn has another completer serves
|
||||
* 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(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>
|
||||
*
|
||||
* <p><b>Parallel recursive decomposition.</b> CountedCompleters may
|
||||
* be arranged in trees similar to those often used with {@link
|
||||
* RecursiveAction}s, although the constructions involved in setting
|
||||
* them up typically vary. Here, the completer of each task is its
|
||||
* parent in the computation tree. Even though they entail a bit more
|
||||
* bookkeeping, CountedCompleters may be better choices when applying
|
||||
* a possibly time-consuming operation (that cannot be further
|
||||
* subdivided) to each element of an array or collection; especially
|
||||
* when the operation takes a significantly different amount of time
|
||||
* to complete for some elements than others, either because of
|
||||
* intrinsic variation (for example I/O) or auxiliary effects such as
|
||||
* garbage collection. Because CountedCompleters provide their own
|
||||
* continuations, other threads need not block waiting to perform
|
||||
* them.
|
||||
*
|
||||
* <p>For example, here is an initial version of a class that uses
|
||||
* divide-by-two recursive decomposition to divide work into single
|
||||
* pieces (leaf tasks). Even when work is split into individual calls,
|
||||
* tree-based techniques are usually preferable to directly forking
|
||||
* leaf tasks, because they reduce inter-thread communication and
|
||||
* 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
|
||||
* (here, implicitly using the {@link ForkJoinPool#commonPool()}).
|
||||
*
|
||||
* <pre> {@code
|
||||
* class MyOperation<E> { void apply(E e) { ... } }
|
||||
*
|
||||
* class ForEach<E> extends CountedCompleter<Void> {
|
||||
*
|
||||
* public static <E> void forEach(E[] array, MyOperation<E> op) {
|
||||
* new ForEach<E>(null, array, op, 0, array.length).invoke();
|
||||
* }
|
||||
*
|
||||
* final E[] array; final MyOperation<E> op; final int lo, hi;
|
||||
* ForEach(CountedCompleter<?> p, E[] array, MyOperation<E> op, int lo, int hi) {
|
||||
* super(p);
|
||||
* this.array = array; this.op = op; this.lo = lo; this.hi = hi;
|
||||
* }
|
||||
*
|
||||
* public void compute() { // version 1
|
||||
* if (hi - lo >= 2) {
|
||||
* int mid = (lo + hi) >>> 1;
|
||||
* setPendingCount(2); // must set pending count before fork
|
||||
* new ForEach(this, array, op, mid, hi).fork(); // right child
|
||||
* new ForEach(this, array, op, lo, mid).fork(); // left child
|
||||
* }
|
||||
* else if (hi > lo)
|
||||
* op.apply(array[lo]);
|
||||
* tryComplete();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* This design can be improved by noticing that in the recursive case,
|
||||
* the task has nothing to do after forking its right task, so can
|
||||
* directly invoke its left task before returning. (This is an analog
|
||||
* of tail recursion removal.) Also, because the task returns upon
|
||||
* executing its left task (rather than falling through to invoke
|
||||
* {@code tryComplete}) the pending count is set to one:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class ForEach<E> ...
|
||||
* public void compute() { // version 2
|
||||
* if (hi - lo >= 2) {
|
||||
* int mid = (lo + hi) >>> 1;
|
||||
* setPendingCount(1); // only one pending
|
||||
* new ForEach(this, array, op, mid, hi).fork(); // right child
|
||||
* new ForEach(this, array, op, lo, mid).compute(); // direct invoke
|
||||
* }
|
||||
* else {
|
||||
* if (hi > lo)
|
||||
* op.apply(array[lo]);
|
||||
* tryComplete();
|
||||
* }
|
||||
* }
|
||||
* }</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(CountedCompleter)} method,
|
||||
* {@code tryComplete()} can be replaced with {@link #propagateCompletion}.
|
||||
*
|
||||
* <pre> {@code
|
||||
* class ForEach<E> ...
|
||||
* public void compute() { // version 3
|
||||
* int l = lo, h = hi;
|
||||
* while (h - l >= 2) {
|
||||
* int mid = (l + h) >>> 1;
|
||||
* addToPendingCount(1);
|
||||
* new ForEach(this, array, op, mid, h).fork(); // right child
|
||||
* h = mid;
|
||||
* }
|
||||
* if (h > l)
|
||||
* op.apply(array[l]);
|
||||
* propagateCompletion();
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* Additional improvements of such classes might entail precomputing
|
||||
* pending counts so that they can be established in constructors,
|
||||
* specializing classes for leaf steps, subdividing by say, four,
|
||||
* instead of two per iteration, and using an adaptive threshold
|
||||
* instead of always subdividing down to single elements.
|
||||
*
|
||||
* <p><b>Searching.</b> A tree of CountedCompleters can search for a
|
||||
* value or property in different parts of a data structure, and
|
||||
* report a result in an {@link
|
||||
* java.util.concurrent.atomic.AtomicReference AtomicReference} as
|
||||
* soon as one is found. The others can poll the result to avoid
|
||||
* unnecessary work. (You could additionally {@linkplain #cancel
|
||||
* cancel} other tasks, but it is usually simpler and more efficient
|
||||
* to just let them notice that the result is set and if so skip
|
||||
* further processing.) Illustrating again with an array using full
|
||||
* partitioning (again, in practice, leaf tasks will almost always
|
||||
* process more than one element):
|
||||
*
|
||||
* <pre> {@code
|
||||
* class Searcher<E> extends CountedCompleter<E> {
|
||||
* final E[] array; final AtomicReference<E> result; final int lo, hi;
|
||||
* Searcher(CountedCompleter<?> p, E[] array, AtomicReference<E> result, int lo, int hi) {
|
||||
* super(p);
|
||||
* this.array = array; this.result = result; this.lo = lo; this.hi = hi;
|
||||
* }
|
||||
* public E getRawResult() { return result.get(); }
|
||||
* public void compute() { // similar to ForEach version 3
|
||||
* int l = lo, h = hi;
|
||||
* while (result.get() == null && h >= l) {
|
||||
* if (h - l >= 2) {
|
||||
* int mid = (l + h) >>> 1;
|
||||
* addToPendingCount(1);
|
||||
* new Searcher(this, array, result, mid, h).fork();
|
||||
* h = mid;
|
||||
* }
|
||||
* else {
|
||||
* E x = array[l];
|
||||
* if (matches(x) && result.compareAndSet(null, x))
|
||||
* quietlyCompleteRoot(); // root task is now joinable
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
* tryComplete(); // normally complete whether or not found
|
||||
* }
|
||||
* boolean matches(E e) { ... } // return true if found
|
||||
*
|
||||
* public static <E> E search(E[] array) {
|
||||
* return new Searcher<E>(null, array, new AtomicReference<E>(), 0, array.length).invoke();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* In this example, as well as others in which tasks have no other
|
||||
* effects except to compareAndSet a common result, the trailing
|
||||
* unconditional invocation of {@code tryComplete} could be made
|
||||
* conditional ({@code if (result.get() == null) tryComplete();})
|
||||
* because no further bookkeeping is required to manage completions
|
||||
* once the root task completes.
|
||||
*
|
||||
* <p><b>Recording subtasks.</b> CountedCompleter tasks that combine
|
||||
* results of multiple subtasks usually need to access these results
|
||||
* 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
|
||||
* sibling, so that it can be accessed in method {@code onCompletion}.
|
||||
* This technique applies to reductions in which the order of
|
||||
* combining left and right results does not matter; ordered
|
||||
* reductions require explicit left/right designations. Variants of
|
||||
* other streamlinings seen in the above examples may also apply.
|
||||
*
|
||||
* <pre> {@code
|
||||
* class MyMapper<E> { E apply(E v) { ... } }
|
||||
* class MyReducer<E> { E apply(E x, E y) { ... } }
|
||||
* class MapReducer<E> extends CountedCompleter<E> {
|
||||
* final E[] array; final MyMapper<E> mapper;
|
||||
* final MyReducer<E> reducer; final int lo, hi;
|
||||
* MapReducer<E> sibling;
|
||||
* E result;
|
||||
* MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
|
||||
* MyReducer<E> reducer, int lo, int hi) {
|
||||
* super(p);
|
||||
* this.array = array; this.mapper = mapper;
|
||||
* this.reducer = reducer; this.lo = lo; this.hi = hi;
|
||||
* }
|
||||
* public void compute() {
|
||||
* if (hi - lo >= 2) {
|
||||
* int mid = (lo + hi) >>> 1;
|
||||
* MapReducer<E> left = new MapReducer(this, array, mapper, reducer, lo, mid);
|
||||
* MapReducer<E> right = new MapReducer(this, array, mapper, reducer, mid, hi);
|
||||
* left.sibling = right;
|
||||
* right.sibling = left;
|
||||
* setPendingCount(1); // only right is pending
|
||||
* right.fork();
|
||||
* left.compute(); // directly execute left
|
||||
* }
|
||||
* else {
|
||||
* if (hi > lo)
|
||||
* result = mapper.apply(array[lo]);
|
||||
* tryComplete();
|
||||
* }
|
||||
* }
|
||||
* public void onCompletion(CountedCompleter<?> caller) {
|
||||
* if (caller != this) {
|
||||
* MapReducer<E> child = (MapReducer<E>)caller;
|
||||
* MapReducer<E> sib = child.sibling;
|
||||
* if (sib == null || sib.result == null)
|
||||
* result = child.result;
|
||||
* else
|
||||
* result = reducer.apply(child.result, sib.result);
|
||||
* }
|
||||
* }
|
||||
* public E getRawResult() { return result; }
|
||||
*
|
||||
* public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
|
||||
* return new MapReducer<E>(null, array, mapper, reducer,
|
||||
* 0, array.length).invoke();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* Here, method {@code onCompletion} takes a form common to many
|
||||
* completion designs that combine results. This callback-style method
|
||||
* is triggered once per task, in either of the two different contexts
|
||||
* in which the pending count is, or becomes, zero: (1) by a task
|
||||
* itself, if its pending count is zero upon invocation of {@code
|
||||
* tryComplete}, or (2) by any of its subtasks when they complete and
|
||||
* decrement the pending count to zero. The {@code caller} argument
|
||||
* distinguishes cases. Most often, when the caller is {@code this},
|
||||
* no action is necessary. Otherwise the caller argument can be used
|
||||
* (usually via a cast) to supply a value (and/or links to other
|
||||
* values) to be combined. Assuming proper use of pending counts, the
|
||||
* actions inside {@code onCompletion} occur (once) upon completion of
|
||||
* a task and its subtasks. No additional synchronization is required
|
||||
* within this method to ensure thread safety of accesses to fields of
|
||||
* this task or other completed tasks.
|
||||
*
|
||||
* <p><b>Completion Traversals</b>. If using {@code onCompletion} to
|
||||
* process completions is inapplicable or inconvenient, you can use
|
||||
* methods {@link #firstComplete} and {@link #nextComplete} to create
|
||||
* custom traversals. For example, to define a MapReducer that only
|
||||
* splits out right-hand tasks in the form of the third ForEach
|
||||
* example, the completions must cooperatively reduce along
|
||||
* unexhausted subtask links, which can be done as follows:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class MapReducer<E> extends CountedCompleter<E> { // version 2
|
||||
* final E[] array; final MyMapper<E> mapper;
|
||||
* final MyReducer<E> reducer; final int lo, hi;
|
||||
* MapReducer<E> forks, next; // record subtask forks in list
|
||||
* E result;
|
||||
* MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
|
||||
* MyReducer<E> reducer, int lo, int hi, MapReducer<E> next) {
|
||||
* super(p);
|
||||
* this.array = array; this.mapper = mapper;
|
||||
* this.reducer = reducer; this.lo = lo; this.hi = hi;
|
||||
* this.next = next;
|
||||
* }
|
||||
* public void compute() {
|
||||
* int l = lo, h = hi;
|
||||
* while (h - l >= 2) {
|
||||
* int mid = (l + h) >>> 1;
|
||||
* addToPendingCount(1);
|
||||
* (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork();
|
||||
* h = mid;
|
||||
* }
|
||||
* if (h > l)
|
||||
* result = mapper.apply(array[l]);
|
||||
* // process completions by reducing along and advancing subtask links
|
||||
* for (CountedCompleter<?> c = firstComplete(); c != null; c = c.nextComplete()) {
|
||||
* for (MapReducer t = (MapReducer)c, s = t.forks; s != null; s = t.forks = s.next)
|
||||
* t.result = reducer.apply(t.result, s.result);
|
||||
* }
|
||||
* }
|
||||
* public E getRawResult() { return result; }
|
||||
*
|
||||
* public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
|
||||
* return new MapReducer<E>(null, array, mapper, reducer,
|
||||
* 0, array.length, null).invoke();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <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 or more async tasks
|
||||
* triggers another async task. For example:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class HeaderBuilder extends CountedCompleter<...> { ... }
|
||||
* class BodyBuilder extends CountedCompleter<...> { ... }
|
||||
* class PacketSender extends CountedCompleter<...> {
|
||||
* PacketSender(...) { super(null, 1); ... } // trigger on second completion
|
||||
* public void compute() { } // never called
|
||||
* public void onCompletion(CountedCompleter<?> caller) { sendPacket(); }
|
||||
* }
|
||||
* // sample use:
|
||||
* PacketSender p = new PacketSender();
|
||||
* new HeaderBuilder(p, ...).fork();
|
||||
* new BodyBuilder(p, ...).fork();
|
||||
* }</pre>
|
||||
*
|
||||
* @since 1.8
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
|
||||
private static final long serialVersionUID = 5232453752276485070L;
|
||||
|
||||
/** This task's completer, or null if none */
|
||||
final CountedCompleter<?> completer;
|
||||
/** The number of pending tasks until completion */
|
||||
volatile int pending;
|
||||
|
||||
/**
|
||||
* Creates a new CountedCompleter with the given completer
|
||||
* and initial pending count.
|
||||
*
|
||||
* @param completer this task's completer, or {@code null} if none
|
||||
* @param initialPendingCount the initial pending count
|
||||
*/
|
||||
protected CountedCompleter(CountedCompleter<?> completer,
|
||||
int initialPendingCount) {
|
||||
this.completer = completer;
|
||||
this.pending = initialPendingCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CountedCompleter with the given completer
|
||||
* and an initial pending count of zero.
|
||||
*
|
||||
* @param completer this task's completer, or {@code null} if none
|
||||
*/
|
||||
protected CountedCompleter(CountedCompleter<?> completer) {
|
||||
this.completer = completer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CountedCompleter with no completer
|
||||
* and an initial pending count of zero.
|
||||
*/
|
||||
protected CountedCompleter() {
|
||||
this.completer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main computation performed by this task.
|
||||
*/
|
||||
public abstract void compute();
|
||||
|
||||
/**
|
||||
* Performs an action when method {@link #tryComplete} is invoked
|
||||
* and the pending count is zero, or when the unconditional
|
||||
* method {@link #complete} is invoked. By default, this method
|
||||
* does nothing. You can distinguish cases by checking the
|
||||
* identity of the given caller argument. If not equal to {@code
|
||||
* this}, then it is typically a subtask that may contain results
|
||||
* (and/or links to other results) to combine.
|
||||
*
|
||||
* @param caller the task invoking this method (which may
|
||||
* be this task itself)
|
||||
*/
|
||||
public void onCompletion(CountedCompleter<?> caller) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {@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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the completer established in this task's constructor,
|
||||
* or {@code null} if none.
|
||||
*
|
||||
* @return the completer
|
||||
*/
|
||||
public final CountedCompleter<?> getCompleter() {
|
||||
return completer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current pending count.
|
||||
*
|
||||
* @return the current pending count
|
||||
*/
|
||||
public final int getPendingCount() {
|
||||
return pending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pending count to the given value.
|
||||
*
|
||||
* @param count the count
|
||||
*/
|
||||
public final void setPendingCount(int count) {
|
||||
pending = count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds (atomically) the given value to the pending count.
|
||||
*
|
||||
* @param delta the value to add
|
||||
*/
|
||||
public final void addToPendingCount(int delta) {
|
||||
U.getAndAddInt(this, PENDING, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets (atomically) the pending count to the given count only if
|
||||
* it currently holds the given expected value.
|
||||
*
|
||||
* @param expected the expected value
|
||||
* @param count the new value
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public final boolean compareAndSetPendingCount(int expected, int count) {
|
||||
return U.compareAndSwapInt(this, PENDING, expected, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pending count is nonzero, (atomically) decrements it.
|
||||
*
|
||||
* @return the initial (undecremented) pending count holding on entry
|
||||
* to this method
|
||||
*/
|
||||
public final int decrementPendingCountUnlessZero() {
|
||||
int c;
|
||||
do {} while ((c = pending) != 0 &&
|
||||
!U.compareAndSwapInt(this, PENDING, c, c - 1));
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root of the current computation; i.e., this
|
||||
* task if it has no completer, else its completer's root.
|
||||
*
|
||||
* @return the root of the current computation
|
||||
*/
|
||||
public final CountedCompleter<?> getRoot() {
|
||||
CountedCompleter<?> a = this, p;
|
||||
while ((p = a.completer) != null)
|
||||
a = p;
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pending count is nonzero, decrements the count;
|
||||
* 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;
|
||||
for (int c;;) {
|
||||
if ((c = a.pending) == 0) {
|
||||
a.onCompletion(s);
|
||||
if ((a = (s = a).completer) == null) {
|
||||
s.quietlyComplete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@link #tryComplete} but does not invoke {@link
|
||||
* #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;
|
||||
for (int c;;) {
|
||||
if ((c = a.pending) == 0) {
|
||||
if ((a = (s = a).completer) == null) {
|
||||
s.quietlyComplete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* However, in the common (and recommended) case in which {@code
|
||||
* setRawResult} is not overridden, this effect can be obtained
|
||||
* more simply using {@code quietlyCompleteRoot();}.
|
||||
*
|
||||
* @param rawResult the raw result
|
||||
*/
|
||||
public void complete(T rawResult) {
|
||||
CountedCompleter<?> p;
|
||||
setRawResult(rawResult);
|
||||
onCompletion(this);
|
||||
quietlyComplete();
|
||||
if ((p = completer) != null)
|
||||
p.tryComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* If this task's pending count is zero, returns this task;
|
||||
* otherwise decrements its pending count and returns {@code
|
||||
* null}. This method is designed to be used with {@link
|
||||
* #nextComplete} in completion traversal loops.
|
||||
*
|
||||
* @return this task, if pending count was zero, else {@code null}
|
||||
*/
|
||||
public final CountedCompleter<?> firstComplete() {
|
||||
for (int c;;) {
|
||||
if ((c = pending) == 0)
|
||||
return this;
|
||||
else if (U.compareAndSwapInt(this, PENDING, c, c - 1))
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this task does not have a completer, invokes {@link
|
||||
* ForkJoinTask#quietlyComplete} and returns {@code null}. Or, if
|
||||
* 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:
|
||||
*
|
||||
* <pre> {@code
|
||||
* for (CountedCompleter<?> c = firstComplete();
|
||||
* c != null;
|
||||
* c = c.nextComplete()) {
|
||||
* // ... process c ...
|
||||
* }}</pre>
|
||||
*
|
||||
* @return the completer, or {@code null} if none
|
||||
*/
|
||||
public final CountedCompleter<?> nextComplete() {
|
||||
CountedCompleter<?> p;
|
||||
if ((p = completer) != null)
|
||||
return p.firstComplete();
|
||||
else {
|
||||
quietlyComplete();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@code getRoot().quietlyComplete()}.
|
||||
*/
|
||||
public final void quietlyCompleteRoot() {
|
||||
for (CountedCompleter<?> a = this, p;;) {
|
||||
if ((p = a.completer) == null) {
|
||||
a.quietlyComplete();
|
||||
return;
|
||||
}
|
||||
a = p;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) == EXCEPTIONAL)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements execution conventions for CountedCompleters.
|
||||
*/
|
||||
protected final boolean exec() {
|
||||
compute();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of the computation. By default
|
||||
* returns {@code null}, which is appropriate for {@code Void}
|
||||
* actions, but in other cases should be overridden, almost
|
||||
* always to return a field or function of a field that
|
||||
* holds the result upon completion.
|
||||
*
|
||||
* @return the result of the computation
|
||||
*/
|
||||
public T getRawResult() { return null; }
|
||||
|
||||
/**
|
||||
* A method that result-bearing CountedCompleters may optionally
|
||||
* use to help maintain result data. By default, does nothing.
|
||||
* Overrides are not recommended. However, if this method is
|
||||
* overridden to update existing objects or fields, then it must
|
||||
* in general be defined to be thread-safe.
|
||||
*/
|
||||
protected void setRawResult(T t) { }
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe U;
|
||||
private static final long PENDING;
|
||||
static {
|
||||
try {
|
||||
U = sun.misc.Unsafe.getUnsafe();
|
||||
PENDING = U.objectFieldOffset
|
||||
(CountedCompleter.class.getDeclaredField("pending"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
491
jdkSrc/jdk8/java/util/concurrent/CyclicBarrier.java
Normal file
491
jdkSrc/jdk8/java/util/concurrent/CyclicBarrier.java
Normal file
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* A synchronization aid that allows a set of threads to all wait for
|
||||
* each other to reach a common barrier point. CyclicBarriers are
|
||||
* useful in programs involving a fixed sized party of threads that
|
||||
* must occasionally wait for each other. The barrier is called
|
||||
* <em>cyclic</em> because it can be re-used after the waiting threads
|
||||
* are released.
|
||||
*
|
||||
* <p>A {@code CyclicBarrier} supports an optional {@link Runnable} command
|
||||
* that is run once per barrier point, after the last thread in the party
|
||||
* arrives, but before any threads are released.
|
||||
* This <em>barrier action</em> is useful
|
||||
* for updating shared-state before any of the parties continue.
|
||||
*
|
||||
* <p><b>Sample usage:</b> Here is an example of using a barrier in a
|
||||
* parallel decomposition design:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class Solver {
|
||||
* final int N;
|
||||
* final float[][] data;
|
||||
* final CyclicBarrier barrier;
|
||||
*
|
||||
* class Worker implements Runnable {
|
||||
* int myRow;
|
||||
* Worker(int row) { myRow = row; }
|
||||
* public void run() {
|
||||
* while (!done()) {
|
||||
* processRow(myRow);
|
||||
*
|
||||
* try {
|
||||
* barrier.await();
|
||||
* } catch (InterruptedException ex) {
|
||||
* return;
|
||||
* } catch (BrokenBarrierException ex) {
|
||||
* return;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* public Solver(float[][] matrix) {
|
||||
* data = matrix;
|
||||
* N = matrix.length;
|
||||
* Runnable barrierAction =
|
||||
* new Runnable() { public void run() { mergeRows(...); }};
|
||||
* barrier = new CyclicBarrier(N, barrierAction);
|
||||
*
|
||||
* List<Thread> threads = new ArrayList<Thread>(N);
|
||||
* for (int i = 0; i < N; i++) {
|
||||
* Thread thread = new Thread(new Worker(i));
|
||||
* threads.add(thread);
|
||||
* thread.start();
|
||||
* }
|
||||
*
|
||||
* // wait until done
|
||||
* for (Thread thread : threads)
|
||||
* thread.join();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* Here, each worker thread processes a row of the matrix then waits at the
|
||||
* barrier until all rows have been processed. When all rows are processed
|
||||
* the supplied {@link Runnable} barrier action is executed and merges the
|
||||
* rows. If the merger
|
||||
* determines that a solution has been found then {@code done()} will return
|
||||
* {@code true} and each worker will terminate.
|
||||
*
|
||||
* <p>If the barrier action does not rely on the parties being suspended when
|
||||
* it is executed, then any of the threads in the party could execute that
|
||||
* action when it is released. To facilitate this, each invocation of
|
||||
* {@link #await} returns the arrival index of that thread at the barrier.
|
||||
* You can then choose which thread should execute the barrier action, for
|
||||
* example:
|
||||
* <pre> {@code
|
||||
* if (barrier.await() == 0) {
|
||||
* // log the completion of this iteration
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>The {@code CyclicBarrier} uses an all-or-none breakage model
|
||||
* for failed synchronization attempts: If a thread leaves a barrier
|
||||
* point prematurely because of interruption, failure, or timeout, all
|
||||
* other threads waiting at that barrier point will also leave
|
||||
* abnormally via {@link BrokenBarrierException} (or
|
||||
* {@link InterruptedException} if they too were interrupted at about
|
||||
* the same time).
|
||||
*
|
||||
* <p>Memory consistency effects: Actions in a thread prior to calling
|
||||
* {@code await()}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* actions that are part of the barrier action, which in turn
|
||||
* <i>happen-before</i> actions following a successful return from the
|
||||
* corresponding {@code await()} in other threads.
|
||||
*
|
||||
* @since 1.5
|
||||
* @see CountDownLatch
|
||||
*
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class CyclicBarrier {
|
||||
/**
|
||||
* Each use of the barrier is represented as a generation instance.
|
||||
* The generation changes whenever the barrier is tripped, or
|
||||
* is reset. There can be many generations associated with threads
|
||||
* using the barrier - due to the non-deterministic way the lock
|
||||
* may be allocated to waiting threads - but only one of these
|
||||
* can be active at a time (the one to which {@code count} applies)
|
||||
* and all the rest are either broken or tripped.
|
||||
* There need not be an active generation if there has been a break
|
||||
* but no subsequent reset.
|
||||
*/
|
||||
private static class Generation {
|
||||
boolean broken = false;
|
||||
}
|
||||
|
||||
/** The lock for guarding barrier entry */
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
/** Condition to wait on until tripped */
|
||||
private final Condition trip = lock.newCondition();
|
||||
/** The number of parties */
|
||||
private final int parties;
|
||||
/* The command to run when tripped */
|
||||
private final Runnable barrierCommand;
|
||||
/** The current generation */
|
||||
private Generation generation = new Generation();
|
||||
|
||||
/**
|
||||
* Number of parties still waiting. Counts down from parties to 0
|
||||
* on each generation. It is reset to parties on each new
|
||||
* generation or when broken.
|
||||
*/
|
||||
private int count;
|
||||
|
||||
/**
|
||||
* Updates state on barrier trip and wakes up everyone.
|
||||
* Called only while holding lock.
|
||||
*/
|
||||
private void nextGeneration() {
|
||||
// signal completion of last generation
|
||||
trip.signalAll();
|
||||
// set up next generation
|
||||
count = parties;
|
||||
generation = new Generation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets current barrier generation as broken and wakes up everyone.
|
||||
* Called only while holding lock.
|
||||
*/
|
||||
private void breakBarrier() {
|
||||
generation.broken = true;
|
||||
count = parties;
|
||||
trip.signalAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Main barrier code, covering the various policies.
|
||||
*/
|
||||
private int dowait(boolean timed, long nanos)
|
||||
throws InterruptedException, BrokenBarrierException,
|
||||
TimeoutException {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
final Generation g = generation;
|
||||
|
||||
if (g.broken)
|
||||
throw new BrokenBarrierException();
|
||||
|
||||
if (Thread.interrupted()) {
|
||||
breakBarrier();
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
int index = --count;
|
||||
if (index == 0) { // tripped
|
||||
boolean ranAction = false;
|
||||
try {
|
||||
final Runnable command = barrierCommand;
|
||||
if (command != null)
|
||||
command.run();
|
||||
ranAction = true;
|
||||
nextGeneration();
|
||||
return 0;
|
||||
} finally {
|
||||
if (!ranAction)
|
||||
breakBarrier();
|
||||
}
|
||||
}
|
||||
|
||||
// loop until tripped, broken, interrupted, or timed out
|
||||
for (;;) {
|
||||
try {
|
||||
if (!timed)
|
||||
trip.await();
|
||||
else if (nanos > 0L)
|
||||
nanos = trip.awaitNanos(nanos);
|
||||
} catch (InterruptedException ie) {
|
||||
if (g == generation && ! g.broken) {
|
||||
breakBarrier();
|
||||
throw ie;
|
||||
} else {
|
||||
// We're about to finish waiting even if we had not
|
||||
// been interrupted, so this interrupt is deemed to
|
||||
// "belong" to subsequent execution.
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
if (g.broken)
|
||||
throw new BrokenBarrierException();
|
||||
|
||||
if (g != generation)
|
||||
return index;
|
||||
|
||||
if (timed && nanos <= 0L) {
|
||||
breakBarrier();
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code CyclicBarrier} that will trip when the
|
||||
* given number of parties (threads) are waiting upon it, and which
|
||||
* will execute the given barrier action when the barrier is tripped,
|
||||
* performed by the last thread entering the barrier.
|
||||
*
|
||||
* @param parties the number of threads that must invoke {@link #await}
|
||||
* before the barrier is tripped
|
||||
* @param barrierAction the command to execute when the barrier is
|
||||
* tripped, or {@code null} if there is no action
|
||||
* @throws IllegalArgumentException if {@code parties} is less than 1
|
||||
*/
|
||||
public CyclicBarrier(int parties, Runnable barrierAction) {
|
||||
if (parties <= 0) throw new IllegalArgumentException();
|
||||
this.parties = parties;
|
||||
this.count = parties;
|
||||
this.barrierCommand = barrierAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code CyclicBarrier} that will trip when the
|
||||
* given number of parties (threads) are waiting upon it, and
|
||||
* does not perform a predefined action when the barrier is tripped.
|
||||
*
|
||||
* @param parties the number of threads that must invoke {@link #await}
|
||||
* before the barrier is tripped
|
||||
* @throws IllegalArgumentException if {@code parties} is less than 1
|
||||
*/
|
||||
public CyclicBarrier(int parties) {
|
||||
this(parties, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of parties required to trip this barrier.
|
||||
*
|
||||
* @return the number of parties required to trip this barrier
|
||||
*/
|
||||
public int getParties() {
|
||||
return parties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until all {@linkplain #getParties parties} have invoked
|
||||
* {@code await} on this barrier.
|
||||
*
|
||||
* <p>If the current thread is not the last to arrive then it is
|
||||
* disabled for thread scheduling purposes and lies dormant until
|
||||
* one of the following things happens:
|
||||
* <ul>
|
||||
* <li>The last thread arrives; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* one of the other waiting threads; or
|
||||
* <li>Some other thread times out while waiting for barrier; or
|
||||
* <li>Some other thread invokes {@link #reset} on this barrier.
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* <p>If the barrier is {@link #reset} while any thread is waiting,
|
||||
* or if the barrier {@linkplain #isBroken is broken} when
|
||||
* {@code await} is invoked, or while any thread is waiting, then
|
||||
* {@link BrokenBarrierException} is thrown.
|
||||
*
|
||||
* <p>If any thread is {@linkplain Thread#interrupt interrupted} while waiting,
|
||||
* then all other waiting threads will throw
|
||||
* {@link BrokenBarrierException} and the barrier is placed in the broken
|
||||
* state.
|
||||
*
|
||||
* <p>If the current thread is the last thread to arrive, and a
|
||||
* non-null barrier action was supplied in the constructor, then the
|
||||
* current thread runs the action before allowing the other threads to
|
||||
* continue.
|
||||
* If an exception occurs during the barrier action then that exception
|
||||
* will be propagated in the current thread and the barrier is placed in
|
||||
* the broken state.
|
||||
*
|
||||
* @return the arrival index of the current thread, where index
|
||||
* {@code getParties() - 1} indicates the first
|
||||
* to arrive and zero indicates the last to arrive
|
||||
* @throws InterruptedException if the current thread was interrupted
|
||||
* while waiting
|
||||
* @throws BrokenBarrierException if <em>another</em> thread was
|
||||
* interrupted or timed out while the current thread was
|
||||
* waiting, or the barrier was reset, or the barrier was
|
||||
* broken when {@code await} was called, or the barrier
|
||||
* action (if present) failed due to an exception
|
||||
*/
|
||||
public int await() throws InterruptedException, BrokenBarrierException {
|
||||
try {
|
||||
return dowait(false, 0L);
|
||||
} catch (TimeoutException toe) {
|
||||
throw new Error(toe); // cannot happen
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until all {@linkplain #getParties parties} have invoked
|
||||
* {@code await} on this barrier, or the specified waiting time elapses.
|
||||
*
|
||||
* <p>If the current thread is not the last to arrive then it is
|
||||
* disabled for thread scheduling purposes and lies dormant until
|
||||
* one of the following things happens:
|
||||
* <ul>
|
||||
* <li>The last thread arrives; or
|
||||
* <li>The specified timeout elapses; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* one of the other waiting threads; or
|
||||
* <li>Some other thread times out while waiting for barrier; or
|
||||
* <li>Some other thread invokes {@link #reset} on this barrier.
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* <p>If the specified waiting time elapses then {@link TimeoutException}
|
||||
* is thrown. If the time is less than or equal to zero, the
|
||||
* method will not wait at all.
|
||||
*
|
||||
* <p>If the barrier is {@link #reset} while any thread is waiting,
|
||||
* or if the barrier {@linkplain #isBroken is broken} when
|
||||
* {@code await} is invoked, or while any thread is waiting, then
|
||||
* {@link BrokenBarrierException} is thrown.
|
||||
*
|
||||
* <p>If any thread is {@linkplain Thread#interrupt interrupted} while
|
||||
* waiting, then all other waiting threads will throw {@link
|
||||
* BrokenBarrierException} and the barrier is placed in the broken
|
||||
* state.
|
||||
*
|
||||
* <p>If the current thread is the last thread to arrive, and a
|
||||
* non-null barrier action was supplied in the constructor, then the
|
||||
* current thread runs the action before allowing the other threads to
|
||||
* continue.
|
||||
* If an exception occurs during the barrier action then that exception
|
||||
* will be propagated in the current thread and the barrier is placed in
|
||||
* the broken state.
|
||||
*
|
||||
* @param timeout the time to wait for the barrier
|
||||
* @param unit the time unit of the timeout parameter
|
||||
* @return the arrival index of the current thread, where index
|
||||
* {@code getParties() - 1} indicates the first
|
||||
* to arrive and zero indicates the last to arrive
|
||||
* @throws InterruptedException if the current thread was interrupted
|
||||
* while waiting
|
||||
* @throws TimeoutException if the specified timeout elapses.
|
||||
* In this case the barrier will be broken.
|
||||
* @throws BrokenBarrierException if <em>another</em> thread was
|
||||
* interrupted or timed out while the current thread was
|
||||
* waiting, or the barrier was reset, or the barrier was broken
|
||||
* when {@code await} was called, or the barrier action (if
|
||||
* present) failed due to an exception
|
||||
*/
|
||||
public int await(long timeout, TimeUnit unit)
|
||||
throws InterruptedException,
|
||||
BrokenBarrierException,
|
||||
TimeoutException {
|
||||
return dowait(true, unit.toNanos(timeout));
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries if this barrier is in a broken state.
|
||||
*
|
||||
* @return {@code true} if one or more parties broke out of this
|
||||
* barrier due to interruption or timeout since
|
||||
* construction or the last reset, or a barrier action
|
||||
* failed due to an exception; {@code false} otherwise.
|
||||
*/
|
||||
public boolean isBroken() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
return generation.broken;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the barrier to its initial state. If any parties are
|
||||
* currently waiting at the barrier, they will return with a
|
||||
* {@link BrokenBarrierException}. Note that resets <em>after</em>
|
||||
* a breakage has occurred for other reasons can be complicated to
|
||||
* carry out; threads need to re-synchronize in some other way,
|
||||
* and choose one to perform the reset. It may be preferable to
|
||||
* instead create a new barrier for subsequent use.
|
||||
*/
|
||||
public void reset() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
breakBarrier(); // break the current generation
|
||||
nextGeneration(); // start a new generation
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of parties currently waiting at the barrier.
|
||||
* This method is primarily useful for debugging and assertions.
|
||||
*
|
||||
* @return the number of parties currently blocked in {@link #await}
|
||||
*/
|
||||
public int getNumberWaiting() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
return parties - count;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
557
jdkSrc/jdk8/java/util/concurrent/DelayQueue.java
Normal file
557
jdkSrc/jdk8/java/util/concurrent/DelayQueue.java
Normal file
@@ -0,0 +1,557 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* An unbounded {@linkplain BlockingQueue blocking queue} of
|
||||
* {@code Delayed} elements, in which an element can only be taken
|
||||
* when its delay has expired. The <em>head</em> of the queue is that
|
||||
* {@code Delayed} element whose delay expired furthest in the
|
||||
* past. If no delay has expired there is no head and {@code poll}
|
||||
* will return {@code null}. Expiration occurs when an element's
|
||||
* {@code getDelay(TimeUnit.NANOSECONDS)} method returns a value less
|
||||
* than or equal to zero. Even though unexpired elements cannot be
|
||||
* removed using {@code take} or {@code poll}, they are otherwise
|
||||
* treated as normal elements. For example, the {@code size} method
|
||||
* returns the count of both expired and unexpired elements.
|
||||
* This queue does not permit null elements.
|
||||
*
|
||||
* <p>This class and its iterator implement all of the
|
||||
* <em>optional</em> methods of the {@link Collection} and {@link
|
||||
* Iterator} interfaces. The Iterator provided in method {@link
|
||||
* #iterator()} is <em>not</em> guaranteed to traverse the elements of
|
||||
* the DelayQueue in any particular order.
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <E> the type of elements held in this collection
|
||||
*/
|
||||
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
|
||||
implements BlockingQueue<E> {
|
||||
|
||||
private final transient ReentrantLock lock = new ReentrantLock();
|
||||
private final PriorityQueue<E> q = new PriorityQueue<E>();
|
||||
|
||||
/**
|
||||
* Thread designated to wait for the element at the head of
|
||||
* the queue. This variant of the Leader-Follower pattern
|
||||
* (http://www.cs.wustl.edu/~schmidt/POSA/POSA2/) serves to
|
||||
* minimize unnecessary timed waiting. When a thread becomes
|
||||
* the leader, it waits only for the next delay to elapse, but
|
||||
* other threads await indefinitely. The leader thread must
|
||||
* signal some other thread before returning from take() or
|
||||
* poll(...), unless some other thread becomes leader in the
|
||||
* interim. Whenever the head of the queue is replaced with
|
||||
* an element with an earlier expiration time, the leader
|
||||
* field is invalidated by being reset to null, and some
|
||||
* waiting thread, but not necessarily the current leader, is
|
||||
* signalled. So waiting threads must be prepared to acquire
|
||||
* and lose leadership while waiting.
|
||||
*/
|
||||
private Thread leader = null;
|
||||
|
||||
/**
|
||||
* Condition signalled when a newer element becomes available
|
||||
* at the head of the queue or a new thread may need to
|
||||
* become leader.
|
||||
*/
|
||||
private final Condition available = lock.newCondition();
|
||||
|
||||
/**
|
||||
* Creates a new {@code DelayQueue} that is initially empty.
|
||||
*/
|
||||
public DelayQueue() {}
|
||||
|
||||
/**
|
||||
* Creates a {@code DelayQueue} initially containing the elements of the
|
||||
* given collection of {@link Delayed} instances.
|
||||
*
|
||||
* @param c the collection of elements to initially contain
|
||||
* @throws NullPointerException if the specified collection or any
|
||||
* of its elements are null
|
||||
*/
|
||||
public DelayQueue(Collection<? extends E> c) {
|
||||
this.addAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this delay queue.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @return {@code true} (as specified by {@link Collection#add})
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public boolean add(E e) {
|
||||
return offer(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this delay queue.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @return {@code true}
|
||||
* @throws NullPointerException if the specified element is null
|
||||
*/
|
||||
public boolean offer(E e) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
q.offer(e);
|
||||
if (q.peek() == e) {
|
||||
leader = null;
|
||||
available.signal();
|
||||
}
|
||||
return true;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this delay queue. As the queue is
|
||||
* unbounded this method will never block.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
*/
|
||||
public void put(E e) {
|
||||
offer(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this delay queue. As the queue is
|
||||
* unbounded this method will never block.
|
||||
*
|
||||
* @param e the element to add
|
||||
* @param timeout This parameter is ignored as the method never blocks
|
||||
* @param unit This parameter is ignored as the method never blocks
|
||||
* @return {@code true}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
*/
|
||||
public boolean offer(E e, long timeout, TimeUnit unit) {
|
||||
return offer(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue, or returns {@code null}
|
||||
* if this queue has no elements with an expired delay.
|
||||
*
|
||||
* @return the head of this queue, or {@code null} if this
|
||||
* queue has no elements with an expired delay
|
||||
*/
|
||||
public E poll() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
E first = q.peek();
|
||||
if (first == null || first.getDelay(NANOSECONDS) > 0)
|
||||
return null;
|
||||
else
|
||||
return q.poll();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue, waiting if necessary
|
||||
* until an element with an expired delay is available on this queue.
|
||||
*
|
||||
* @return the head of this queue
|
||||
* @throws InterruptedException {@inheritDoc}
|
||||
*/
|
||||
public E take() throws InterruptedException {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lockInterruptibly();
|
||||
try {
|
||||
for (;;) {
|
||||
E first = q.peek();
|
||||
if (first == null)
|
||||
available.await();
|
||||
else {
|
||||
long delay = first.getDelay(NANOSECONDS);
|
||||
if (delay <= 0)
|
||||
return q.poll();
|
||||
first = null; // don't retain ref while waiting
|
||||
if (leader != null)
|
||||
available.await();
|
||||
else {
|
||||
Thread thisThread = Thread.currentThread();
|
||||
leader = thisThread;
|
||||
try {
|
||||
available.awaitNanos(delay);
|
||||
} finally {
|
||||
if (leader == thisThread)
|
||||
leader = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (leader == null && q.peek() != null)
|
||||
available.signal();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue, waiting if necessary
|
||||
* until an element with an expired delay is available on this queue,
|
||||
* or the specified wait time expires.
|
||||
*
|
||||
* @return the head of this queue, or {@code null} if the
|
||||
* specified waiting time elapses before an element with
|
||||
* an expired delay becomes available
|
||||
* @throws InterruptedException {@inheritDoc}
|
||||
*/
|
||||
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
long nanos = unit.toNanos(timeout);
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lockInterruptibly();
|
||||
try {
|
||||
for (;;) {
|
||||
E first = q.peek();
|
||||
if (first == null) {
|
||||
if (nanos <= 0)
|
||||
return null;
|
||||
else
|
||||
nanos = available.awaitNanos(nanos);
|
||||
} else {
|
||||
long delay = first.getDelay(NANOSECONDS);
|
||||
if (delay <= 0)
|
||||
return q.poll();
|
||||
if (nanos <= 0)
|
||||
return null;
|
||||
first = null; // don't retain ref while waiting
|
||||
if (nanos < delay || leader != null)
|
||||
nanos = available.awaitNanos(nanos);
|
||||
else {
|
||||
Thread thisThread = Thread.currentThread();
|
||||
leader = thisThread;
|
||||
try {
|
||||
long timeLeft = available.awaitNanos(delay);
|
||||
nanos -= delay - timeLeft;
|
||||
} finally {
|
||||
if (leader == thisThread)
|
||||
leader = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (leader == null && q.peek() != null)
|
||||
available.signal();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue, or
|
||||
* returns {@code null} if this queue is empty. Unlike
|
||||
* {@code poll}, if no expired elements are available in the queue,
|
||||
* this method returns the element that will expire next,
|
||||
* if one exists.
|
||||
*
|
||||
* @return the head of this queue, or {@code null} if this
|
||||
* queue is empty
|
||||
*/
|
||||
public E peek() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
return q.peek();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
return q.size();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first element only if it is expired.
|
||||
* Used only by drainTo. Call only when holding lock.
|
||||
*/
|
||||
private E peekExpired() {
|
||||
// assert lock.isHeldByCurrentThread();
|
||||
E first = q.peek();
|
||||
return (first == null || first.getDelay(NANOSECONDS) > 0) ?
|
||||
null : first;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws UnsupportedOperationException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public int drainTo(Collection<? super E> c) {
|
||||
if (c == null)
|
||||
throw new NullPointerException();
|
||||
if (c == this)
|
||||
throw new IllegalArgumentException();
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
int n = 0;
|
||||
for (E e; (e = peekExpired()) != null;) {
|
||||
c.add(e); // In this order, in case add() throws.
|
||||
q.poll();
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws UnsupportedOperationException {@inheritDoc}
|
||||
* @throws ClassCastException {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public int drainTo(Collection<? super E> c, int maxElements) {
|
||||
if (c == null)
|
||||
throw new NullPointerException();
|
||||
if (c == this)
|
||||
throw new IllegalArgumentException();
|
||||
if (maxElements <= 0)
|
||||
return 0;
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
int n = 0;
|
||||
for (E e; n < maxElements && (e = peekExpired()) != null;) {
|
||||
c.add(e); // In this order, in case add() throws.
|
||||
q.poll();
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically removes all of the elements from this delay queue.
|
||||
* The queue will be empty after this call returns.
|
||||
* Elements with an unexpired delay are not waited for; they are
|
||||
* simply discarded from the queue.
|
||||
*/
|
||||
public void clear() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
q.clear();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns {@code Integer.MAX_VALUE} because
|
||||
* a {@code DelayQueue} is not capacity constrained.
|
||||
*
|
||||
* @return {@code Integer.MAX_VALUE}
|
||||
*/
|
||||
public int remainingCapacity() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all of the elements in this queue.
|
||||
* The returned array elements are in no particular order.
|
||||
*
|
||||
* <p>The returned array will be "safe" in that no references to it are
|
||||
* maintained by this queue. (In other words, this method must allocate
|
||||
* a new array). The caller is thus free to modify the returned array.
|
||||
*
|
||||
* <p>This method acts as bridge between array-based and collection-based
|
||||
* APIs.
|
||||
*
|
||||
* @return an array containing all of the elements in this queue
|
||||
*/
|
||||
public Object[] toArray() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
return q.toArray();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all of the elements in this queue; the
|
||||
* runtime type of the returned array is that of the specified array.
|
||||
* The returned array elements are in no particular order.
|
||||
* If the queue fits in the specified array, it is returned therein.
|
||||
* Otherwise, a new array is allocated with the runtime type of the
|
||||
* specified array and the size of this queue.
|
||||
*
|
||||
* <p>If this queue fits in the specified array with room to spare
|
||||
* (i.e., the array has more elements than this queue), the element in
|
||||
* the array immediately following the end of the queue is set to
|
||||
* {@code null}.
|
||||
*
|
||||
* <p>Like the {@link #toArray()} method, this method acts as bridge between
|
||||
* array-based and collection-based APIs. Further, this method allows
|
||||
* precise control over the runtime type of the output array, and may,
|
||||
* under certain circumstances, be used to save allocation costs.
|
||||
*
|
||||
* <p>The following code can be used to dump a delay queue into a newly
|
||||
* allocated array of {@code Delayed}:
|
||||
*
|
||||
* <pre> {@code Delayed[] a = q.toArray(new Delayed[0]);}</pre>
|
||||
*
|
||||
* Note that {@code toArray(new Object[0])} is identical in function to
|
||||
* {@code toArray()}.
|
||||
*
|
||||
* @param a the array into which the elements of the queue are to
|
||||
* be stored, if it is big enough; otherwise, a new array of the
|
||||
* same runtime type is allocated for this purpose
|
||||
* @return an array containing all of the elements in this queue
|
||||
* @throws ArrayStoreException if the runtime type of the specified array
|
||||
* is not a supertype of the runtime type of every element in
|
||||
* this queue
|
||||
* @throws NullPointerException if the specified array is null
|
||||
*/
|
||||
public <T> T[] toArray(T[] a) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
return q.toArray(a);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a single instance of the specified element from this
|
||||
* queue, if it is present, whether or not it has expired.
|
||||
*/
|
||||
public boolean remove(Object o) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
return q.remove(o);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Identity-based version for use in Itr.remove
|
||||
*/
|
||||
void removeEQ(Object o) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
for (Iterator<E> it = q.iterator(); it.hasNext(); ) {
|
||||
if (o == it.next()) {
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over all the elements (both expired and
|
||||
* unexpired) in this queue. The iterator does not return the
|
||||
* elements in any particular order.
|
||||
*
|
||||
* <p>The returned iterator is
|
||||
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
|
||||
*
|
||||
* @return an iterator over the elements in this queue
|
||||
*/
|
||||
public Iterator<E> iterator() {
|
||||
return new Itr(toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Snapshot iterator that works off copy of underlying q array.
|
||||
*/
|
||||
private class Itr implements Iterator<E> {
|
||||
final Object[] array; // Array of all elements
|
||||
int cursor; // index of next element to return
|
||||
int lastRet; // index of last element, or -1 if no such
|
||||
|
||||
Itr(Object[] array) {
|
||||
lastRet = -1;
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return cursor < array.length;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public E next() {
|
||||
if (cursor >= array.length)
|
||||
throw new NoSuchElementException();
|
||||
lastRet = cursor;
|
||||
return (E)array[cursor++];
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if (lastRet < 0)
|
||||
throw new IllegalStateException();
|
||||
removeEQ(array[lastRet]);
|
||||
lastRet = -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
60
jdkSrc/jdk8/java/util/concurrent/Delayed.java
Normal file
60
jdkSrc/jdk8/java/util/concurrent/Delayed.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A mix-in style interface for marking objects that should be
|
||||
* acted upon after a given delay.
|
||||
*
|
||||
* <p>An implementation of this interface must define a
|
||||
* {@code compareTo} method that provides an ordering consistent with
|
||||
* its {@code getDelay} method.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface Delayed extends Comparable<Delayed> {
|
||||
|
||||
/**
|
||||
* Returns the remaining delay associated with this object, in the
|
||||
* given time unit.
|
||||
*
|
||||
* @param unit the time unit
|
||||
* @return the remaining delay; zero or negative values indicate
|
||||
* that the delay has already elapsed
|
||||
*/
|
||||
long getDelay(TimeUnit unit);
|
||||
}
|
||||
664
jdkSrc/jdk8/java/util/concurrent/Exchanger.java
Normal file
664
jdkSrc/jdk8/java/util/concurrent/Exchanger.java
Normal file
@@ -0,0 +1,664 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea, Bill Scherer, and Michael Scott with
|
||||
* assistance from members of JCP JSR-166 Expert Group and released to
|
||||
* the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
/**
|
||||
* A synchronization point at which threads can pair and swap elements
|
||||
* within pairs. Each thread presents some object on entry to the
|
||||
* {@link #exchange exchange} method, matches with a partner thread,
|
||||
* and receives its partner's object on return. An Exchanger may be
|
||||
* viewed as a bidirectional form of a {@link SynchronousQueue}.
|
||||
* Exchangers may be useful in applications such as genetic algorithms
|
||||
* and pipeline designs.
|
||||
*
|
||||
* <p><b>Sample Usage:</b>
|
||||
* Here are the highlights of a class that uses an {@code Exchanger}
|
||||
* to swap buffers between threads so that the thread filling the
|
||||
* buffer gets a freshly emptied one when it needs it, handing off the
|
||||
* filled one to the thread emptying the buffer.
|
||||
* <pre> {@code
|
||||
* class FillAndEmpty {
|
||||
* Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
|
||||
* DataBuffer initialEmptyBuffer = ... a made-up type
|
||||
* DataBuffer initialFullBuffer = ...
|
||||
*
|
||||
* class FillingLoop implements Runnable {
|
||||
* public void run() {
|
||||
* DataBuffer currentBuffer = initialEmptyBuffer;
|
||||
* try {
|
||||
* while (currentBuffer != null) {
|
||||
* addToBuffer(currentBuffer);
|
||||
* if (currentBuffer.isFull())
|
||||
* currentBuffer = exchanger.exchange(currentBuffer);
|
||||
* }
|
||||
* } catch (InterruptedException ex) { ... handle ... }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* class EmptyingLoop implements Runnable {
|
||||
* public void run() {
|
||||
* DataBuffer currentBuffer = initialFullBuffer;
|
||||
* try {
|
||||
* while (currentBuffer != null) {
|
||||
* takeFromBuffer(currentBuffer);
|
||||
* if (currentBuffer.isEmpty())
|
||||
* currentBuffer = exchanger.exchange(currentBuffer);
|
||||
* }
|
||||
* } catch (InterruptedException ex) { ... handle ...}
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* void start() {
|
||||
* new Thread(new FillingLoop()).start();
|
||||
* new Thread(new EmptyingLoop()).start();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>Memory consistency effects: For each pair of threads that
|
||||
* successfully exchange objects via an {@code Exchanger}, actions
|
||||
* prior to the {@code exchange()} in each thread
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* those subsequent to a return from the corresponding {@code exchange()}
|
||||
* in the other thread.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea and Bill Scherer and Michael Scott
|
||||
* @param <V> The type of objects that may be exchanged
|
||||
*/
|
||||
public class Exchanger<V> {
|
||||
|
||||
/*
|
||||
* Overview: The core algorithm is, for an exchange "slot",
|
||||
* and a participant (caller) with an item:
|
||||
*
|
||||
* for (;;) {
|
||||
* if (slot is empty) { // offer
|
||||
* place item in a Node;
|
||||
* if (can CAS slot from empty to node) {
|
||||
* wait for release;
|
||||
* return matching item in node;
|
||||
* }
|
||||
* }
|
||||
* else if (can CAS slot from node to empty) { // release
|
||||
* get the item in node;
|
||||
* set matching item in node;
|
||||
* release waiting thread;
|
||||
* }
|
||||
* // else retry on CAS failure
|
||||
* }
|
||||
*
|
||||
* This is among the simplest forms of a "dual data structure" --
|
||||
* see Scott and Scherer's DISC 04 paper and
|
||||
* http://www.cs.rochester.edu/research/synchronization/pseudocode/duals.html
|
||||
*
|
||||
* This works great in principle. But in practice, like many
|
||||
* algorithms centered on atomic updates to a single location, it
|
||||
* scales horribly when there are more than a few participants
|
||||
* using the same Exchanger. So the implementation instead uses a
|
||||
* form of elimination arena, that spreads out this contention by
|
||||
* arranging that some threads typically use different slots,
|
||||
* while still ensuring that eventually, any two parties will be
|
||||
* able to exchange items. That is, we cannot completely partition
|
||||
* across threads, but instead give threads arena indices that
|
||||
* will on average grow under contention and shrink under lack of
|
||||
* contention. We approach this by defining the Nodes that we need
|
||||
* anyway as ThreadLocals, and include in them per-thread index
|
||||
* and related bookkeeping state. (We can safely reuse per-thread
|
||||
* nodes rather than creating them fresh each time because slots
|
||||
* alternate between pointing to a node vs null, so cannot
|
||||
* encounter ABA problems. However, we do need some care in
|
||||
* resetting them between uses.)
|
||||
*
|
||||
* Implementing an effective arena requires allocating a bunch of
|
||||
* space, so we only do so upon detecting contention (except on
|
||||
* uniprocessors, where they wouldn't help, so aren't used).
|
||||
* Otherwise, exchanges use the single-slot slotExchange method.
|
||||
* On contention, not only must the slots be in different
|
||||
* locations, but the locations must not encounter memory
|
||||
* contention due to being on the same cache line (or more
|
||||
* generally, the same coherence unit). Because, as of this
|
||||
* writing, there is no way to determine cacheline size, we define
|
||||
* a value that is enough for common platforms. Additionally,
|
||||
* extra care elsewhere is taken to avoid other false/unintended
|
||||
* sharing and to enhance locality, including adding padding (via
|
||||
* sun.misc.Contended) to Nodes, embedding "bound" as an Exchanger
|
||||
* field, and reworking some park/unpark mechanics compared to
|
||||
* LockSupport versions.
|
||||
*
|
||||
* The arena starts out with only one used slot. We expand the
|
||||
* effective arena size by tracking collisions; i.e., failed CASes
|
||||
* while trying to exchange. By nature of the above algorithm, the
|
||||
* only kinds of collision that reliably indicate contention are
|
||||
* when two attempted releases collide -- one of two attempted
|
||||
* offers can legitimately fail to CAS without indicating
|
||||
* contention by more than one other thread. (Note: it is possible
|
||||
* but not worthwhile to more precisely detect contention by
|
||||
* reading slot values after CAS failures.) When a thread has
|
||||
* collided at each slot within the current arena bound, it tries
|
||||
* to expand the arena size by one. We track collisions within
|
||||
* bounds by using a version (sequence) number on the "bound"
|
||||
* field, and conservatively reset collision counts when a
|
||||
* participant notices that bound has been updated (in either
|
||||
* direction).
|
||||
*
|
||||
* The effective arena size is reduced (when there is more than
|
||||
* one slot) by giving up on waiting after a while and trying to
|
||||
* decrement the arena size on expiration. The value of "a while"
|
||||
* is an empirical matter. We implement by piggybacking on the
|
||||
* use of spin->yield->block that is essential for reasonable
|
||||
* waiting performance anyway -- in a busy exchanger, offers are
|
||||
* usually almost immediately released, in which case context
|
||||
* switching on multiprocessors is extremely slow/wasteful. Arena
|
||||
* waits just omit the blocking part, and instead cancel. The spin
|
||||
* count is empirically chosen to be a value that avoids blocking
|
||||
* 99% of the time under maximum sustained exchange rates on a
|
||||
* range of test machines. Spins and yields entail some limited
|
||||
* randomness (using a cheap xorshift) to avoid regular patterns
|
||||
* that can induce unproductive grow/shrink cycles. (Using a
|
||||
* pseudorandom also helps regularize spin cycle duration by
|
||||
* making branches unpredictable.) Also, during an offer, a
|
||||
* waiter can "know" that it will be released when its slot has
|
||||
* changed, but cannot yet proceed until match is set. In the
|
||||
* mean time it cannot cancel the offer, so instead spins/yields.
|
||||
* Note: It is possible to avoid this secondary check by changing
|
||||
* the linearization point to be a CAS of the match field (as done
|
||||
* in one case in the Scott & Scherer DISC paper), which also
|
||||
* increases asynchrony a bit, at the expense of poorer collision
|
||||
* detection and inability to always reuse per-thread nodes. So
|
||||
* the current scheme is typically a better tradeoff.
|
||||
*
|
||||
* On collisions, indices traverse the arena cyclically in reverse
|
||||
* order, restarting at the maximum index (which will tend to be
|
||||
* sparsest) when bounds change. (On expirations, indices instead
|
||||
* are halved until reaching 0.) It is possible (and has been
|
||||
* tried) to use randomized, prime-value-stepped, or double-hash
|
||||
* style traversal instead of simple cyclic traversal to reduce
|
||||
* bunching. But empirically, whatever benefits these may have
|
||||
* don't overcome their added overhead: We are managing operations
|
||||
* that occur very quickly unless there is sustained contention,
|
||||
* so simpler/faster control policies work better than more
|
||||
* accurate but slower ones.
|
||||
*
|
||||
* Because we use expiration for arena size control, we cannot
|
||||
* throw TimeoutExceptions in the timed version of the public
|
||||
* exchange method until the arena size has shrunken to zero (or
|
||||
* the arena isn't enabled). This may delay response to timeout
|
||||
* but is still within spec.
|
||||
*
|
||||
* Essentially all of the implementation is in methods
|
||||
* slotExchange and arenaExchange. These have similar overall
|
||||
* structure, but differ in too many details to combine. The
|
||||
* slotExchange method uses the single Exchanger field "slot"
|
||||
* rather than arena array elements. However, it still needs
|
||||
* minimal collision detection to trigger arena construction.
|
||||
* (The messiest part is making sure interrupt status and
|
||||
* InterruptedExceptions come out right during transitions when
|
||||
* both methods may be called. This is done by using null return
|
||||
* as a sentinel to recheck interrupt status.)
|
||||
*
|
||||
* As is too common in this sort of code, methods are monolithic
|
||||
* because most of the logic relies on reads of fields that are
|
||||
* maintained as local variables so can't be nicely factored --
|
||||
* mainly, here, bulky spin->yield->block/cancel code), and
|
||||
* heavily dependent on intrinsics (Unsafe) to use inlined
|
||||
* embedded CAS and related memory access operations (that tend
|
||||
* not to be as readily inlined by dynamic compilers when they are
|
||||
* hidden behind other methods that would more nicely name and
|
||||
* encapsulate the intended effects). This includes the use of
|
||||
* putOrderedX to clear fields of the per-thread Nodes between
|
||||
* uses. Note that field Node.item is not declared as volatile
|
||||
* even though it is read by releasing threads, because they only
|
||||
* do so after CAS operations that must precede access, and all
|
||||
* uses by the owning thread are otherwise acceptably ordered by
|
||||
* other operations. (Because the actual points of atomicity are
|
||||
* slot CASes, it would also be legal for the write to Node.match
|
||||
* in a release to be weaker than a full volatile write. However,
|
||||
* this is not done because it could allow further postponement of
|
||||
* the write, delaying progress.)
|
||||
*/
|
||||
|
||||
/**
|
||||
* The byte distance (as a shift value) between any two used slots
|
||||
* in the arena. 1 << ASHIFT should be at least cacheline size.
|
||||
*/
|
||||
private static final int ASHIFT = 7;
|
||||
|
||||
/**
|
||||
* The maximum supported arena index. The maximum allocatable
|
||||
* arena size is MMASK + 1. Must be a power of two minus one, less
|
||||
* than (1<<(31-ASHIFT)). The cap of 255 (0xff) more than suffices
|
||||
* for the expected scaling limits of the main algorithms.
|
||||
*/
|
||||
private static final int MMASK = 0xff;
|
||||
|
||||
/**
|
||||
* Unit for sequence/version bits of bound field. Each successful
|
||||
* change to the bound also adds SEQ.
|
||||
*/
|
||||
private static final int SEQ = MMASK + 1;
|
||||
|
||||
/** The number of CPUs, for sizing and spin control */
|
||||
private static final int NCPU = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
/**
|
||||
* The maximum slot index of the arena: The number of slots that
|
||||
* can in principle hold all threads without contention, or at
|
||||
* most the maximum indexable value.
|
||||
*/
|
||||
static final int FULL = (NCPU >= (MMASK << 1)) ? MMASK : NCPU >>> 1;
|
||||
|
||||
/**
|
||||
* The bound for spins while waiting for a match. The actual
|
||||
* number of iterations will on average be about twice this value
|
||||
* due to randomization. Note: Spinning is disabled when NCPU==1.
|
||||
*/
|
||||
private static final int SPINS = 1 << 10;
|
||||
|
||||
/**
|
||||
* Value representing null arguments/returns from public
|
||||
* methods. Needed because the API originally didn't disallow null
|
||||
* arguments, which it should have.
|
||||
*/
|
||||
private static final Object NULL_ITEM = new Object();
|
||||
|
||||
/**
|
||||
* Sentinel value returned by internal exchange methods upon
|
||||
* timeout, to avoid need for separate timed versions of these
|
||||
* methods.
|
||||
*/
|
||||
private static final Object TIMED_OUT = new Object();
|
||||
|
||||
/**
|
||||
* Nodes hold partially exchanged data, plus other per-thread
|
||||
* bookkeeping. Padded via @sun.misc.Contended to reduce memory
|
||||
* contention.
|
||||
*/
|
||||
@sun.misc.Contended static final class Node {
|
||||
int index; // Arena index
|
||||
int bound; // Last recorded value of Exchanger.bound
|
||||
int collides; // Number of CAS failures at current bound
|
||||
int hash; // Pseudo-random for spins
|
||||
Object item; // This thread's current item
|
||||
volatile Object match; // Item provided by releasing thread
|
||||
volatile Thread parked; // Set to this thread when parked, else null
|
||||
}
|
||||
|
||||
/** The corresponding thread local class */
|
||||
static final class Participant extends ThreadLocal<Node> {
|
||||
public Node initialValue() { return new Node(); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-thread state
|
||||
*/
|
||||
private final Participant participant;
|
||||
|
||||
/**
|
||||
* Elimination array; null until enabled (within slotExchange).
|
||||
* Element accesses use emulation of volatile gets and CAS.
|
||||
*/
|
||||
private volatile Node[] arena;
|
||||
|
||||
/**
|
||||
* Slot used until contention detected.
|
||||
*/
|
||||
private volatile Node slot;
|
||||
|
||||
/**
|
||||
* The index of the largest valid arena position, OR'ed with SEQ
|
||||
* number in high bits, incremented on each update. The initial
|
||||
* update from 0 to SEQ is used to ensure that the arena array is
|
||||
* constructed only once.
|
||||
*/
|
||||
private volatile int bound;
|
||||
|
||||
/**
|
||||
* Exchange function when arenas enabled. See above for explanation.
|
||||
*
|
||||
* @param item the (non-null) item to exchange
|
||||
* @param timed true if the wait is timed
|
||||
* @param ns if timed, the maximum wait time, else 0L
|
||||
* @return the other thread's item; or null if interrupted; or
|
||||
* TIMED_OUT if timed and timed out
|
||||
*/
|
||||
private final Object arenaExchange(Object item, boolean timed, long ns) {
|
||||
Node[] a = arena;
|
||||
Node p = participant.get();
|
||||
for (int i = p.index;;) { // access slot at i
|
||||
int b, m, c; long j; // j is raw array offset
|
||||
Node q = (Node)U.getObjectVolatile(a, j = (i << ASHIFT) + ABASE);
|
||||
if (q != null && U.compareAndSwapObject(a, j, q, null)) {
|
||||
Object v = q.item; // release
|
||||
q.match = item;
|
||||
Thread w = q.parked;
|
||||
if (w != null)
|
||||
U.unpark(w);
|
||||
return v;
|
||||
}
|
||||
else if (i <= (m = (b = bound) & MMASK) && q == null) {
|
||||
p.item = item; // offer
|
||||
if (U.compareAndSwapObject(a, j, null, p)) {
|
||||
long end = (timed && m == 0) ? System.nanoTime() + ns : 0L;
|
||||
Thread t = Thread.currentThread(); // wait
|
||||
for (int h = p.hash, spins = SPINS;;) {
|
||||
Object v = p.match;
|
||||
if (v != null) {
|
||||
U.putOrderedObject(p, MATCH, null);
|
||||
p.item = null; // clear for next use
|
||||
p.hash = h;
|
||||
return v;
|
||||
}
|
||||
else if (spins > 0) {
|
||||
h ^= h << 1; h ^= h >>> 3; h ^= h << 10; // xorshift
|
||||
if (h == 0) // initialize hash
|
||||
h = SPINS | (int)t.getId();
|
||||
else if (h < 0 && // approx 50% true
|
||||
(--spins & ((SPINS >>> 1) - 1)) == 0)
|
||||
Thread.yield(); // two yields per wait
|
||||
}
|
||||
else if (U.getObjectVolatile(a, j) != p)
|
||||
spins = SPINS; // releaser hasn't set match yet
|
||||
else if (!t.isInterrupted() && m == 0 &&
|
||||
(!timed ||
|
||||
(ns = end - System.nanoTime()) > 0L)) {
|
||||
U.putObject(t, BLOCKER, this); // emulate LockSupport
|
||||
p.parked = t; // minimize window
|
||||
if (U.getObjectVolatile(a, j) == p)
|
||||
U.park(false, ns);
|
||||
p.parked = null;
|
||||
U.putObject(t, BLOCKER, null);
|
||||
}
|
||||
else if (U.getObjectVolatile(a, j) == p &&
|
||||
U.compareAndSwapObject(a, j, p, null)) {
|
||||
if (m != 0) // try to shrink
|
||||
U.compareAndSwapInt(this, BOUND, b, b + SEQ - 1);
|
||||
p.item = null;
|
||||
p.hash = h;
|
||||
i = p.index >>>= 1; // descend
|
||||
if (Thread.interrupted())
|
||||
return null;
|
||||
if (timed && m == 0 && ns <= 0L)
|
||||
return TIMED_OUT;
|
||||
break; // expired; restart
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
p.item = null; // clear offer
|
||||
}
|
||||
else {
|
||||
if (p.bound != b) { // stale; reset
|
||||
p.bound = b;
|
||||
p.collides = 0;
|
||||
i = (i != m || m == 0) ? m : m - 1;
|
||||
}
|
||||
else if ((c = p.collides) < m || m == FULL ||
|
||||
!U.compareAndSwapInt(this, BOUND, b, b + SEQ + 1)) {
|
||||
p.collides = c + 1;
|
||||
i = (i == 0) ? m : i - 1; // cyclically traverse
|
||||
}
|
||||
else
|
||||
i = m + 1; // grow
|
||||
p.index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exchange function used until arenas enabled. See above for explanation.
|
||||
*
|
||||
* @param item the item to exchange
|
||||
* @param timed true if the wait is timed
|
||||
* @param ns if timed, the maximum wait time, else 0L
|
||||
* @return the other thread's item; or null if either the arena
|
||||
* was enabled or the thread was interrupted before completion; or
|
||||
* TIMED_OUT if timed and timed out
|
||||
*/
|
||||
private final Object slotExchange(Object item, boolean timed, long ns) {
|
||||
Node p = participant.get();
|
||||
Thread t = Thread.currentThread();
|
||||
if (t.isInterrupted()) // preserve interrupt status so caller can recheck
|
||||
return null;
|
||||
|
||||
for (Node q;;) {
|
||||
if ((q = slot) != null) {
|
||||
if (U.compareAndSwapObject(this, SLOT, q, null)) {
|
||||
Object v = q.item;
|
||||
q.match = item;
|
||||
Thread w = q.parked;
|
||||
if (w != null)
|
||||
U.unpark(w);
|
||||
return v;
|
||||
}
|
||||
// create arena on contention, but continue until slot null
|
||||
if (NCPU > 1 && bound == 0 &&
|
||||
U.compareAndSwapInt(this, BOUND, 0, SEQ))
|
||||
arena = new Node[(FULL + 2) << ASHIFT];
|
||||
}
|
||||
else if (arena != null)
|
||||
return null; // caller must reroute to arenaExchange
|
||||
else {
|
||||
p.item = item;
|
||||
if (U.compareAndSwapObject(this, SLOT, null, p))
|
||||
break;
|
||||
p.item = null;
|
||||
}
|
||||
}
|
||||
|
||||
// await release
|
||||
int h = p.hash;
|
||||
long end = timed ? System.nanoTime() + ns : 0L;
|
||||
int spins = (NCPU > 1) ? SPINS : 1;
|
||||
Object v;
|
||||
while ((v = p.match) == null) {
|
||||
if (spins > 0) {
|
||||
h ^= h << 1; h ^= h >>> 3; h ^= h << 10;
|
||||
if (h == 0)
|
||||
h = SPINS | (int)t.getId();
|
||||
else if (h < 0 && (--spins & ((SPINS >>> 1) - 1)) == 0)
|
||||
Thread.yield();
|
||||
}
|
||||
else if (slot != p)
|
||||
spins = SPINS;
|
||||
else if (!t.isInterrupted() && arena == null &&
|
||||
(!timed || (ns = end - System.nanoTime()) > 0L)) {
|
||||
U.putObject(t, BLOCKER, this);
|
||||
p.parked = t;
|
||||
if (slot == p)
|
||||
U.park(false, ns);
|
||||
p.parked = null;
|
||||
U.putObject(t, BLOCKER, null);
|
||||
}
|
||||
else if (U.compareAndSwapObject(this, SLOT, p, null)) {
|
||||
v = timed && ns <= 0L && !t.isInterrupted() ? TIMED_OUT : null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
U.putOrderedObject(p, MATCH, null);
|
||||
p.item = null;
|
||||
p.hash = h;
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Exchanger.
|
||||
*/
|
||||
public Exchanger() {
|
||||
participant = new Participant();
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for another thread to arrive at this exchange point (unless
|
||||
* the current thread is {@linkplain Thread#interrupt interrupted}),
|
||||
* and then transfers the given object to it, receiving its object
|
||||
* in return.
|
||||
*
|
||||
* <p>If another thread is already waiting at the exchange point then
|
||||
* it is resumed for thread scheduling purposes and receives the object
|
||||
* passed in by the current thread. The current thread returns immediately,
|
||||
* receiving the object passed to the exchange by that other thread.
|
||||
*
|
||||
* <p>If no other thread is already waiting at the exchange then the
|
||||
* current thread is disabled for thread scheduling purposes and lies
|
||||
* dormant until one of two things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread enters the exchange; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread.
|
||||
* </ul>
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* for the exchange,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* @param x the object to exchange
|
||||
* @return the object provided by the other thread
|
||||
* @throws InterruptedException if the current thread was
|
||||
* interrupted while waiting
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public V exchange(V x) throws InterruptedException {
|
||||
Object v;
|
||||
Object item = (x == null) ? NULL_ITEM : x; // translate null args
|
||||
if ((arena != null ||
|
||||
(v = slotExchange(item, false, 0L)) == null) &&
|
||||
((Thread.interrupted() || // disambiguates null return
|
||||
(v = arenaExchange(item, false, 0L)) == null)))
|
||||
throw new InterruptedException();
|
||||
return (v == NULL_ITEM) ? null : (V)v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for another thread to arrive at this exchange point (unless
|
||||
* the current thread is {@linkplain Thread#interrupt interrupted} or
|
||||
* the specified waiting time elapses), and then transfers the given
|
||||
* object to it, receiving its object in return.
|
||||
*
|
||||
* <p>If another thread is already waiting at the exchange point then
|
||||
* it is resumed for thread scheduling purposes and receives the object
|
||||
* passed in by the current thread. The current thread returns immediately,
|
||||
* receiving the object passed to the exchange by that other thread.
|
||||
*
|
||||
* <p>If no other thread is already waiting at the exchange then the
|
||||
* current thread is disabled for thread scheduling purposes and lies
|
||||
* dormant until one of three things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread enters the exchange; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
* <li>The specified waiting time elapses.
|
||||
* </ul>
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* for the exchange,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* <p>If the specified waiting time elapses then {@link
|
||||
* TimeoutException} is thrown. If the time is less than or equal
|
||||
* to zero, the method will not wait at all.
|
||||
*
|
||||
* @param x the object to exchange
|
||||
* @param timeout the maximum time to wait
|
||||
* @param unit the time unit of the {@code timeout} argument
|
||||
* @return the object provided by the other thread
|
||||
* @throws InterruptedException if the current thread was
|
||||
* interrupted while waiting
|
||||
* @throws TimeoutException if the specified waiting time elapses
|
||||
* before another thread enters the exchange
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public V exchange(V x, long timeout, TimeUnit unit)
|
||||
throws InterruptedException, TimeoutException {
|
||||
Object v;
|
||||
Object item = (x == null) ? NULL_ITEM : x;
|
||||
long ns = unit.toNanos(timeout);
|
||||
if ((arena != null ||
|
||||
(v = slotExchange(item, true, ns)) == null) &&
|
||||
((Thread.interrupted() ||
|
||||
(v = arenaExchange(item, true, ns)) == null)))
|
||||
throw new InterruptedException();
|
||||
if (v == TIMED_OUT)
|
||||
throw new TimeoutException();
|
||||
return (v == NULL_ITEM) ? null : (V)v;
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe U;
|
||||
private static final long BOUND;
|
||||
private static final long SLOT;
|
||||
private static final long MATCH;
|
||||
private static final long BLOCKER;
|
||||
private static final int ABASE;
|
||||
static {
|
||||
int s;
|
||||
try {
|
||||
U = sun.misc.Unsafe.getUnsafe();
|
||||
Class<?> ek = Exchanger.class;
|
||||
Class<?> nk = Node.class;
|
||||
Class<?> ak = Node[].class;
|
||||
Class<?> tk = Thread.class;
|
||||
BOUND = U.objectFieldOffset
|
||||
(ek.getDeclaredField("bound"));
|
||||
SLOT = U.objectFieldOffset
|
||||
(ek.getDeclaredField("slot"));
|
||||
MATCH = U.objectFieldOffset
|
||||
(nk.getDeclaredField("match"));
|
||||
BLOCKER = U.objectFieldOffset
|
||||
(tk.getDeclaredField("parkBlocker"));
|
||||
s = U.arrayIndexScale(ak);
|
||||
// ABASE absorbs padding in front of element 0
|
||||
ABASE = U.arrayBaseOffset(ak) + (1 << ASHIFT);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
if ((s & (s-1)) != 0 || s > (1 << ASHIFT))
|
||||
throw new Error("Unsupported array scale");
|
||||
}
|
||||
|
||||
}
|
||||
92
jdkSrc/jdk8/java/util/concurrent/ExecutionException.java
Normal file
92
jdkSrc/jdk8/java/util/concurrent/ExecutionException.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to retrieve the result of a task
|
||||
* that aborted by throwing an exception. This exception can be
|
||||
* inspected using the {@link #getCause()} method.
|
||||
*
|
||||
* @see Future
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class ExecutionException extends Exception {
|
||||
private static final long serialVersionUID = 7830266012832686185L;
|
||||
|
||||
/**
|
||||
* 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 {@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}.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
protected ExecutionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@code ExecutionException} with the specified detail
|
||||
* message and cause.
|
||||
*
|
||||
* @param message the detail message
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link #getCause()} method)
|
||||
*/
|
||||
public ExecutionException(String message, Throwable cause) {
|
||||
super(message, 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}).
|
||||
*
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link #getCause()} method)
|
||||
*/
|
||||
public ExecutionException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
141
jdkSrc/jdk8/java/util/concurrent/Executor.java
Normal file
141
jdkSrc/jdk8/java/util/concurrent/Executor.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* 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 {@code Executor} is normally used
|
||||
* instead of explicitly creating threads. For example, rather than
|
||||
* invoking {@code new Thread(new(RunnableTask())).start()} for each
|
||||
* of a set of tasks, you might use:
|
||||
*
|
||||
* <pre>
|
||||
* Executor executor = <em>anExecutor</em>;
|
||||
* executor.execute(new RunnableTask1());
|
||||
* executor.execute(new RunnableTask2());
|
||||
* ...
|
||||
* </pre>
|
||||
*
|
||||
* 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:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class DirectExecutor implements Executor {
|
||||
* public void execute(Runnable r) {
|
||||
* r.run();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* More typically, tasks are executed in some thread other
|
||||
* than the caller's thread. The executor below spawns a new thread
|
||||
* for each task.
|
||||
*
|
||||
* <pre> {@code
|
||||
* class ThreadPerTaskExecutor implements Executor {
|
||||
* public void execute(Runnable r) {
|
||||
* new Thread(r).start();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* <pre> {@code
|
||||
* class SerialExecutor implements Executor {
|
||||
* final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
|
||||
* final Executor executor;
|
||||
* Runnable active;
|
||||
*
|
||||
* SerialExecutor(Executor executor) {
|
||||
* this.executor = executor;
|
||||
* }
|
||||
*
|
||||
* public synchronized void execute(final Runnable r) {
|
||||
* tasks.offer(new Runnable() {
|
||||
* public void run() {
|
||||
* try {
|
||||
* r.run();
|
||||
* } finally {
|
||||
* scheduleNext();
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
* if (active == null) {
|
||||
* scheduleNext();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* protected synchronized void scheduleNext() {
|
||||
* if ((active = tasks.poll()) != null) {
|
||||
* executor.execute(active);
|
||||
* }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* 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
|
||||
* provides convenient factory methods for these Executors.
|
||||
*
|
||||
* <p>Memory consistency effects: Actions in a thread prior to
|
||||
* submitting a {@code Runnable} object to an {@code Executor}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* its execution begins, perhaps in another thread.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface Executor {
|
||||
|
||||
/**
|
||||
* 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 {@code Executor} implementation.
|
||||
*
|
||||
* @param command the runnable task
|
||||
* @throws RejectedExecutionException if this task cannot be
|
||||
* accepted for execution
|
||||
* @throws NullPointerException if command is null
|
||||
*/
|
||||
void execute(Runnable command);
|
||||
}
|
||||
205
jdkSrc/jdk8/java/util/concurrent/ExecutorCompletionService.java
Normal file
205
jdkSrc/jdk8/java/util/concurrent/ExecutorCompletionService.java
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A {@link CompletionService} that uses a supplied {@link Executor}
|
||||
* to execute tasks. This class arranges that submitted tasks are,
|
||||
* upon completion, placed on a queue accessible using {@code take}.
|
||||
* The class is lightweight enough to be suitable for transient use
|
||||
* when processing groups of tasks.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* <b>Usage Examples.</b>
|
||||
*
|
||||
* Suppose you have a set of solvers for a certain problem, each
|
||||
* returning a value of some type {@code Result}, and would like to
|
||||
* run them concurrently, processing the results of each of them that
|
||||
* return a non-null value, in some method {@code use(Result r)}. You
|
||||
* could write this as:
|
||||
*
|
||||
* <pre> {@code
|
||||
* void solve(Executor e,
|
||||
* Collection<Callable<Result>> solvers)
|
||||
* throws InterruptedException, ExecutionException {
|
||||
* CompletionService<Result> ecs
|
||||
* = new ExecutorCompletionService<Result>(e);
|
||||
* for (Callable<Result> s : solvers)
|
||||
* ecs.submit(s);
|
||||
* int n = solvers.size();
|
||||
* for (int i = 0; i < n; ++i) {
|
||||
* Result r = ecs.take().get();
|
||||
* if (r != null)
|
||||
* use(r);
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* Suppose instead that you would like to use the first non-null result
|
||||
* of the set of tasks, ignoring any that encounter exceptions,
|
||||
* and cancelling all other tasks when the first one is ready:
|
||||
*
|
||||
* <pre> {@code
|
||||
* void solve(Executor e,
|
||||
* Collection<Callable<Result>> solvers)
|
||||
* throws InterruptedException {
|
||||
* CompletionService<Result> ecs
|
||||
* = new ExecutorCompletionService<Result>(e);
|
||||
* int n = solvers.size();
|
||||
* List<Future<Result>> futures
|
||||
* = new ArrayList<Future<Result>>(n);
|
||||
* Result result = null;
|
||||
* try {
|
||||
* for (Callable<Result> s : solvers)
|
||||
* futures.add(ecs.submit(s));
|
||||
* for (int i = 0; i < n; ++i) {
|
||||
* try {
|
||||
* Result r = ecs.take().get();
|
||||
* if (r != null) {
|
||||
* result = r;
|
||||
* break;
|
||||
* }
|
||||
* } catch (ExecutionException ignore) {}
|
||||
* }
|
||||
* }
|
||||
* finally {
|
||||
* for (Future<Result> f : futures)
|
||||
* f.cancel(true);
|
||||
* }
|
||||
*
|
||||
* if (result != null)
|
||||
* use(result);
|
||||
* }}</pre>
|
||||
*/
|
||||
public class ExecutorCompletionService<V> implements CompletionService<V> {
|
||||
private final Executor executor;
|
||||
private final AbstractExecutorService aes;
|
||||
private final BlockingQueue<Future<V>> completionQueue;
|
||||
|
||||
/**
|
||||
* FutureTask extension to enqueue upon completion
|
||||
*/
|
||||
private class QueueingFuture extends FutureTask<Void> {
|
||||
QueueingFuture(RunnableFuture<V> task) {
|
||||
super(task, null);
|
||||
this.task = task;
|
||||
}
|
||||
protected void done() { completionQueue.add(task); }
|
||||
private final Future<V> task;
|
||||
}
|
||||
|
||||
private RunnableFuture<V> newTaskFor(Callable<V> task) {
|
||||
if (aes == null)
|
||||
return new FutureTask<V>(task);
|
||||
else
|
||||
return aes.newTaskFor(task);
|
||||
}
|
||||
|
||||
private RunnableFuture<V> newTaskFor(Runnable task, V result) {
|
||||
if (aes == null)
|
||||
return new FutureTask<V>(task, result);
|
||||
else
|
||||
return aes.newTaskFor(task, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ExecutorCompletionService using the supplied
|
||||
* executor for base task execution and a
|
||||
* {@link LinkedBlockingQueue} as a completion queue.
|
||||
*
|
||||
* @param executor the executor to use
|
||||
* @throws NullPointerException if executor is {@code null}
|
||||
*/
|
||||
public ExecutorCompletionService(Executor executor) {
|
||||
if (executor == null)
|
||||
throw new NullPointerException();
|
||||
this.executor = executor;
|
||||
this.aes = (executor instanceof AbstractExecutorService) ?
|
||||
(AbstractExecutorService) executor : null;
|
||||
this.completionQueue = new LinkedBlockingQueue<Future<V>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ExecutorCompletionService using the supplied
|
||||
* executor for base task execution and the supplied queue as its
|
||||
* completion queue.
|
||||
*
|
||||
* @param executor the executor to use
|
||||
* @param completionQueue the queue to use as the completion queue
|
||||
* normally one dedicated for use by this service. This
|
||||
* queue is treated as unbounded -- failed attempted
|
||||
* {@code Queue.add} operations for completed tasks cause
|
||||
* them not to be retrievable.
|
||||
* @throws NullPointerException if executor or completionQueue are {@code null}
|
||||
*/
|
||||
public ExecutorCompletionService(Executor executor,
|
||||
BlockingQueue<Future<V>> completionQueue) {
|
||||
if (executor == null || completionQueue == null)
|
||||
throw new NullPointerException();
|
||||
this.executor = executor;
|
||||
this.aes = (executor instanceof AbstractExecutorService) ?
|
||||
(AbstractExecutorService) executor : null;
|
||||
this.completionQueue = completionQueue;
|
||||
}
|
||||
|
||||
public Future<V> submit(Callable<V> task) {
|
||||
if (task == null) throw new NullPointerException();
|
||||
RunnableFuture<V> f = newTaskFor(task);
|
||||
executor.execute(new QueueingFuture(f));
|
||||
return f;
|
||||
}
|
||||
|
||||
public Future<V> submit(Runnable task, V result) {
|
||||
if (task == null) throw new NullPointerException();
|
||||
RunnableFuture<V> f = newTaskFor(task, result);
|
||||
executor.execute(new QueueingFuture(f));
|
||||
return f;
|
||||
}
|
||||
|
||||
public Future<V> take() throws InterruptedException {
|
||||
return completionQueue.take();
|
||||
}
|
||||
|
||||
public Future<V> poll() {
|
||||
return completionQueue.poll();
|
||||
}
|
||||
|
||||
public Future<V> poll(long timeout, TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
return completionQueue.poll(timeout, unit);
|
||||
}
|
||||
|
||||
}
|
||||
370
jdkSrc/jdk8/java/util/concurrent/ExecutorService.java
Normal file
370
jdkSrc/jdk8/java/util/concurrent/ExecutorService.java
Normal file
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* An {@link Executor} that provides methods to manage termination and
|
||||
* methods that can produce a {@link Future} for tracking progress of
|
||||
* one or more asynchronous tasks.
|
||||
*
|
||||
* <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 {@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 {@code ExecutorService} should be shut down to allow
|
||||
* reclamation of its resources.
|
||||
*
|
||||
* <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
|
||||
* write customized variants of these methods.)
|
||||
*
|
||||
* <p>The {@link Executors} class provides factory methods for the
|
||||
* executor services provided in this package.
|
||||
*
|
||||
* <h3>Usage Examples</h3>
|
||||
*
|
||||
* Here is a sketch of a network service in which threads in a thread
|
||||
* pool service incoming requests. It uses the preconfigured {@link
|
||||
* Executors#newFixedThreadPool} factory method:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class NetworkService implements Runnable {
|
||||
* private final ServerSocket serverSocket;
|
||||
* private final ExecutorService pool;
|
||||
*
|
||||
* public NetworkService(int port, int poolSize)
|
||||
* throws IOException {
|
||||
* serverSocket = new ServerSocket(port);
|
||||
* pool = Executors.newFixedThreadPool(poolSize);
|
||||
* }
|
||||
*
|
||||
* public void run() { // run the service
|
||||
* try {
|
||||
* for (;;) {
|
||||
* pool.execute(new Handler(serverSocket.accept()));
|
||||
* }
|
||||
* } catch (IOException ex) {
|
||||
* pool.shutdown();
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* class Handler implements Runnable {
|
||||
* private final Socket socket;
|
||||
* Handler(Socket socket) { this.socket = socket; }
|
||||
* public void run() {
|
||||
* // read and service request on socket
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* 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) {
|
||||
* pool.shutdown(); // Disable new tasks from being submitted
|
||||
* try {
|
||||
* // Wait a while for existing tasks to terminate
|
||||
* if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
|
||||
* pool.shutdownNow(); // Cancel currently executing tasks
|
||||
* // Wait a while for tasks to respond to being cancelled
|
||||
* if (!pool.awaitTermination(60, TimeUnit.SECONDS))
|
||||
* System.err.println("Pool did not terminate");
|
||||
* }
|
||||
* } catch (InterruptedException ie) {
|
||||
* // (Re-)Cancel if current thread also interrupted
|
||||
* pool.shutdownNow();
|
||||
* // Preserve interrupt status
|
||||
* Thread.currentThread().interrupt();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>Memory consistency effects: Actions in a thread prior to the
|
||||
* submission of a {@code Runnable} or {@code Callable} task to an
|
||||
* {@code ExecutorService}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* any actions taken by that task, which in turn <i>happen-before</i> the
|
||||
* result is retrieved via {@code Future.get()}.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface ExecutorService extends Executor {
|
||||
|
||||
/**
|
||||
* Initiates an orderly shutdown in which previously submitted
|
||||
* tasks are executed, but no new tasks will be accepted.
|
||||
* Invocation has no additional effect if already shut down.
|
||||
*
|
||||
* <p>This method does not wait for previously submitted tasks to
|
||||
* complete execution. Use {@link #awaitTermination awaitTermination}
|
||||
* to do that.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* shutting down this ExecutorService may manipulate
|
||||
* threads that the caller is not permitted to modify
|
||||
* because it does not hold {@link
|
||||
* java.lang.RuntimePermission}{@code ("modifyThread")},
|
||||
* or the security manager's {@code checkAccess} method
|
||||
* denies access.
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* Attempts to stop all actively executing tasks, halts the
|
||||
* processing of waiting tasks, and returns a list of the tasks
|
||||
* that were awaiting execution.
|
||||
*
|
||||
* <p>This method does not wait for actively executing tasks to
|
||||
* terminate. Use {@link #awaitTermination awaitTermination} to
|
||||
* do that.
|
||||
*
|
||||
* <p>There are no guarantees beyond best-effort attempts to stop
|
||||
* processing actively executing tasks. For example, typical
|
||||
* implementations will cancel via {@link Thread#interrupt}, so any
|
||||
* task that fails to respond to interrupts may never terminate.
|
||||
*
|
||||
* @return list of tasks that never commenced execution
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* shutting down this ExecutorService may manipulate
|
||||
* threads that the caller is not permitted to modify
|
||||
* because it does not hold {@link
|
||||
* java.lang.RuntimePermission}{@code ("modifyThread")},
|
||||
* or the security manager's {@code checkAccess} method
|
||||
* denies access.
|
||||
*/
|
||||
List<Runnable> shutdownNow();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this executor has been shut down.
|
||||
*
|
||||
* @return {@code true} if this executor has been shut down
|
||||
*/
|
||||
boolean isShutdown();
|
||||
|
||||
/**
|
||||
* 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 {@code true} if all tasks have completed following shut down
|
||||
*/
|
||||
boolean isTerminated();
|
||||
|
||||
/**
|
||||
* Blocks until all tasks have completed execution after a shutdown
|
||||
* request, or the timeout occurs, or the current thread is
|
||||
* interrupted, whichever happens first.
|
||||
*
|
||||
* @param timeout the maximum time to wait
|
||||
* @param unit the time unit of the timeout argument
|
||||
* @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)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Submits a value-returning task for execution and returns a
|
||||
* Future representing the pending results of the task. The
|
||||
* 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
|
||||
* {@code result = exec.submit(aCallable).get();}
|
||||
*
|
||||
* <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.
|
||||
*
|
||||
* @param task the task to submit
|
||||
* @param <T> the type of the task's result
|
||||
* @return a Future representing pending completion of the task
|
||||
* @throws RejectedExecutionException if the task cannot be
|
||||
* scheduled for execution
|
||||
* @throws NullPointerException if the task is null
|
||||
*/
|
||||
<T> Future<T> submit(Callable<T> task);
|
||||
|
||||
/**
|
||||
* Submits a Runnable task for execution and returns a Future
|
||||
* representing that task. The Future's {@code get} method will
|
||||
* return the given result upon successful completion.
|
||||
*
|
||||
* @param task the task to submit
|
||||
* @param result the result to return
|
||||
* @param <T> the type of the result
|
||||
* @return a Future representing pending completion of the task
|
||||
* @throws RejectedExecutionException if the task cannot be
|
||||
* scheduled for execution
|
||||
* @throws NullPointerException if the task is null
|
||||
*/
|
||||
<T> Future<T> submit(Runnable task, T result);
|
||||
|
||||
/**
|
||||
* Submits a Runnable task for execution and returns a Future
|
||||
* 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
|
||||
* @throws RejectedExecutionException if the task cannot be
|
||||
* scheduled for execution
|
||||
* @throws NullPointerException if the task is null
|
||||
*/
|
||||
Future<?> submit(Runnable task);
|
||||
|
||||
/**
|
||||
* Executes the given tasks, returning a list of Futures holding
|
||||
* their status and results when all complete.
|
||||
* {@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.
|
||||
* The results of this method are undefined if the given
|
||||
* collection is modified while this operation is in progress.
|
||||
*
|
||||
* @param tasks the collection of tasks
|
||||
* @param <T> the type of the values returned from the tasks
|
||||
* @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
|
||||
* @throws InterruptedException if interrupted while waiting, in
|
||||
* 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
|
||||
*/
|
||||
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* 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 {@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
|
||||
* terminated either normally or by throwing an exception.
|
||||
* The results of this method are undefined if the given
|
||||
* collection is modified while this operation is in progress.
|
||||
*
|
||||
* @param tasks the collection of tasks
|
||||
* @param timeout the maximum time to wait
|
||||
* @param unit the time unit of the timeout argument
|
||||
* @param <T> the type of the values returned from the tasks
|
||||
* @return a list of Futures representing the tasks, in the same
|
||||
* sequential order as produced by the iterator for the
|
||||
* given task list. If the operation did not time out,
|
||||
* each task will have completed. If it did time out, some
|
||||
* of these tasks will not have completed.
|
||||
* @throws InterruptedException if interrupted while waiting, in
|
||||
* which case unfinished tasks are cancelled
|
||||
* @throws NullPointerException if tasks, any of its elements, or
|
||||
* unit are {@code null}
|
||||
* @throws RejectedExecutionException if any task cannot be scheduled
|
||||
* for execution
|
||||
*/
|
||||
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
|
||||
long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Executes the given tasks, returning the result
|
||||
* of one that has completed successfully (i.e., without throwing
|
||||
* an exception), if any do. Upon normal or exceptional return,
|
||||
* tasks that have not completed are cancelled.
|
||||
* The results of this method are undefined if the given
|
||||
* collection is modified while this operation is in progress.
|
||||
*
|
||||
* @param tasks the collection of tasks
|
||||
* @param <T> the type of the values returned from the tasks
|
||||
* @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 {@code null}
|
||||
* @throws IllegalArgumentException if tasks is empty
|
||||
* @throws ExecutionException if no task successfully completes
|
||||
* @throws RejectedExecutionException if tasks cannot be scheduled
|
||||
* for execution
|
||||
*/
|
||||
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
|
||||
throws InterruptedException, ExecutionException;
|
||||
|
||||
/**
|
||||
* Executes the given tasks, returning the result
|
||||
* of one that has completed successfully (i.e., without throwing
|
||||
* an exception), if any do before the given timeout elapses.
|
||||
* Upon normal or exceptional return, tasks that have not
|
||||
* completed are cancelled.
|
||||
* The results of this method are undefined if the given
|
||||
* collection is modified while this operation is in progress.
|
||||
*
|
||||
* @param tasks the collection of tasks
|
||||
* @param timeout the maximum time to wait
|
||||
* @param unit the time unit of the timeout argument
|
||||
* @param <T> the type of the values returned from 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 {@code null}
|
||||
* @throws TimeoutException if the given timeout elapses before
|
||||
* any task successfully completes
|
||||
* @throws ExecutionException if no task successfully completes
|
||||
* @throws RejectedExecutionException if tasks cannot be scheduled
|
||||
* for execution
|
||||
*/
|
||||
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
|
||||
long timeout, TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException, TimeoutException;
|
||||
}
|
||||
744
jdkSrc/jdk8/java/util/concurrent/Executors.java
Normal file
744
jdkSrc/jdk8/java/util/concurrent/Executors.java
Normal file
@@ -0,0 +1,744 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.AccessControlException;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
/**
|
||||
* Factory and utility methods for {@link Executor}, {@link
|
||||
* ExecutorService}, {@link ScheduledExecutorService}, {@link
|
||||
* ThreadFactory}, and {@link Callable} classes defined in this
|
||||
* package. This class supports the following kinds of methods:
|
||||
*
|
||||
* <ul>
|
||||
* <li> Methods that create and return an {@link ExecutorService}
|
||||
* set up with commonly useful configuration settings.
|
||||
* <li> Methods that create and return a {@link ScheduledExecutorService}
|
||||
* set up with commonly useful configuration settings.
|
||||
* <li> Methods that create and return a "wrapped" ExecutorService, that
|
||||
* disables reconfiguration by making implementation-specific methods
|
||||
* inaccessible.
|
||||
* <li> Methods that create and return a {@link ThreadFactory}
|
||||
* 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 {@code Callable}.
|
||||
* </ul>
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class Executors {
|
||||
|
||||
/**
|
||||
* Creates a thread pool that reuses a fixed number of threads
|
||||
* operating off a shared unbounded queue. At any point, 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 execution
|
||||
* prior to shutdown, a new one will take its place if needed to
|
||||
* execute subsequent tasks. The threads in the pool will exist
|
||||
* until it is explicitly {@link ExecutorService#shutdown shutdown}.
|
||||
*
|
||||
* @param nThreads the number of threads in the pool
|
||||
* @return the newly created thread pool
|
||||
* @throws IllegalArgumentException if {@code nThreads <= 0}
|
||||
*/
|
||||
public static ExecutorService newFixedThreadPool(int nThreads) {
|
||||
return new ThreadPoolExecutor(nThreads, nThreads,
|
||||
0L, TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<Runnable>());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {@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 prior to shutdown, a new one will take its place if
|
||||
* needed to execute subsequent tasks. The threads in the pool will
|
||||
* exist until it is explicitly {@link ExecutorService#shutdown
|
||||
* shutdown}.
|
||||
*
|
||||
* @param nThreads the number of threads in the pool
|
||||
* @param threadFactory the factory to use when creating new threads
|
||||
* @return the newly created thread pool
|
||||
* @throws NullPointerException if threadFactory is null
|
||||
* @throws IllegalArgumentException if {@code nThreads <= 0}
|
||||
*/
|
||||
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
|
||||
return new ThreadPoolExecutor(nThreads, nThreads,
|
||||
0L, TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(),
|
||||
threadFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Executor that uses a single worker thread operating
|
||||
* off an unbounded queue. (Note however that if this single
|
||||
* thread terminates due to a failure during execution prior to
|
||||
* shutdown, a new one will take its 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
|
||||
* {@code newFixedThreadPool(1)} the returned executor is
|
||||
* guaranteed not to be reconfigurable to use additional threads.
|
||||
*
|
||||
* @return the newly created single-threaded Executor
|
||||
*/
|
||||
public static ExecutorService newSingleThreadExecutor() {
|
||||
return new FinalizableDelegatedExecutorService
|
||||
(new ThreadPoolExecutor(1, 1,
|
||||
0L, TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<Runnable>()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {@code newFixedThreadPool(1, threadFactory)} the
|
||||
* returned executor is guaranteed not to be reconfigurable to use
|
||||
* additional threads.
|
||||
*
|
||||
* @param threadFactory the factory to use when creating new
|
||||
* threads
|
||||
*
|
||||
* @return the newly created single-threaded Executor
|
||||
* @throws NullPointerException if threadFactory is null
|
||||
*/
|
||||
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
|
||||
return new FinalizableDelegatedExecutorService
|
||||
(new ThreadPoolExecutor(1, 1,
|
||||
0L, TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(),
|
||||
threadFactory));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a thread pool that creates new threads as needed, but
|
||||
* 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 {@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
|
||||
* the cache. Thus, a pool that remains idle for long enough will
|
||||
* not consume any resources. Note that pools with similar
|
||||
* properties but different details (for example, timeout parameters)
|
||||
* may be created using {@link ThreadPoolExecutor} constructors.
|
||||
*
|
||||
* @return the newly created thread pool
|
||||
*/
|
||||
public static ExecutorService newCachedThreadPool() {
|
||||
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
|
||||
60L, TimeUnit.SECONDS,
|
||||
new SynchronousQueue<Runnable>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a thread pool that creates new threads as needed, but
|
||||
* will reuse previously constructed threads when they are
|
||||
* available, and uses the provided
|
||||
* ThreadFactory to create new threads when needed.
|
||||
* @param threadFactory the factory to use when creating new threads
|
||||
* @return the newly created thread pool
|
||||
* @throws NullPointerException if threadFactory is null
|
||||
*/
|
||||
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
|
||||
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
|
||||
60L, TimeUnit.SECONDS,
|
||||
new SynchronousQueue<Runnable>(),
|
||||
threadFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single-threaded executor that can schedule commands
|
||||
* to run after a given delay, or to execute periodically.
|
||||
* (Note however that if this single
|
||||
* thread terminates due to a failure during execution prior to
|
||||
* shutdown, a new one will take its 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
|
||||
* {@code newScheduledThreadPool(1)} the returned executor is
|
||||
* guaranteed not to be reconfigurable to use additional threads.
|
||||
* @return the newly created scheduled executor
|
||||
*/
|
||||
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
|
||||
return new DelegatedScheduledExecutorService
|
||||
(new ScheduledThreadPoolExecutor(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single-threaded executor that can schedule commands
|
||||
* to run after a given delay, or to execute periodically. (Note
|
||||
* however that if this single thread terminates due to a failure
|
||||
* during execution prior to shutdown, a new one will take its
|
||||
* 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 {@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
|
||||
* threads
|
||||
* @return a newly created scheduled executor
|
||||
* @throws NullPointerException if threadFactory is null
|
||||
*/
|
||||
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
|
||||
return new DelegatedScheduledExecutorService
|
||||
(new ScheduledThreadPoolExecutor(1, threadFactory));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return a newly created scheduled thread pool
|
||||
* @throws IllegalArgumentException if {@code corePoolSize < 0}
|
||||
*/
|
||||
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
|
||||
return new ScheduledThreadPoolExecutor(corePoolSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param threadFactory the factory to use when the executor
|
||||
* creates a new thread
|
||||
* @return a newly created scheduled thread pool
|
||||
* @throws IllegalArgumentException if {@code corePoolSize < 0}
|
||||
* @throws NullPointerException if threadFactory is null
|
||||
*/
|
||||
public static ScheduledExecutorService newScheduledThreadPool(
|
||||
int corePoolSize, ThreadFactory threadFactory) {
|
||||
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object that delegates all defined {@link
|
||||
* ExecutorService} methods to the given executor, but not any
|
||||
* other methods that might otherwise be accessible using
|
||||
* casts. This provides a way to safely "freeze" configuration and
|
||||
* disallow tuning of a given concrete implementation.
|
||||
* @param executor the underlying implementation
|
||||
* @return an {@code ExecutorService} instance
|
||||
* @throws NullPointerException if executor null
|
||||
*/
|
||||
public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
|
||||
if (executor == null)
|
||||
throw new NullPointerException();
|
||||
return new DelegatedExecutorService(executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object that delegates all defined {@link
|
||||
* ScheduledExecutorService} methods to the given executor, but
|
||||
* not any other methods that might otherwise be accessible using
|
||||
* casts. This provides a way to safely "freeze" configuration and
|
||||
* disallow tuning of a given concrete implementation.
|
||||
* @param executor the underlying implementation
|
||||
* @return a {@code ScheduledExecutorService} instance
|
||||
* @throws NullPointerException if executor null
|
||||
*/
|
||||
public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
|
||||
if (executor == null)
|
||||
throw new NullPointerException();
|
||||
return new DelegatedScheduledExecutorService(executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a default thread factory used to create new threads.
|
||||
* This factory creates all new threads used by an Executor in the
|
||||
* 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 {@code defaultThreadFactory} method. Each new
|
||||
* thread is created as a non-daemon thread with priority set to
|
||||
* 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
|
||||
* number of this factory, and <em>M</em> is the sequence number
|
||||
* of the thread created by this factory.
|
||||
* @return a thread factory
|
||||
*/
|
||||
public static ThreadFactory defaultThreadFactory() {
|
||||
return new DefaultThreadFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a thread factory used to create new threads that
|
||||
* have the same permissions as the current thread.
|
||||
* This factory creates threads with the same settings as {@link
|
||||
* Executors#defaultThreadFactory}, additionally setting the
|
||||
* AccessControlContext and contextClassLoader of new threads to
|
||||
* be the same as the thread invoking this
|
||||
* {@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
|
||||
* 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(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
|
||||
*/
|
||||
public static ThreadFactory privilegedThreadFactory() {
|
||||
return new PrivilegedThreadFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* {@code Callable} to an otherwise resultless action.
|
||||
* @param task the task to run
|
||||
* @param result the result to return
|
||||
* @param <T> the type of the result
|
||||
* @return a callable object
|
||||
* @throws NullPointerException if task null
|
||||
*/
|
||||
public static <T> Callable<T> callable(Runnable task, T result) {
|
||||
if (task == null)
|
||||
throw new NullPointerException();
|
||||
return new RunnableAdapter<T>(task, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Callable} object that, when
|
||||
* called, runs the given task and returns {@code null}.
|
||||
* @param task the task to run
|
||||
* @return a callable object
|
||||
* @throws NullPointerException if task null
|
||||
*/
|
||||
public static Callable<Object> callable(Runnable task) {
|
||||
if (task == null)
|
||||
throw new NullPointerException();
|
||||
return new RunnableAdapter<Object>(task, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Callable} object that, when
|
||||
* called, runs the given privileged action and returns its result.
|
||||
* @param action the privileged action to run
|
||||
* @return a callable object
|
||||
* @throws NullPointerException if action null
|
||||
*/
|
||||
public static Callable<Object> callable(final PrivilegedAction<?> action) {
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
return new Callable<Object>() {
|
||||
public Object call() { return action.run(); }};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Callable} object that, when
|
||||
* called, runs the given privileged exception action and returns
|
||||
* its result.
|
||||
* @param action the privileged exception action to run
|
||||
* @return a callable object
|
||||
* @throws NullPointerException if action null
|
||||
*/
|
||||
public static Callable<Object> callable(final PrivilegedExceptionAction<?> action) {
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
return new Callable<Object>() {
|
||||
public Object call() throws Exception { return action.run(); }};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param <T> the type of the callable's result
|
||||
* @return a callable object
|
||||
* @throws NullPointerException if callable null
|
||||
*/
|
||||
public static <T> Callable<T> privilegedCallable(Callable<T> callable) {
|
||||
if (callable == null)
|
||||
throw new NullPointerException();
|
||||
return new PrivilegedCallable<T>(callable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param <T> the type of the callable's result
|
||||
* @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
|
||||
*/
|
||||
public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable) {
|
||||
if (callable == null)
|
||||
throw new NullPointerException();
|
||||
return new PrivilegedCallableUsingCurrentClassLoader<T>(callable);
|
||||
}
|
||||
|
||||
// Non-public classes supporting the public methods
|
||||
|
||||
/**
|
||||
* A callable that runs given task and returns given result
|
||||
*/
|
||||
static final class RunnableAdapter<T> implements Callable<T> {
|
||||
final Runnable task;
|
||||
final T result;
|
||||
RunnableAdapter(Runnable task, T result) {
|
||||
this.task = task;
|
||||
this.result = result;
|
||||
}
|
||||
public T call() {
|
||||
task.run();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A callable that runs under established access control settings
|
||||
*/
|
||||
static final class PrivilegedCallable<T> implements Callable<T> {
|
||||
private final Callable<T> task;
|
||||
private final AccessControlContext acc;
|
||||
|
||||
PrivilegedCallable(Callable<T> task) {
|
||||
this.task = task;
|
||||
this.acc = AccessController.getContext();
|
||||
}
|
||||
|
||||
public T call() throws Exception {
|
||||
try {
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<T>() {
|
||||
public T run() throws Exception {
|
||||
return task.call();
|
||||
}
|
||||
}, acc);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw e.getException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A callable that runs under established access control settings and
|
||||
* current ClassLoader
|
||||
*/
|
||||
static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> {
|
||||
private final Callable<T> task;
|
||||
private final AccessControlContext acc;
|
||||
private final ClassLoader ccl;
|
||||
|
||||
PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
// Calls to getContextClassLoader from this class
|
||||
// never trigger a security check, but we check
|
||||
// whether our callers have this permission anyways.
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
|
||||
// Whether setContextClassLoader turns out to be necessary
|
||||
// or not, we fail fast if permission is not available.
|
||||
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
|
||||
}
|
||||
this.task = task;
|
||||
this.acc = AccessController.getContext();
|
||||
this.ccl = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
|
||||
public T call() throws Exception {
|
||||
try {
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<T>() {
|
||||
public T run() throws Exception {
|
||||
Thread t = Thread.currentThread();
|
||||
ClassLoader cl = t.getContextClassLoader();
|
||||
if (ccl == cl) {
|
||||
return task.call();
|
||||
} else {
|
||||
t.setContextClassLoader(ccl);
|
||||
try {
|
||||
return task.call();
|
||||
} finally {
|
||||
t.setContextClassLoader(cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, acc);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw e.getException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The default thread factory
|
||||
*/
|
||||
static class DefaultThreadFactory implements ThreadFactory {
|
||||
private static final AtomicInteger poolNumber = new AtomicInteger(1);
|
||||
private final ThreadGroup group;
|
||||
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
private final String namePrefix;
|
||||
|
||||
DefaultThreadFactory() {
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
group = (s != null) ? s.getThreadGroup() :
|
||||
Thread.currentThread().getThreadGroup();
|
||||
namePrefix = "pool-" +
|
||||
poolNumber.getAndIncrement() +
|
||||
"-thread-";
|
||||
}
|
||||
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(group, r,
|
||||
namePrefix + threadNumber.getAndIncrement(),
|
||||
0);
|
||||
if (t.isDaemon())
|
||||
t.setDaemon(false);
|
||||
if (t.getPriority() != Thread.NORM_PRIORITY)
|
||||
t.setPriority(Thread.NORM_PRIORITY);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread factory capturing access control context and class loader
|
||||
*/
|
||||
static class PrivilegedThreadFactory extends DefaultThreadFactory {
|
||||
private final AccessControlContext acc;
|
||||
private final ClassLoader ccl;
|
||||
|
||||
PrivilegedThreadFactory() {
|
||||
super();
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
// Calls to getContextClassLoader from this class
|
||||
// never trigger a security check, but we check
|
||||
// whether our callers have this permission anyways.
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
|
||||
// Fail fast
|
||||
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
|
||||
}
|
||||
this.acc = AccessController.getContext();
|
||||
this.ccl = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
|
||||
public Thread newThread(final Runnable r) {
|
||||
return super.newThread(new Runnable() {
|
||||
public void run() {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
Thread.currentThread().setContextClassLoader(ccl);
|
||||
r.run();
|
||||
return null;
|
||||
}
|
||||
}, acc);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper class that exposes only the ExecutorService methods
|
||||
* of an ExecutorService implementation.
|
||||
*/
|
||||
static class DelegatedExecutorService extends AbstractExecutorService {
|
||||
private final ExecutorService e;
|
||||
DelegatedExecutorService(ExecutorService executor) { e = executor; }
|
||||
public void execute(Runnable command) { e.execute(command); }
|
||||
public void shutdown() { e.shutdown(); }
|
||||
public List<Runnable> shutdownNow() { return e.shutdownNow(); }
|
||||
public boolean isShutdown() { return e.isShutdown(); }
|
||||
public boolean isTerminated() { return e.isTerminated(); }
|
||||
public boolean awaitTermination(long timeout, TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
return e.awaitTermination(timeout, unit);
|
||||
}
|
||||
public Future<?> submit(Runnable task) {
|
||||
return e.submit(task);
|
||||
}
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
return e.submit(task);
|
||||
}
|
||||
public <T> Future<T> submit(Runnable task, T result) {
|
||||
return e.submit(task, result);
|
||||
}
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
|
||||
throws InterruptedException {
|
||||
return e.invokeAll(tasks);
|
||||
}
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
|
||||
long timeout, TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
return e.invokeAll(tasks, timeout, unit);
|
||||
}
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
|
||||
throws InterruptedException, ExecutionException {
|
||||
return e.invokeAny(tasks);
|
||||
}
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
|
||||
long timeout, TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
return e.invokeAny(tasks, timeout, unit);
|
||||
}
|
||||
}
|
||||
|
||||
static class FinalizableDelegatedExecutorService
|
||||
extends DelegatedExecutorService {
|
||||
FinalizableDelegatedExecutorService(ExecutorService executor) {
|
||||
super(executor);
|
||||
}
|
||||
protected void finalize() {
|
||||
super.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper class that exposes only the ScheduledExecutorService
|
||||
* methods of a ScheduledExecutorService implementation.
|
||||
*/
|
||||
static class DelegatedScheduledExecutorService
|
||||
extends DelegatedExecutorService
|
||||
implements ScheduledExecutorService {
|
||||
private final ScheduledExecutorService e;
|
||||
DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
|
||||
super(executor);
|
||||
e = executor;
|
||||
}
|
||||
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
|
||||
return e.schedule(command, delay, unit);
|
||||
}
|
||||
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
|
||||
return e.schedule(callable, delay, unit);
|
||||
}
|
||||
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
|
||||
return e.scheduleAtFixedRate(command, initialDelay, period, unit);
|
||||
}
|
||||
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
|
||||
return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
|
||||
}
|
||||
}
|
||||
|
||||
/** Cannot instantiate. */
|
||||
private Executors() {}
|
||||
}
|
||||
3487
jdkSrc/jdk8/java/util/concurrent/ForkJoinPool.java
Normal file
3487
jdkSrc/jdk8/java/util/concurrent/ForkJoinPool.java
Normal file
File diff suppressed because it is too large
Load Diff
1529
jdkSrc/jdk8/java/util/concurrent/ForkJoinTask.java
Normal file
1529
jdkSrc/jdk8/java/util/concurrent/ForkJoinTask.java
Normal file
File diff suppressed because it is too large
Load Diff
287
jdkSrc/jdk8/java/util/concurrent/ForkJoinWorkerThread.java
Normal file
287
jdkSrc/jdk8/java/util/concurrent/ForkJoinWorkerThread.java
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.ProtectionDomain;
|
||||
|
||||
/**
|
||||
* A thread managed by a {@link ForkJoinPool}, which executes
|
||||
* {@link ForkJoinTask}s.
|
||||
* This class is subclassable solely for the sake of adding
|
||||
* functionality -- there are no overridable methods dealing with
|
||||
* 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
|
||||
* {@linkplain ForkJoinPool#ForkJoinPool use it} in a {@code ForkJoinPool}.
|
||||
*
|
||||
* @since 1.7
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class ForkJoinWorkerThread extends Thread {
|
||||
/*
|
||||
* ForkJoinWorkerThreads are managed by ForkJoinPools and perform
|
||||
* ForkJoinTasks. For explanation, see the internal documentation
|
||||
* of class ForkJoinPool.
|
||||
*
|
||||
* This class just maintains links to its pool and WorkQueue. The
|
||||
* pool field is set immediately upon construction, but the
|
||||
* workQueue field is not set until a call to registerWorker
|
||||
* completes. This leads to a visibility race, that is tolerated
|
||||
* by requiring that the workQueue field is only accessed by the
|
||||
* owning thread.
|
||||
*
|
||||
* Support for (non-public) subclass InnocuousForkJoinWorkerThread
|
||||
* requires that we break quite a lot of encapsulation (via Unsafe)
|
||||
* both here and in the subclass to access and set Thread fields.
|
||||
*/
|
||||
|
||||
final ForkJoinPool pool; // the pool this thread works in
|
||||
final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
|
||||
|
||||
/** An AccessControlContext supporting no privileges */
|
||||
private static final AccessControlContext INNOCUOUS_ACC =
|
||||
new AccessControlContext(
|
||||
new ProtectionDomain[] { new ProtectionDomain(null, null) });
|
||||
|
||||
/**
|
||||
* Creates a ForkJoinWorkerThread operating in the given pool.
|
||||
*
|
||||
* @param pool the pool this thread works in
|
||||
* @throws NullPointerException if pool is null
|
||||
*/
|
||||
protected ForkJoinWorkerThread(ForkJoinPool pool) {
|
||||
// Use a placeholder until a useful name can be set in registerWorker
|
||||
super("aForkJoinWorkerThread");
|
||||
this.pool = pool;
|
||||
this.workQueue = pool.registerWorker(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version for use by the default pool. This is a separate constructor to
|
||||
* avoid affecting the protected constructor.
|
||||
*/
|
||||
ForkJoinWorkerThread(ForkJoinPool pool, boolean innocuous) {
|
||||
super("aForkJoinWorkerThread");
|
||||
if (innocuous) {
|
||||
U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, INNOCUOUS_ACC);
|
||||
}
|
||||
this.pool = pool;
|
||||
this.workQueue = pool.registerWorker(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version for InnocuousForkJoinWorkerThread
|
||||
*/
|
||||
ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
|
||||
AccessControlContext acc) {
|
||||
super(threadGroup, null, "aForkJoinWorkerThread");
|
||||
U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);
|
||||
eraseThreadLocals(); // clear before registering
|
||||
this.pool = pool;
|
||||
this.workQueue = pool.registerWorker(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pool hosting this thread.
|
||||
*
|
||||
* @return the pool
|
||||
*/
|
||||
public ForkJoinPool getPool() {
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.getPoolIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes internal state after construction but before
|
||||
* processing any tasks. If you override this method, you must
|
||||
* invoke {@code super.onStart()} at the beginning of the method.
|
||||
* Initialization requires care: Most fields must have legal
|
||||
* default values, to ensure that attempted accesses from other
|
||||
* threads work correctly even before this thread starts
|
||||
* processing tasks.
|
||||
*/
|
||||
protected void onStart() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs cleanup associated with termination of this worker
|
||||
* thread. If you override this method, you must invoke
|
||||
* {@code super.onTermination} at the end of the overridden method.
|
||||
*
|
||||
* @param exception the exception causing this thread to abort due
|
||||
* to an unrecoverable error, or {@code null} if completed normally
|
||||
*/
|
||||
protected void onTermination(Throwable exception) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required to be public, but should never be
|
||||
* called explicitly. It performs the main run loop to execute
|
||||
* {@link ForkJoinTask}s.
|
||||
*/
|
||||
public void run() {
|
||||
if (workQueue.array == null) { // only run once
|
||||
Throwable exception = null;
|
||||
try {
|
||||
onStart();
|
||||
pool.runWorker(workQueue);
|
||||
} catch (Throwable ex) {
|
||||
exception = ex;
|
||||
} finally {
|
||||
try {
|
||||
onTermination(exception);
|
||||
} catch (Throwable ex) {
|
||||
if (exception == null)
|
||||
exception = ex;
|
||||
} finally {
|
||||
pool.deregisterWorker(this, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Erases ThreadLocals by nulling out Thread maps.
|
||||
*/
|
||||
final void eraseThreadLocals() {
|
||||
U.putObject(this, THREADLOCALS, null);
|
||||
U.putObject(this, INHERITABLETHREADLOCALS, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-public hook method for InnocuousForkJoinWorkerThread
|
||||
*/
|
||||
void afterTopLevelExec() {
|
||||
}
|
||||
|
||||
// Set up to allow setting thread fields in constructor
|
||||
private static final sun.misc.Unsafe U;
|
||||
private static final long THREADLOCALS;
|
||||
private static final long INHERITABLETHREADLOCALS;
|
||||
private static final long INHERITEDACCESSCONTROLCONTEXT;
|
||||
static {
|
||||
try {
|
||||
U = sun.misc.Unsafe.getUnsafe();
|
||||
Class<?> tk = Thread.class;
|
||||
THREADLOCALS = U.objectFieldOffset
|
||||
(tk.getDeclaredField("threadLocals"));
|
||||
INHERITABLETHREADLOCALS = U.objectFieldOffset
|
||||
(tk.getDeclaredField("inheritableThreadLocals"));
|
||||
INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
|
||||
(tk.getDeclaredField("inheritedAccessControlContext"));
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A worker thread that has no permissions, is not a member of any
|
||||
* user-defined ThreadGroup, and erases all ThreadLocals after
|
||||
* running each top-level task.
|
||||
*/
|
||||
static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
|
||||
/** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
|
||||
private static final ThreadGroup innocuousThreadGroup =
|
||||
createThreadGroup();
|
||||
|
||||
InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
|
||||
super(pool, innocuousThreadGroup, INNOCUOUS_ACC);
|
||||
}
|
||||
|
||||
@Override // to erase ThreadLocals
|
||||
void afterTopLevelExec() {
|
||||
eraseThreadLocals();
|
||||
}
|
||||
|
||||
@Override // to always report system loader
|
||||
public ClassLoader getContextClassLoader() {
|
||||
return ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
|
||||
@Override // to silently fail
|
||||
public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }
|
||||
|
||||
@Override // paranoically
|
||||
public void setContextClassLoader(ClassLoader cl) {
|
||||
throw new SecurityException("setContextClassLoader");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new group with the system ThreadGroup (the
|
||||
* topmost, parent-less group) as parent. Uses Unsafe to
|
||||
* traverse Thread.group and ThreadGroup.parent fields.
|
||||
*/
|
||||
private static ThreadGroup createThreadGroup() {
|
||||
try {
|
||||
sun.misc.Unsafe u = sun.misc.Unsafe.getUnsafe();
|
||||
Class<?> tk = Thread.class;
|
||||
Class<?> gk = ThreadGroup.class;
|
||||
long tg = u.objectFieldOffset(tk.getDeclaredField("group"));
|
||||
long gp = u.objectFieldOffset(gk.getDeclaredField("parent"));
|
||||
ThreadGroup group = (ThreadGroup)
|
||||
u.getObject(Thread.currentThread(), tg);
|
||||
while (group != null) {
|
||||
ThreadGroup parent = (ThreadGroup)u.getObject(group, gp);
|
||||
if (parent == null)
|
||||
return new ThreadGroup(group,
|
||||
"InnocuousForkJoinWorkerThreadGroup");
|
||||
group = parent;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
// fall through if null as cannot-happen safeguard
|
||||
throw new Error("Cannot create ThreadGroup");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
169
jdkSrc/jdk8/java/util/concurrent/Future.java
Normal file
169
jdkSrc/jdk8/java/util/concurrent/Future.java
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* {@code get} when the computation has completed, blocking if
|
||||
* necessary until it is ready. Cancellation is performed by the
|
||||
* {@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 {@code Future} for the sake
|
||||
* of cancellability but not provide a usable result, you can
|
||||
* declare types of the form {@code Future<?>} and
|
||||
* return {@code null} as a result of the underlying task.
|
||||
*
|
||||
* <p>
|
||||
* <b>Sample Usage</b> (Note that the following classes are all
|
||||
* made-up.)
|
||||
* <pre> {@code
|
||||
* interface ArchiveSearcher { String search(String target); }
|
||||
* class App {
|
||||
* ExecutorService executor = ...
|
||||
* ArchiveSearcher searcher = ...
|
||||
* void showSearch(final String target)
|
||||
* throws InterruptedException {
|
||||
* Future<String> future
|
||||
* = executor.submit(new Callable<String>() {
|
||||
* public String call() {
|
||||
* return searcher.search(target);
|
||||
* }});
|
||||
* displayOtherThings(); // do other things while searching
|
||||
* try {
|
||||
* displayText(future.get()); // use future
|
||||
* } catch (ExecutionException ex) { cleanup(); return; }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* 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>() {
|
||||
* public String call() {
|
||||
* return searcher.search(target);
|
||||
* }});
|
||||
* executor.execute(future);}</pre>
|
||||
*
|
||||
* <p>Memory consistency effects: Actions taken by the asynchronous computation
|
||||
* <a href="package-summary.html#MemoryVisibility"> <i>happen-before</i></a>
|
||||
* actions following the corresponding {@code Future.get()} in another thread.
|
||||
*
|
||||
* @see FutureTask
|
||||
* @see Executor
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <V> The result type returned by this Future's {@code get} method
|
||||
*/
|
||||
public interface Future<V> {
|
||||
|
||||
/**
|
||||
* 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 {@code cancel} is called,
|
||||
* this task should never run. If the task has already started,
|
||||
* 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 {@code true}. Subsequent calls to {@link #isCancelled}
|
||||
* will always return {@code true} if this method returned {@code true}.
|
||||
*
|
||||
* @param mayInterruptIfRunning {@code true} if the thread executing this
|
||||
* task should be interrupted; otherwise, in-progress tasks are allowed
|
||||
* to complete
|
||||
* @return {@code false} if the task could not be cancelled,
|
||||
* typically because it has already completed normally;
|
||||
* {@code true} otherwise
|
||||
*/
|
||||
boolean cancel(boolean mayInterruptIfRunning);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this task was cancelled before it completed
|
||||
* normally.
|
||||
*
|
||||
* @return {@code true} if this task was cancelled before it completed
|
||||
*/
|
||||
boolean isCancelled();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* {@code true}.
|
||||
*
|
||||
* @return {@code true} if this task completed
|
||||
*/
|
||||
boolean isDone();
|
||||
|
||||
/**
|
||||
* Waits if necessary for the computation to complete, and then
|
||||
* retrieves its result.
|
||||
*
|
||||
* @return the computed result
|
||||
* @throws CancellationException if the computation was cancelled
|
||||
* @throws ExecutionException if the computation threw an
|
||||
* exception
|
||||
* @throws InterruptedException if the current thread was interrupted
|
||||
* while waiting
|
||||
*/
|
||||
V get() throws InterruptedException, ExecutionException;
|
||||
|
||||
/**
|
||||
* Waits if necessary for at most the given time for the computation
|
||||
* to complete, and then retrieves its result, if available.
|
||||
*
|
||||
* @param timeout the maximum time to wait
|
||||
* @param unit the time unit of the timeout argument
|
||||
* @return the computed result
|
||||
* @throws CancellationException if the computation was cancelled
|
||||
* @throws ExecutionException if the computation threw an
|
||||
* exception
|
||||
* @throws InterruptedException if the current thread was interrupted
|
||||
* while waiting
|
||||
* @throws TimeoutException if the wait timed out
|
||||
*/
|
||||
V get(long timeout, TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException, TimeoutException;
|
||||
}
|
||||
486
jdkSrc/jdk8/java/util/concurrent/FutureTask.java
Normal file
486
jdkSrc/jdk8/java/util/concurrent/FutureTask.java
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
/**
|
||||
* A cancellable asynchronous computation. This class provides a base
|
||||
* implementation of {@link Future}, with methods to start and cancel
|
||||
* a computation, query to see if the computation is complete, and
|
||||
* retrieve the result of the computation. The result can only be
|
||||
* retrieved when the computation has completed; the {@code get}
|
||||
* methods will block if the computation has not yet completed. Once
|
||||
* the computation has completed, the computation cannot be restarted
|
||||
* or cancelled (unless the computation is invoked using
|
||||
* {@link #runAndReset}).
|
||||
*
|
||||
* <p>A {@code FutureTask} can be used to wrap a {@link Callable} or
|
||||
* {@link Runnable} object. Because {@code FutureTask} implements
|
||||
* {@code Runnable}, a {@code FutureTask} can be submitted to an
|
||||
* {@link Executor} for execution.
|
||||
*
|
||||
* <p>In addition to serving as a standalone class, this class provides
|
||||
* {@code protected} functionality that may be useful when creating
|
||||
* customized task classes.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <V> The result type returned by this FutureTask's {@code get} methods
|
||||
*/
|
||||
public class FutureTask<V> implements RunnableFuture<V> {
|
||||
/*
|
||||
* Revision notes: This differs from previous versions of this
|
||||
* class that relied on AbstractQueuedSynchronizer, mainly to
|
||||
* avoid surprising users about retaining interrupt status during
|
||||
* cancellation races. Sync control in the current design relies
|
||||
* on a "state" field updated via CAS to track completion, along
|
||||
* with a simple Treiber stack to hold waiting threads.
|
||||
*
|
||||
* Style note: As usual, we bypass overhead of using
|
||||
* AtomicXFieldUpdaters and instead directly use Unsafe intrinsics.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The run state of this task, initially NEW. The run state
|
||||
* transitions to a terminal state only in methods set,
|
||||
* setException, and cancel. During completion, state may take on
|
||||
* transient values of COMPLETING (while outcome is being set) or
|
||||
* INTERRUPTING (only while interrupting the runner to satisfy a
|
||||
* cancel(true)). Transitions from these intermediate to final
|
||||
* states use cheaper ordered/lazy writes because values are unique
|
||||
* and cannot be further modified.
|
||||
*
|
||||
* Possible state transitions:
|
||||
* NEW -> COMPLETING -> NORMAL
|
||||
* NEW -> COMPLETING -> EXCEPTIONAL
|
||||
* NEW -> CANCELLED
|
||||
* NEW -> INTERRUPTING -> INTERRUPTED
|
||||
*/
|
||||
private volatile int state;
|
||||
private static final int NEW = 0;
|
||||
private static final int COMPLETING = 1;
|
||||
private static final int NORMAL = 2;
|
||||
private static final int EXCEPTIONAL = 3;
|
||||
private static final int CANCELLED = 4;
|
||||
private static final int INTERRUPTING = 5;
|
||||
private static final int INTERRUPTED = 6;
|
||||
|
||||
/** The underlying callable; nulled out after running */
|
||||
private Callable<V> callable;
|
||||
/** The result to return or exception to throw from get() */
|
||||
private Object outcome; // non-volatile, protected by state reads/writes
|
||||
/** The thread running the callable; CASed during run() */
|
||||
private volatile Thread runner;
|
||||
/** Treiber stack of waiting threads */
|
||||
private volatile WaitNode waiters;
|
||||
|
||||
/**
|
||||
* Returns result or throws exception for completed task.
|
||||
*
|
||||
* @param s completed state value
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private V report(int s) throws ExecutionException {
|
||||
Object x = outcome;
|
||||
if (s == NORMAL)
|
||||
return (V)x;
|
||||
if (s >= CANCELLED)
|
||||
throw new CancellationException();
|
||||
throw new ExecutionException((Throwable)x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code FutureTask} that will, upon running, execute the
|
||||
* given {@code Callable}.
|
||||
*
|
||||
* @param callable the callable task
|
||||
* @throws NullPointerException if the callable is null
|
||||
*/
|
||||
public FutureTask(Callable<V> callable) {
|
||||
if (callable == null)
|
||||
throw new NullPointerException();
|
||||
this.callable = callable;
|
||||
this.state = NEW; // ensure visibility of callable
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code FutureTask} that will, upon running, execute the
|
||||
* given {@code Runnable}, and arrange that {@code get} will return the
|
||||
* given result on successful completion.
|
||||
*
|
||||
* @param runnable the runnable task
|
||||
* @param result the result to return on successful completion. If
|
||||
* you don't need a particular result, consider using
|
||||
* constructions of the form:
|
||||
* {@code Future<?> f = new FutureTask<Void>(runnable, null)}
|
||||
* @throws NullPointerException if the runnable is null
|
||||
*/
|
||||
public FutureTask(Runnable runnable, V result) {
|
||||
this.callable = Executors.callable(runnable, result);
|
||||
this.state = NEW; // ensure visibility of callable
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return state >= CANCELLED;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return state != NEW;
|
||||
}
|
||||
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
if (!(state == NEW &&
|
||||
UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
|
||||
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
|
||||
return false;
|
||||
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();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws CancellationException {@inheritDoc}
|
||||
*/
|
||||
public V get() throws InterruptedException, ExecutionException {
|
||||
int s = state;
|
||||
if (s <= COMPLETING)
|
||||
s = awaitDone(false, 0L);
|
||||
return report(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws CancellationException {@inheritDoc}
|
||||
*/
|
||||
public V get(long timeout, TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
if (unit == null)
|
||||
throw new NullPointerException();
|
||||
int s = state;
|
||||
if (s <= COMPLETING &&
|
||||
(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
|
||||
throw new TimeoutException();
|
||||
return report(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected method invoked when this task transitions to state
|
||||
* {@code isDone} (whether normally or via cancellation). The
|
||||
* default implementation does nothing. Subclasses may override
|
||||
* this method to invoke completion callbacks or perform
|
||||
* bookkeeping. Note that you can query status inside the
|
||||
* implementation of this method to determine whether this task
|
||||
* has been cancelled.
|
||||
*/
|
||||
protected void done() { }
|
||||
|
||||
/**
|
||||
* Sets the result of this future to the given value unless
|
||||
* this future has already been set or has been cancelled.
|
||||
*
|
||||
* <p>This method is invoked internally by the {@link #run} method
|
||||
* upon successful completion of the computation.
|
||||
*
|
||||
* @param v the value
|
||||
*/
|
||||
protected void set(V v) {
|
||||
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
|
||||
outcome = v;
|
||||
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
|
||||
finishCompletion();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes this future to report an {@link ExecutionException}
|
||||
* with the given throwable as its cause, unless this future has
|
||||
* already been set or has been cancelled.
|
||||
*
|
||||
* <p>This method is invoked internally by the {@link #run} method
|
||||
* upon failure of the computation.
|
||||
*
|
||||
* @param t the cause of failure
|
||||
*/
|
||||
protected void setException(Throwable t) {
|
||||
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
|
||||
outcome = t;
|
||||
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
|
||||
finishCompletion();
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (state != NEW ||
|
||||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
|
||||
null, Thread.currentThread()))
|
||||
return;
|
||||
try {
|
||||
Callable<V> c = callable;
|
||||
if (c != null && state == NEW) {
|
||||
V result;
|
||||
boolean ran;
|
||||
try {
|
||||
result = c.call();
|
||||
ran = true;
|
||||
} catch (Throwable ex) {
|
||||
result = null;
|
||||
ran = false;
|
||||
setException(ex);
|
||||
}
|
||||
if (ran)
|
||||
set(result);
|
||||
}
|
||||
} finally {
|
||||
// runner must be non-null until state is settled to
|
||||
// prevent concurrent calls to run()
|
||||
runner = null;
|
||||
// state must be re-read after nulling runner to prevent
|
||||
// leaked interrupts
|
||||
int s = state;
|
||||
if (s >= INTERRUPTING)
|
||||
handlePossibleCancellationInterrupt(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the computation without setting its result, and then
|
||||
* resets this future to initial state, failing to do so if the
|
||||
* computation encounters an exception or is cancelled. This is
|
||||
* designed for use with tasks that intrinsically execute more
|
||||
* than once.
|
||||
*
|
||||
* @return {@code true} if successfully run and reset
|
||||
*/
|
||||
protected boolean runAndReset() {
|
||||
if (state != NEW ||
|
||||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
|
||||
null, Thread.currentThread()))
|
||||
return false;
|
||||
boolean ran = false;
|
||||
int s = state;
|
||||
try {
|
||||
Callable<V> c = callable;
|
||||
if (c != null && s == NEW) {
|
||||
try {
|
||||
c.call(); // don't set result
|
||||
ran = true;
|
||||
} catch (Throwable ex) {
|
||||
setException(ex);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// runner must be non-null until state is settled to
|
||||
// prevent concurrent calls to run()
|
||||
runner = null;
|
||||
// state must be re-read after nulling runner to prevent
|
||||
// leaked interrupts
|
||||
s = state;
|
||||
if (s >= INTERRUPTING)
|
||||
handlePossibleCancellationInterrupt(s);
|
||||
}
|
||||
return ran && s == NEW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that any interrupt from a possible cancel(true) is only
|
||||
* delivered to a task while in run or runAndReset.
|
||||
*/
|
||||
private void handlePossibleCancellationInterrupt(int s) {
|
||||
// It is possible for our interrupter to stall before getting a
|
||||
// chance to interrupt us. Let's spin-wait patiently.
|
||||
if (s == INTERRUPTING)
|
||||
while (state == INTERRUPTING)
|
||||
Thread.yield(); // wait out pending interrupt
|
||||
|
||||
// assert state == INTERRUPTED;
|
||||
|
||||
// We want to clear any interrupt we may have received from
|
||||
// cancel(true). However, it is permissible to use interrupts
|
||||
// as an independent mechanism for a task to communicate with
|
||||
// its caller, and there is no way to clear only the
|
||||
// cancellation interrupt.
|
||||
//
|
||||
// Thread.interrupted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple linked list nodes to record waiting threads in a Treiber
|
||||
* stack. See other classes such as Phaser and SynchronousQueue
|
||||
* for more detailed explanation.
|
||||
*/
|
||||
static final class WaitNode {
|
||||
volatile Thread thread;
|
||||
volatile WaitNode next;
|
||||
WaitNode() { thread = Thread.currentThread(); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and signals all waiting threads, invokes done(), and
|
||||
* nulls out callable.
|
||||
*/
|
||||
private void finishCompletion() {
|
||||
// assert state > COMPLETING;
|
||||
for (WaitNode q; (q = waiters) != null;) {
|
||||
if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
|
||||
for (;;) {
|
||||
Thread t = q.thread;
|
||||
if (t != null) {
|
||||
q.thread = null;
|
||||
LockSupport.unpark(t);
|
||||
}
|
||||
WaitNode next = q.next;
|
||||
if (next == null)
|
||||
break;
|
||||
q.next = null; // unlink to help gc
|
||||
q = next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done();
|
||||
|
||||
callable = null; // to reduce footprint
|
||||
}
|
||||
|
||||
/**
|
||||
* Awaits completion or aborts on interrupt or timeout.
|
||||
*
|
||||
* @param timed true if use timed waits
|
||||
* @param nanos time to wait, if timed
|
||||
* @return state upon completion
|
||||
*/
|
||||
private int awaitDone(boolean timed, long nanos)
|
||||
throws InterruptedException {
|
||||
final long deadline = timed ? System.nanoTime() + nanos : 0L;
|
||||
WaitNode q = null;
|
||||
boolean queued = false;
|
||||
for (;;) {
|
||||
if (Thread.interrupted()) {
|
||||
removeWaiter(q);
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
int s = state;
|
||||
if (s > COMPLETING) {
|
||||
if (q != null)
|
||||
q.thread = null;
|
||||
return s;
|
||||
}
|
||||
else if (s == COMPLETING) // cannot time out yet
|
||||
Thread.yield();
|
||||
else if (q == null)
|
||||
q = new WaitNode();
|
||||
else if (!queued)
|
||||
queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
|
||||
q.next = waiters, q);
|
||||
else if (timed) {
|
||||
nanos = deadline - System.nanoTime();
|
||||
if (nanos <= 0L) {
|
||||
removeWaiter(q);
|
||||
return state;
|
||||
}
|
||||
LockSupport.parkNanos(this, nanos);
|
||||
}
|
||||
else
|
||||
LockSupport.park(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to unlink a timed-out or interrupted wait node to avoid
|
||||
* accumulating garbage. Internal nodes are simply unspliced
|
||||
* without CAS since it is harmless if they are traversed anyway
|
||||
* by releasers. To avoid effects of unsplicing from already
|
||||
* removed nodes, the list is retraversed in case of an apparent
|
||||
* race. This is slow when there are a lot of nodes, but we don't
|
||||
* expect lists to be long enough to outweigh higher-overhead
|
||||
* schemes.
|
||||
*/
|
||||
private void removeWaiter(WaitNode node) {
|
||||
if (node != null) {
|
||||
node.thread = null;
|
||||
retry:
|
||||
for (;;) { // restart on removeWaiter race
|
||||
for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
|
||||
s = q.next;
|
||||
if (q.thread != null)
|
||||
pred = q;
|
||||
else if (pred != null) {
|
||||
pred.next = s;
|
||||
if (pred.thread == null) // check for race
|
||||
continue retry;
|
||||
}
|
||||
else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
|
||||
q, s))
|
||||
continue retry;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long stateOffset;
|
||||
private static final long runnerOffset;
|
||||
private static final long waitersOffset;
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class<?> k = FutureTask.class;
|
||||
stateOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("state"));
|
||||
runnerOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("runner"));
|
||||
waitersOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("waiters"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1333
jdkSrc/jdk8/java/util/concurrent/LinkedBlockingDeque.java
Normal file
1333
jdkSrc/jdk8/java/util/concurrent/LinkedBlockingDeque.java
Normal file
File diff suppressed because it is too large
Load Diff
1044
jdkSrc/jdk8/java/util/concurrent/LinkedBlockingQueue.java
Normal file
1044
jdkSrc/jdk8/java/util/concurrent/LinkedBlockingQueue.java
Normal file
File diff suppressed because it is too large
Load Diff
1481
jdkSrc/jdk8/java/util/concurrent/LinkedTransferQueue.java
Normal file
1481
jdkSrc/jdk8/java/util/concurrent/LinkedTransferQueue.java
Normal file
File diff suppressed because it is too large
Load Diff
1161
jdkSrc/jdk8/java/util/concurrent/Phaser.java
Normal file
1161
jdkSrc/jdk8/java/util/concurrent/Phaser.java
Normal file
File diff suppressed because it is too large
Load Diff
1045
jdkSrc/jdk8/java/util/concurrent/PriorityBlockingQueue.java
Normal file
1045
jdkSrc/jdk8/java/util/concurrent/PriorityBlockingQueue.java
Normal file
File diff suppressed because it is too large
Load Diff
193
jdkSrc/jdk8/java/util/concurrent/RecursiveAction.java
Normal file
193
jdkSrc/jdk8/java/util/concurrent/RecursiveAction.java
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A recursive resultless {@link ForkJoinTask}. This class
|
||||
* establishes conventions to parameterize resultless actions as
|
||||
* {@code Void} {@code ForkJoinTask}s. Because {@code null} is the
|
||||
* only valid value of type {@code Void}, methods such as {@code join}
|
||||
* always return {@code null} upon completion.
|
||||
*
|
||||
* <p><b>Sample Usages.</b> Here is a simple but complete ForkJoin
|
||||
* sort that sorts a given {@code long[]} array:
|
||||
*
|
||||
* <pre> {@code
|
||||
* static class SortTask extends RecursiveAction {
|
||||
* final long[] array; final int lo, hi;
|
||||
* SortTask(long[] array, int lo, int hi) {
|
||||
* this.array = array; this.lo = lo; this.hi = hi;
|
||||
* }
|
||||
* SortTask(long[] array) { this(array, 0, array.length); }
|
||||
* protected void compute() {
|
||||
* if (hi - lo < THRESHOLD)
|
||||
* sortSequentially(lo, hi);
|
||||
* else {
|
||||
* int mid = (lo + hi) >>> 1;
|
||||
* invokeAll(new SortTask(array, lo, mid),
|
||||
* new SortTask(array, mid, hi));
|
||||
* merge(lo, mid, hi);
|
||||
* }
|
||||
* }
|
||||
* // implementation details follow:
|
||||
* static final int THRESHOLD = 1000;
|
||||
* void sortSequentially(int lo, int hi) {
|
||||
* Arrays.sort(array, lo, hi);
|
||||
* }
|
||||
* void merge(int lo, int mid, int hi) {
|
||||
* long[] buf = Arrays.copyOfRange(array, lo, mid);
|
||||
* for (int i = 0, j = lo, k = mid; i < buf.length; j++)
|
||||
* array[j] = (k == hi || buf[i] < array[k]) ?
|
||||
* buf[i++] : array[k++];
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* You could then sort {@code anArray} by creating {@code new
|
||||
* SortTask(anArray)} and invoking it in a ForkJoinPool. As a more
|
||||
* concrete simple example, the following task increments each element
|
||||
* of an array:
|
||||
* <pre> {@code
|
||||
* class IncrementTask extends RecursiveAction {
|
||||
* final long[] array; final int lo, hi;
|
||||
* IncrementTask(long[] array, int lo, int hi) {
|
||||
* this.array = array; this.lo = lo; this.hi = hi;
|
||||
* }
|
||||
* protected void compute() {
|
||||
* if (hi - lo < THRESHOLD) {
|
||||
* for (int i = lo; i < hi; ++i)
|
||||
* array[i]++;
|
||||
* }
|
||||
* else {
|
||||
* int mid = (lo + hi) >>> 1;
|
||||
* invokeAll(new IncrementTask(array, lo, mid),
|
||||
* new IncrementTask(array, mid, hi));
|
||||
* }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>The following example illustrates some refinements and idioms
|
||||
* that may lead to better performance: RecursiveActions need not be
|
||||
* fully recursive, so long as they maintain the basic
|
||||
* divide-and-conquer approach. Here is a class that sums the squares
|
||||
* of each element of a double array, by subdividing out only the
|
||||
* right-hand-sides of repeated divisions by two, and keeping track of
|
||||
* them with a chain of {@code next} references. It uses a dynamic
|
||||
* threshold based on method {@code getSurplusQueuedTaskCount}, but
|
||||
* counterbalances potential excess partitioning by directly
|
||||
* performing leaf actions on unstolen tasks rather than further
|
||||
* subdividing.
|
||||
*
|
||||
* <pre> {@code
|
||||
* double sumOfSquares(ForkJoinPool pool, double[] array) {
|
||||
* int n = array.length;
|
||||
* Applyer a = new Applyer(array, 0, n, null);
|
||||
* pool.invoke(a);
|
||||
* return a.result;
|
||||
* }
|
||||
*
|
||||
* class Applyer extends RecursiveAction {
|
||||
* final double[] array;
|
||||
* final int lo, hi;
|
||||
* double result;
|
||||
* Applyer next; // keeps track of right-hand-side tasks
|
||||
* Applyer(double[] array, int lo, int hi, Applyer next) {
|
||||
* this.array = array; this.lo = lo; this.hi = hi;
|
||||
* this.next = next;
|
||||
* }
|
||||
*
|
||||
* double atLeaf(int l, int h) {
|
||||
* double sum = 0;
|
||||
* for (int i = l; i < h; ++i) // perform leftmost base step
|
||||
* sum += array[i] * array[i];
|
||||
* return sum;
|
||||
* }
|
||||
*
|
||||
* protected void compute() {
|
||||
* int l = lo;
|
||||
* 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;
|
||||
* }
|
||||
* double sum = atLeaf(l, h);
|
||||
* while (right != null) {
|
||||
* if (right.tryUnfork()) // directly calculate if not stolen
|
||||
* sum += right.atLeaf(right.lo, right.hi);
|
||||
* else {
|
||||
* right.join();
|
||||
* sum += right.result;
|
||||
* }
|
||||
* right = right.next;
|
||||
* }
|
||||
* result = sum;
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* @since 1.7
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public abstract class RecursiveAction extends ForkJoinTask<Void> {
|
||||
private static final long serialVersionUID = 5232453952276485070L;
|
||||
|
||||
/**
|
||||
* The main computation performed by this task.
|
||||
*/
|
||||
protected abstract void compute();
|
||||
|
||||
/**
|
||||
* Always returns {@code null}.
|
||||
*
|
||||
* @return {@code null} always
|
||||
*/
|
||||
public final Void getRawResult() { return null; }
|
||||
|
||||
/**
|
||||
* Requires null completion value.
|
||||
*/
|
||||
protected final void setRawResult(Void mustBeNull) { }
|
||||
|
||||
/**
|
||||
* Implements execution conventions for RecursiveActions.
|
||||
*/
|
||||
protected final boolean exec() {
|
||||
compute();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
98
jdkSrc/jdk8/java/util/concurrent/RecursiveTask.java
Normal file
98
jdkSrc/jdk8/java/util/concurrent/RecursiveTask.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A recursive result-bearing {@link ForkJoinTask}.
|
||||
*
|
||||
* <p>For a classic example, here is a task computing Fibonacci numbers:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class Fibonacci extends RecursiveTask<Integer> {
|
||||
* final int n;
|
||||
* Fibonacci(int n) { this.n = n; }
|
||||
* Integer compute() {
|
||||
* if (n <= 1)
|
||||
* return n;
|
||||
* Fibonacci f1 = new Fibonacci(n - 1);
|
||||
* f1.fork();
|
||||
* Fibonacci f2 = new Fibonacci(n - 2);
|
||||
* return f2.compute() + f1.join();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* However, besides being a dumb way to compute Fibonacci functions
|
||||
* (there is a simple fast linear algorithm that you'd use in
|
||||
* practice), this is likely to perform poorly because the smallest
|
||||
* subtasks are too small to be worthwhile splitting up. Instead, as
|
||||
* is the case for nearly all fork/join applications, you'd pick some
|
||||
* minimum granularity size (for example 10 here) for which you always
|
||||
* sequentially solve rather than subdividing.
|
||||
*
|
||||
* @since 1.7
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public abstract class RecursiveTask<V> extends ForkJoinTask<V> {
|
||||
private static final long serialVersionUID = 5232453952276485270L;
|
||||
|
||||
/**
|
||||
* The result of the computation.
|
||||
*/
|
||||
V result;
|
||||
|
||||
/**
|
||||
* The main computation performed by this task.
|
||||
* @return the result of the computation
|
||||
*/
|
||||
protected abstract V compute();
|
||||
|
||||
public final V getRawResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
protected final void setRawResult(V value) {
|
||||
result = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements execution conventions for RecursiveTask.
|
||||
*/
|
||||
protected final boolean exec() {
|
||||
result = compute();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* Exception thrown by an {@link Executor} when a task cannot be
|
||||
* accepted for execution.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class RejectedExecutionException extends RuntimeException {
|
||||
private static final long serialVersionUID = -375805702767069545L;
|
||||
|
||||
/**
|
||||
* 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 {@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}.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public RejectedExecutionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@code RejectedExecutionException} with the
|
||||
* specified detail message and cause.
|
||||
*
|
||||
* @param message the detail message
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link #getCause()} method)
|
||||
*/
|
||||
public RejectedExecutionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {@code cause}).
|
||||
*
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link #getCause()} method)
|
||||
*/
|
||||
public RejectedExecutionException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A handler for tasks that cannot be executed by a {@link ThreadPoolExecutor}.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface RejectedExecutionHandler {
|
||||
|
||||
/**
|
||||
* Method that may be invoked by a {@link ThreadPoolExecutor} when
|
||||
* {@link ThreadPoolExecutor#execute execute} cannot accept a
|
||||
* task. This may occur when no more threads or queue slots are
|
||||
* available because their bounds would be exceeded, or upon
|
||||
* shutdown of the Executor.
|
||||
*
|
||||
* <p>In the absence of other alternatives, the method may throw
|
||||
* an unchecked {@link RejectedExecutionException}, which will be
|
||||
* propagated to the caller of {@code execute}.
|
||||
*
|
||||
* @param r the runnable task requested to be executed
|
||||
* @param executor the executor attempting to execute this task
|
||||
* @throws RejectedExecutionException if there is no remedy
|
||||
*/
|
||||
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
|
||||
}
|
||||
54
jdkSrc/jdk8/java/util/concurrent/RunnableFuture.java
Normal file
54
jdkSrc/jdk8/java/util/concurrent/RunnableFuture.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A {@link Future} that is {@link Runnable}. Successful 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 {@code get} method
|
||||
*/
|
||||
public interface RunnableFuture<V> extends Runnable, Future<V> {
|
||||
/**
|
||||
* Sets this Future to the result of its computation
|
||||
* unless it has been cancelled.
|
||||
*/
|
||||
void run();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A {@link ScheduledFuture} that is {@link Runnable}. Successful
|
||||
* 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 {@code get} method
|
||||
*/
|
||||
public interface RunnableScheduledFuture<V> extends RunnableFuture<V>, ScheduledFuture<V> {
|
||||
|
||||
/**
|
||||
* 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 {@code true} if this task is periodic
|
||||
*/
|
||||
boolean isPeriodic();
|
||||
}
|
||||
186
jdkSrc/jdk8/java/util/concurrent/ScheduledExecutorService.java
Normal file
186
jdkSrc/jdk8/java/util/concurrent/ScheduledExecutorService.java
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* An {@link ExecutorService} that can schedule commands to run after a given
|
||||
* delay, or to execute periodically.
|
||||
*
|
||||
* <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 {@code scheduleAtFixedRate} and
|
||||
* {@code scheduleWithFixedDelay} methods create and execute tasks
|
||||
* that run periodically until cancelled.
|
||||
*
|
||||
* <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 {@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 {@code date}, you can use: {@code schedule(task,
|
||||
* date.getTime() - System.currentTimeMillis(),
|
||||
* 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.
|
||||
*
|
||||
* <p>The {@link Executors} class provides convenient factory methods for
|
||||
* the ScheduledExecutorService implementations provided in this package.
|
||||
*
|
||||
* <h3>Usage Example</h3>
|
||||
*
|
||||
* Here is a class with a method that sets up a ScheduledExecutorService
|
||||
* to beep every ten seconds for an hour:
|
||||
*
|
||||
* <pre> {@code
|
||||
* import static java.util.concurrent.TimeUnit.*;
|
||||
* class BeeperControl {
|
||||
* private final ScheduledExecutorService scheduler =
|
||||
* Executors.newScheduledThreadPool(1);
|
||||
*
|
||||
* public void beepForAnHour() {
|
||||
* final Runnable beeper = new Runnable() {
|
||||
* public void run() { System.out.println("beep"); }
|
||||
* };
|
||||
* final ScheduledFuture<?> beeperHandle =
|
||||
* scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
|
||||
* scheduler.schedule(new Runnable() {
|
||||
* public void run() { beeperHandle.cancel(true); }
|
||||
* }, 60 * 60, SECONDS);
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface ScheduledExecutorService extends ExecutorService {
|
||||
|
||||
/**
|
||||
* Creates and executes a one-shot action that becomes enabled
|
||||
* after the given delay.
|
||||
*
|
||||
* @param command the task to execute
|
||||
* @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 {@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
|
||||
*/
|
||||
public ScheduledFuture<?> schedule(Runnable command,
|
||||
long delay, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Creates and executes a ScheduledFuture that becomes enabled after the
|
||||
* given delay.
|
||||
*
|
||||
* @param callable the function to execute
|
||||
* @param delay the time from now to delay execution
|
||||
* @param unit the time unit of the delay parameter
|
||||
* @param <V> the type of the callable's result
|
||||
* @return a ScheduledFuture that can be used to extract result or cancel
|
||||
* @throws RejectedExecutionException if the task cannot be
|
||||
* scheduled for execution
|
||||
* @throws NullPointerException if callable is null
|
||||
*/
|
||||
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
|
||||
long delay, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* {@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
|
||||
* termination of the executor. If any execution of this task
|
||||
* takes longer than its period, then subsequent executions
|
||||
* may start late, but will not concurrently execute.
|
||||
*
|
||||
* @param command the task to execute
|
||||
* @param initialDelay the time to delay first execution
|
||||
* @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 {@code get()} method will throw an
|
||||
* exception upon cancellation
|
||||
* @throws RejectedExecutionException if the task cannot be
|
||||
* scheduled for execution
|
||||
* @throws NullPointerException if command is null
|
||||
* @throws IllegalArgumentException if period less than or equal to zero
|
||||
*/
|
||||
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
|
||||
long initialDelay,
|
||||
long period,
|
||||
TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Creates and executes 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. If any execution of the task
|
||||
* encounters an exception, subsequent executions are suppressed.
|
||||
* Otherwise, the task will only terminate via cancellation or
|
||||
* termination of the executor.
|
||||
*
|
||||
* @param command the task to execute
|
||||
* @param initialDelay the time to delay first execution
|
||||
* @param delay the delay between the termination of one
|
||||
* 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 {@code get()} method will throw an
|
||||
* exception upon cancellation
|
||||
* @throws RejectedExecutionException if the task cannot be
|
||||
* scheduled for execution
|
||||
* @throws NullPointerException if command is null
|
||||
* @throws IllegalArgumentException if delay less than or equal to zero
|
||||
*/
|
||||
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
|
||||
long initialDelay,
|
||||
long delay,
|
||||
TimeUnit unit);
|
||||
|
||||
}
|
||||
48
jdkSrc/jdk8/java/util/concurrent/ScheduledFuture.java
Normal file
48
jdkSrc/jdk8/java/util/concurrent/ScheduledFuture.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A delayed result-bearing action that can be cancelled.
|
||||
* Usually a scheduled future is the result of scheduling
|
||||
* a task with a {@link ScheduledExecutorService}.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <V> The result type returned by this Future
|
||||
*/
|
||||
public interface ScheduledFuture<V> extends Delayed, Future<V> {
|
||||
}
|
||||
1283
jdkSrc/jdk8/java/util/concurrent/ScheduledThreadPoolExecutor.java
Normal file
1283
jdkSrc/jdk8/java/util/concurrent/ScheduledThreadPoolExecutor.java
Normal file
File diff suppressed because it is too large
Load Diff
707
jdkSrc/jdk8/java/util/concurrent/Semaphore.java
Normal file
707
jdkSrc/jdk8/java/util/concurrent/Semaphore.java
Normal file
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
|
||||
|
||||
/**
|
||||
* A counting semaphore. Conceptually, a semaphore maintains a set of
|
||||
* permits. Each {@link #acquire} blocks if necessary until a permit is
|
||||
* available, and then takes it. Each {@link #release} adds a permit,
|
||||
* potentially releasing a blocking acquirer.
|
||||
* However, no actual permit objects are used; the {@code Semaphore} just
|
||||
* keeps a count of the number available and acts accordingly.
|
||||
*
|
||||
* <p>Semaphores are often used to restrict the number of threads than can
|
||||
* access some (physical or logical) resource. For example, here is
|
||||
* a class that uses a semaphore to control access to a pool of items:
|
||||
* <pre> {@code
|
||||
* class Pool {
|
||||
* private static final int MAX_AVAILABLE = 100;
|
||||
* private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
|
||||
*
|
||||
* public Object getItem() throws InterruptedException {
|
||||
* available.acquire();
|
||||
* return getNextAvailableItem();
|
||||
* }
|
||||
*
|
||||
* public void putItem(Object x) {
|
||||
* if (markAsUnused(x))
|
||||
* available.release();
|
||||
* }
|
||||
*
|
||||
* // Not a particularly efficient data structure; just for demo
|
||||
*
|
||||
* protected Object[] items = ... whatever kinds of items being managed
|
||||
* protected boolean[] used = new boolean[MAX_AVAILABLE];
|
||||
*
|
||||
* protected synchronized Object getNextAvailableItem() {
|
||||
* for (int i = 0; i < MAX_AVAILABLE; ++i) {
|
||||
* if (!used[i]) {
|
||||
* used[i] = true;
|
||||
* return items[i];
|
||||
* }
|
||||
* }
|
||||
* return null; // not reached
|
||||
* }
|
||||
*
|
||||
* protected synchronized boolean markAsUnused(Object item) {
|
||||
* for (int i = 0; i < MAX_AVAILABLE; ++i) {
|
||||
* if (item == items[i]) {
|
||||
* if (used[i]) {
|
||||
* used[i] = false;
|
||||
* return true;
|
||||
* } else
|
||||
* return false;
|
||||
* }
|
||||
* }
|
||||
* return false;
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>Before obtaining an item each thread must acquire a permit from
|
||||
* the semaphore, guaranteeing that an item is available for use. When
|
||||
* the thread has finished with the item it is returned back to the
|
||||
* pool and a permit is returned to the semaphore, allowing another
|
||||
* thread to acquire that item. Note that no synchronization lock is
|
||||
* held when {@link #acquire} is called as that would prevent an item
|
||||
* from being returned to the pool. The semaphore encapsulates the
|
||||
* synchronization needed to restrict access to the pool, separately
|
||||
* from any synchronization needed to maintain the consistency of the
|
||||
* pool itself.
|
||||
*
|
||||
* <p>A semaphore initialized to one, and which is used such that it
|
||||
* only has at most one permit available, can serve as a mutual
|
||||
* exclusion lock. This is more commonly known as a <em>binary
|
||||
* semaphore</em>, because it only has two states: one permit
|
||||
* available, or zero permits available. When used in this way, the
|
||||
* binary semaphore has the property (unlike many {@link java.util.concurrent.locks.Lock}
|
||||
* implementations), that the "lock" can be released by a
|
||||
* thread other than the owner (as semaphores have no notion of
|
||||
* ownership). This can be useful in some specialized contexts, such
|
||||
* as deadlock recovery.
|
||||
*
|
||||
* <p> The constructor for this class optionally accepts a
|
||||
* <em>fairness</em> parameter. When set false, this class makes no
|
||||
* guarantees about the order in which threads acquire permits. In
|
||||
* particular, <em>barging</em> is permitted, that is, a thread
|
||||
* invoking {@link #acquire} can be allocated a permit ahead of a
|
||||
* thread that has been waiting - logically the new thread places itself at
|
||||
* the head of the queue of waiting threads. When fairness is set true, the
|
||||
* semaphore guarantees that threads invoking any of the {@link
|
||||
* #acquire() acquire} methods are selected to obtain permits in the order in
|
||||
* which their invocation of those methods was processed
|
||||
* (first-in-first-out; FIFO). Note that FIFO ordering necessarily
|
||||
* applies to specific internal points of execution within these
|
||||
* methods. So, it is possible for one thread to invoke
|
||||
* {@code acquire} before another, but reach the ordering point after
|
||||
* the other, and similarly upon return from the method.
|
||||
* Also note that the untimed {@link #tryAcquire() tryAcquire} methods do not
|
||||
* honor the fairness setting, but will take any permits that are
|
||||
* available.
|
||||
*
|
||||
* <p>Generally, semaphores used to control resource access should be
|
||||
* initialized as fair, to ensure that no thread is starved out from
|
||||
* accessing a resource. When using semaphores for other kinds of
|
||||
* synchronization control, the throughput advantages of non-fair
|
||||
* ordering often outweigh fairness considerations.
|
||||
*
|
||||
* <p>This class also provides convenience methods to {@link
|
||||
* #acquire(int) acquire} and {@link #release(int) release} multiple
|
||||
* permits at a time. Beware of the increased risk of indefinite
|
||||
* postponement when these methods are used without fairness set true.
|
||||
*
|
||||
* <p>Memory consistency effects: Actions in a thread prior to calling
|
||||
* a "release" method such as {@code release()}
|
||||
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* actions following a successful "acquire" method such as {@code acquire()}
|
||||
* in another thread.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class Semaphore implements java.io.Serializable {
|
||||
private static final long serialVersionUID = -3222578661600680210L;
|
||||
/** All mechanics via AbstractQueuedSynchronizer subclass */
|
||||
private final Sync sync;
|
||||
|
||||
/**
|
||||
* Synchronization implementation for semaphore. Uses AQS state
|
||||
* to represent permits. Subclassed into fair and nonfair
|
||||
* versions.
|
||||
*/
|
||||
abstract static class Sync extends AbstractQueuedSynchronizer {
|
||||
private static final long serialVersionUID = 1192457210091910933L;
|
||||
|
||||
Sync(int permits) {
|
||||
setState(permits);
|
||||
}
|
||||
|
||||
final int getPermits() {
|
||||
return getState();
|
||||
}
|
||||
|
||||
final int nonfairTryAcquireShared(int acquires) {
|
||||
for (;;) {
|
||||
int available = getState();
|
||||
int remaining = available - acquires;
|
||||
if (remaining < 0 ||
|
||||
compareAndSetState(available, remaining))
|
||||
return remaining;
|
||||
}
|
||||
}
|
||||
|
||||
protected final boolean tryReleaseShared(int releases) {
|
||||
for (;;) {
|
||||
int current = getState();
|
||||
int next = current + releases;
|
||||
if (next < current) // overflow
|
||||
throw new Error("Maximum permit count exceeded");
|
||||
if (compareAndSetState(current, next))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
final void reducePermits(int reductions) {
|
||||
for (;;) {
|
||||
int current = getState();
|
||||
int next = current - reductions;
|
||||
if (next > current) // underflow
|
||||
throw new Error("Permit count underflow");
|
||||
if (compareAndSetState(current, next))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final int drainPermits() {
|
||||
for (;;) {
|
||||
int current = getState();
|
||||
if (current == 0 || compareAndSetState(current, 0))
|
||||
return current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NonFair version
|
||||
*/
|
||||
static final class NonfairSync extends Sync {
|
||||
private static final long serialVersionUID = -2694183684443567898L;
|
||||
|
||||
NonfairSync(int permits) {
|
||||
super(permits);
|
||||
}
|
||||
|
||||
protected int tryAcquireShared(int acquires) {
|
||||
return nonfairTryAcquireShared(acquires);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fair version
|
||||
*/
|
||||
static final class FairSync extends Sync {
|
||||
private static final long serialVersionUID = 2014338818796000944L;
|
||||
|
||||
FairSync(int permits) {
|
||||
super(permits);
|
||||
}
|
||||
|
||||
protected int tryAcquireShared(int acquires) {
|
||||
for (;;) {
|
||||
if (hasQueuedPredecessors())
|
||||
return -1;
|
||||
int available = getState();
|
||||
int remaining = available - acquires;
|
||||
if (remaining < 0 ||
|
||||
compareAndSetState(available, remaining))
|
||||
return remaining;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code Semaphore} with the given number of
|
||||
* permits and nonfair fairness setting.
|
||||
*
|
||||
* @param permits the initial number of permits available.
|
||||
* This value may be negative, in which case releases
|
||||
* must occur before any acquires will be granted.
|
||||
*/
|
||||
public Semaphore(int permits) {
|
||||
sync = new NonfairSync(permits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code Semaphore} with the given number of
|
||||
* permits and the given fairness setting.
|
||||
*
|
||||
* @param permits the initial number of permits available.
|
||||
* This value may be negative, in which case releases
|
||||
* must occur before any acquires will be granted.
|
||||
* @param fair {@code true} if this semaphore will guarantee
|
||||
* first-in first-out granting of permits under contention,
|
||||
* else {@code false}
|
||||
*/
|
||||
public Semaphore(int permits, boolean fair) {
|
||||
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires a permit from this semaphore, blocking until one is
|
||||
* available, or the thread is {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>Acquires a permit, if one is available and returns immediately,
|
||||
* reducing the number of available permits by one.
|
||||
*
|
||||
* <p>If no permit is available then the current thread becomes
|
||||
* disabled for thread scheduling purposes and lies dormant until
|
||||
* one of two things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes the {@link #release} method for this
|
||||
* semaphore and the current thread is next to be assigned a permit; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread.
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* for a permit,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
*/
|
||||
public void acquire() throws InterruptedException {
|
||||
sync.acquireSharedInterruptibly(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires a permit from this semaphore, blocking until one is
|
||||
* available.
|
||||
*
|
||||
* <p>Acquires a permit, if one is available and returns immediately,
|
||||
* reducing the number of available permits by one.
|
||||
*
|
||||
* <p>If no permit is available then the current thread becomes
|
||||
* disabled for thread scheduling purposes and lies dormant until
|
||||
* some other thread invokes the {@link #release} method for this
|
||||
* semaphore and the current thread is next to be assigned a permit.
|
||||
*
|
||||
* <p>If the current thread is {@linkplain Thread#interrupt interrupted}
|
||||
* while waiting for a permit then it will continue to wait, but the
|
||||
* time at which the thread is assigned a permit may change compared to
|
||||
* the time it would have received the permit had no interruption
|
||||
* occurred. When the thread does return from this method its interrupt
|
||||
* status will be set.
|
||||
*/
|
||||
public void acquireUninterruptibly() {
|
||||
sync.acquireShared(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires a permit from this semaphore, only if one is available at the
|
||||
* time of invocation.
|
||||
*
|
||||
* <p>Acquires a permit, if one is available and returns immediately,
|
||||
* with the value {@code true},
|
||||
* reducing the number of available permits by one.
|
||||
*
|
||||
* <p>If no permit is available then this method will return
|
||||
* immediately with the value {@code false}.
|
||||
*
|
||||
* <p>Even when this semaphore has been set to use a
|
||||
* fair ordering policy, a call to {@code tryAcquire()} <em>will</em>
|
||||
* immediately acquire a permit if one is available, whether or not
|
||||
* other threads are currently waiting.
|
||||
* 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) }
|
||||
* which is almost equivalent (it also detects interruption).
|
||||
*
|
||||
* @return {@code true} if a permit was acquired and {@code false}
|
||||
* otherwise
|
||||
*/
|
||||
public boolean tryAcquire() {
|
||||
return sync.nonfairTryAcquireShared(1) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires a permit from this semaphore, if one becomes available
|
||||
* within the given waiting time and the current thread has not
|
||||
* been {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>Acquires a permit, if one is available and returns immediately,
|
||||
* with the value {@code true},
|
||||
* reducing the number of available permits by one.
|
||||
*
|
||||
* <p>If no permit is available then the current thread becomes
|
||||
* disabled for thread scheduling purposes and lies dormant until
|
||||
* one of three things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes the {@link #release} method for this
|
||||
* semaphore and the current thread is next to be assigned a permit; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
* <li>The specified waiting time elapses.
|
||||
* </ul>
|
||||
*
|
||||
* <p>If a permit is acquired then the value {@code true} is returned.
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* to acquire a permit,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* <p>If the specified waiting time elapses then the value {@code false}
|
||||
* is returned. If the time is less than or equal to zero, the method
|
||||
* will not wait at all.
|
||||
*
|
||||
* @param timeout the maximum time to wait for a permit
|
||||
* @param unit the time unit of the {@code timeout} argument
|
||||
* @return {@code true} if a permit was acquired and {@code false}
|
||||
* if the waiting time elapsed before a permit was acquired
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
*/
|
||||
public boolean tryAcquire(long timeout, TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a permit, returning it to the semaphore.
|
||||
*
|
||||
* <p>Releases a permit, increasing the number of available permits by
|
||||
* one. If any threads are trying to acquire a permit, then one is
|
||||
* selected and given the permit that was just released. That thread
|
||||
* is (re)enabled for thread scheduling purposes.
|
||||
*
|
||||
* <p>There is no requirement that a thread that releases a permit must
|
||||
* have acquired that permit by calling {@link #acquire}.
|
||||
* Correct usage of a semaphore is established by programming convention
|
||||
* in the application.
|
||||
*/
|
||||
public void release() {
|
||||
sync.releaseShared(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the given number of permits from this semaphore,
|
||||
* blocking until all are available,
|
||||
* or the thread is {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>Acquires the given number of permits, if they are available,
|
||||
* and returns immediately, reducing the number of available permits
|
||||
* by the given amount.
|
||||
*
|
||||
* <p>If insufficient permits are available then the current thread becomes
|
||||
* disabled for thread scheduling purposes and lies dormant until
|
||||
* one of two things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes one of the {@link #release() release}
|
||||
* methods for this semaphore, the current thread is next to be assigned
|
||||
* permits and the number of available permits satisfies this request; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread.
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* for a permit,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
* Any permits that were to be assigned to this thread are instead
|
||||
* assigned to other threads trying to acquire permits, as if
|
||||
* permits had been made available by a call to {@link #release()}.
|
||||
*
|
||||
* @param permits the number of permits to acquire
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* @throws IllegalArgumentException if {@code permits} is negative
|
||||
*/
|
||||
public void acquire(int permits) throws InterruptedException {
|
||||
if (permits < 0) throw new IllegalArgumentException();
|
||||
sync.acquireSharedInterruptibly(permits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the given number of permits from this semaphore,
|
||||
* blocking until all are available.
|
||||
*
|
||||
* <p>Acquires the given number of permits, if they are available,
|
||||
* and returns immediately, reducing the number of available permits
|
||||
* by the given amount.
|
||||
*
|
||||
* <p>If insufficient permits are available then the current thread becomes
|
||||
* disabled for thread scheduling purposes and lies dormant until
|
||||
* some other thread invokes one of the {@link #release() release}
|
||||
* methods for this semaphore, the current thread is next to be assigned
|
||||
* permits and the number of available permits satisfies this request.
|
||||
*
|
||||
* <p>If the current thread is {@linkplain Thread#interrupt interrupted}
|
||||
* while waiting for permits then it will continue to wait and its
|
||||
* position in the queue is not affected. When the thread does return
|
||||
* from this method its interrupt status will be set.
|
||||
*
|
||||
* @param permits the number of permits to acquire
|
||||
* @throws IllegalArgumentException if {@code permits} is negative
|
||||
*/
|
||||
public void acquireUninterruptibly(int permits) {
|
||||
if (permits < 0) throw new IllegalArgumentException();
|
||||
sync.acquireShared(permits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the given number of permits from this semaphore, only
|
||||
* if all are available at the time of invocation.
|
||||
*
|
||||
* <p>Acquires the given number of permits, if they are available, and
|
||||
* returns immediately, with the value {@code true},
|
||||
* reducing the number of available permits by the given amount.
|
||||
*
|
||||
* <p>If insufficient permits are available then this method will return
|
||||
* immediately with the value {@code false} and the number of available
|
||||
* permits is unchanged.
|
||||
*
|
||||
* <p>Even when this semaphore has been set to use a fair ordering
|
||||
* policy, a call to {@code tryAcquire} <em>will</em>
|
||||
* immediately acquire a permit if one is available, whether or
|
||||
* not other threads are currently waiting. 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(int,
|
||||
* long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SECONDS) }
|
||||
* which is almost equivalent (it also detects interruption).
|
||||
*
|
||||
* @param permits the number of permits to acquire
|
||||
* @return {@code true} if the permits were acquired and
|
||||
* {@code false} otherwise
|
||||
* @throws IllegalArgumentException if {@code permits} is negative
|
||||
*/
|
||||
public boolean tryAcquire(int permits) {
|
||||
if (permits < 0) throw new IllegalArgumentException();
|
||||
return sync.nonfairTryAcquireShared(permits) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the given number of permits from this semaphore, if all
|
||||
* become available within the given waiting time and the current
|
||||
* thread has not been {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>Acquires the given number of permits, if they are available and
|
||||
* returns immediately, with the value {@code true},
|
||||
* reducing the number of available permits by the given amount.
|
||||
*
|
||||
* <p>If insufficient permits are available then
|
||||
* the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until one of three things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes one of the {@link #release() release}
|
||||
* methods for this semaphore, the current thread is next to be assigned
|
||||
* permits and the number of available permits satisfies this request; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
* <li>The specified waiting time elapses.
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the permits are acquired then the value {@code true} is returned.
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* to acquire the permits,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
* Any permits that were to be assigned to this thread, are instead
|
||||
* assigned to other threads trying to acquire permits, as if
|
||||
* the permits had been made available by a call to {@link #release()}.
|
||||
*
|
||||
* <p>If the specified waiting time elapses then the value {@code false}
|
||||
* is returned. If the time is less than or equal to zero, the method
|
||||
* will not wait at all. Any permits that were to be assigned to this
|
||||
* thread, are instead assigned to other threads trying to acquire
|
||||
* permits, as if the permits had been made available by a call to
|
||||
* {@link #release()}.
|
||||
*
|
||||
* @param permits the number of permits to acquire
|
||||
* @param timeout the maximum time to wait for the permits
|
||||
* @param unit the time unit of the {@code timeout} argument
|
||||
* @return {@code true} if all permits were acquired and {@code false}
|
||||
* if the waiting time elapsed before all permits were acquired
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* @throws IllegalArgumentException if {@code permits} is negative
|
||||
*/
|
||||
public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
if (permits < 0) throw new IllegalArgumentException();
|
||||
return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the given number of permits, returning them to the semaphore.
|
||||
*
|
||||
* <p>Releases the given number of permits, increasing the number of
|
||||
* available permits by that amount.
|
||||
* If any threads are trying to acquire permits, then one
|
||||
* is selected and given the permits that were just released.
|
||||
* If the number of available permits satisfies that thread's request
|
||||
* then that thread is (re)enabled for thread scheduling purposes;
|
||||
* otherwise the thread will wait until sufficient permits are available.
|
||||
* If there are still permits available
|
||||
* after this thread's request has been satisfied, then those permits
|
||||
* are assigned in turn to other threads trying to acquire permits.
|
||||
*
|
||||
* <p>There is no requirement that a thread that releases a permit must
|
||||
* have acquired that permit by calling {@link Semaphore#acquire acquire}.
|
||||
* Correct usage of a semaphore is established by programming convention
|
||||
* in the application.
|
||||
*
|
||||
* @param permits the number of permits to release
|
||||
* @throws IllegalArgumentException if {@code permits} is negative
|
||||
*/
|
||||
public void release(int permits) {
|
||||
if (permits < 0) throw new IllegalArgumentException();
|
||||
sync.releaseShared(permits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current number of permits available in this semaphore.
|
||||
*
|
||||
* <p>This method is typically used for debugging and testing purposes.
|
||||
*
|
||||
* @return the number of permits available in this semaphore
|
||||
*/
|
||||
public int availablePermits() {
|
||||
return sync.getPermits();
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires and returns all permits that are immediately available.
|
||||
*
|
||||
* @return the number of permits acquired
|
||||
*/
|
||||
public int drainPermits() {
|
||||
return sync.drainPermits();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shrinks the number of available permits by the indicated
|
||||
* reduction. This method can be useful in subclasses that use
|
||||
* semaphores to track resources that become unavailable. This
|
||||
* method differs from {@code acquire} in that it does not block
|
||||
* waiting for permits to become available.
|
||||
*
|
||||
* @param reduction the number of permits to remove
|
||||
* @throws IllegalArgumentException if {@code reduction} is negative
|
||||
*/
|
||||
protected void reducePermits(int reduction) {
|
||||
if (reduction < 0) throw new IllegalArgumentException();
|
||||
sync.reducePermits(reduction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this semaphore has fairness set true.
|
||||
*
|
||||
* @return {@code true} if this semaphore has fairness set true
|
||||
*/
|
||||
public boolean isFair() {
|
||||
return sync instanceof FairSync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries whether any threads are waiting to acquire. Note that
|
||||
* because cancellations may occur at any time, a {@code true}
|
||||
* return does not guarantee that any other thread will ever
|
||||
* acquire. This method is designed primarily for use in
|
||||
* monitoring of the system state.
|
||||
*
|
||||
* @return {@code true} if there may be other threads waiting to
|
||||
* acquire the lock
|
||||
*/
|
||||
public final boolean hasQueuedThreads() {
|
||||
return sync.hasQueuedThreads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of threads waiting to acquire.
|
||||
* The value is only an estimate because the number of threads may
|
||||
* change dynamically while this method traverses internal data
|
||||
* structures. This method is designed for use in monitoring of the
|
||||
* system state, not for synchronization control.
|
||||
*
|
||||
* @return the estimated number of threads waiting for this lock
|
||||
*/
|
||||
public final int getQueueLength() {
|
||||
return sync.getQueueLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection containing threads that may be waiting to acquire.
|
||||
* Because the actual set of threads may change dynamically while
|
||||
* constructing this result, the returned collection is only a best-effort
|
||||
* estimate. The elements of the returned collection are in no particular
|
||||
* order. This method is designed to facilitate construction of
|
||||
* subclasses that provide more extensive monitoring facilities.
|
||||
*
|
||||
* @return the collection of threads
|
||||
*/
|
||||
protected Collection<Thread> getQueuedThreads() {
|
||||
return sync.getQueuedThreads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string identifying this semaphore, as well as its state.
|
||||
* The state, in brackets, includes the String {@code "Permits ="}
|
||||
* followed by the number of permits.
|
||||
*
|
||||
* @return a string identifying this semaphore, as well as its state
|
||||
*/
|
||||
public String toString() {
|
||||
return super.toString() + "[Permits = " + sync.getPermits() + "]";
|
||||
}
|
||||
}
|
||||
1212
jdkSrc/jdk8/java/util/concurrent/SynchronousQueue.java
Normal file
1212
jdkSrc/jdk8/java/util/concurrent/SynchronousQueue.java
Normal file
File diff suppressed because it is too large
Load Diff
69
jdkSrc/jdk8/java/util/concurrent/ThreadFactory.java
Normal file
69
jdkSrc/jdk8/java/util/concurrent/ThreadFactory.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* An object that creates new threads on demand. Using thread factories
|
||||
* removes hardwiring of calls to {@link Thread#Thread(Runnable) new Thread},
|
||||
* enabling applications to use special thread subclasses, priorities, etc.
|
||||
*
|
||||
* <p>
|
||||
* The simplest implementation of this interface is just:
|
||||
* <pre> {@code
|
||||
* class SimpleThreadFactory implements ThreadFactory {
|
||||
* public Thread newThread(Runnable r) {
|
||||
* return new Thread(r);
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* The {@link Executors#defaultThreadFactory} method provides a more
|
||||
* useful simple implementation, that sets the created thread context
|
||||
* to known values before returning it.
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface ThreadFactory {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Thread}. Implementations may also initialize
|
||||
* priority, name, daemon status, {@code ThreadGroup}, etc.
|
||||
*
|
||||
* @param r a runnable to be executed by new thread instance
|
||||
* @return constructed thread, or {@code null} if the request to
|
||||
* create a thread is rejected
|
||||
*/
|
||||
Thread newThread(Runnable r);
|
||||
}
|
||||
1071
jdkSrc/jdk8/java/util/concurrent/ThreadLocalRandom.java
Normal file
1071
jdkSrc/jdk8/java/util/concurrent/ThreadLocalRandom.java
Normal file
File diff suppressed because it is too large
Load Diff
2114
jdkSrc/jdk8/java/util/concurrent/ThreadPoolExecutor.java
Normal file
2114
jdkSrc/jdk8/java/util/concurrent/ThreadPoolExecutor.java
Normal file
File diff suppressed because it is too large
Load Diff
390
jdkSrc/jdk8/java/util/concurrent/TimeUnit.java
Normal file
390
jdkSrc/jdk8/java/util/concurrent/TimeUnit.java
Normal file
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A {@code TimeUnit} represents time durations at a given unit of
|
||||
* granularity and provides utility methods to convert across units,
|
||||
* and to perform timing and delay operations in these units. A
|
||||
* {@code TimeUnit} does not maintain time information, but only
|
||||
* helps organize and use time representations that may be maintained
|
||||
* separately across various contexts. A nanosecond is defined as one
|
||||
* thousandth of a microsecond, a microsecond as one thousandth of a
|
||||
* millisecond, a millisecond as one thousandth of a second, a minute
|
||||
* as sixty seconds, an hour as sixty minutes, and a day as twenty four
|
||||
* hours.
|
||||
*
|
||||
* <p>A {@code TimeUnit} is mainly used to inform time-based methods
|
||||
* how a given timing parameter should be interpreted. For example,
|
||||
* the following code will timeout in 50 milliseconds if the {@link
|
||||
* java.util.concurrent.locks.Lock lock} is not available:
|
||||
*
|
||||
* <pre> {@code
|
||||
* Lock lock = ...;
|
||||
* if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre>
|
||||
*
|
||||
* while this code will timeout in 50 seconds:
|
||||
* <pre> {@code
|
||||
* Lock lock = ...;
|
||||
* if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre>
|
||||
*
|
||||
* Note however, that there is no guarantee that a particular timeout
|
||||
* implementation will be able to notice the passage of time at the
|
||||
* same granularity as the given {@code TimeUnit}.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public enum TimeUnit {
|
||||
/**
|
||||
* Time unit representing one thousandth of a microsecond
|
||||
*/
|
||||
NANOSECONDS {
|
||||
public long toNanos(long d) { return d; }
|
||||
public long toMicros(long d) { return d/(C1/C0); }
|
||||
public long toMillis(long d) { return d/(C2/C0); }
|
||||
public long toSeconds(long d) { return d/(C3/C0); }
|
||||
public long toMinutes(long d) { return d/(C4/C0); }
|
||||
public long toHours(long d) { return d/(C5/C0); }
|
||||
public long toDays(long d) { return d/(C6/C0); }
|
||||
public long convert(long d, TimeUnit u) { return u.toNanos(d); }
|
||||
int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
|
||||
},
|
||||
|
||||
/**
|
||||
* Time unit representing one thousandth of a millisecond
|
||||
*/
|
||||
MICROSECONDS {
|
||||
public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); }
|
||||
public long toMicros(long d) { return d; }
|
||||
public long toMillis(long d) { return d/(C2/C1); }
|
||||
public long toSeconds(long d) { return d/(C3/C1); }
|
||||
public long toMinutes(long d) { return d/(C4/C1); }
|
||||
public long toHours(long d) { return d/(C5/C1); }
|
||||
public long toDays(long d) { return d/(C6/C1); }
|
||||
public long convert(long d, TimeUnit u) { return u.toMicros(d); }
|
||||
int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
|
||||
},
|
||||
|
||||
/**
|
||||
* Time unit representing one thousandth of a second
|
||||
*/
|
||||
MILLISECONDS {
|
||||
public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); }
|
||||
public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); }
|
||||
public long toMillis(long d) { return d; }
|
||||
public long toSeconds(long d) { return d/(C3/C2); }
|
||||
public long toMinutes(long d) { return d/(C4/C2); }
|
||||
public long toHours(long d) { return d/(C5/C2); }
|
||||
public long toDays(long d) { return d/(C6/C2); }
|
||||
public long convert(long d, TimeUnit u) { return u.toMillis(d); }
|
||||
int excessNanos(long d, long m) { return 0; }
|
||||
},
|
||||
|
||||
/**
|
||||
* Time unit representing one second
|
||||
*/
|
||||
SECONDS {
|
||||
public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); }
|
||||
public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); }
|
||||
public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); }
|
||||
public long toSeconds(long d) { return d; }
|
||||
public long toMinutes(long d) { return d/(C4/C3); }
|
||||
public long toHours(long d) { return d/(C5/C3); }
|
||||
public long toDays(long d) { return d/(C6/C3); }
|
||||
public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
|
||||
int excessNanos(long d, long m) { return 0; }
|
||||
},
|
||||
|
||||
/**
|
||||
* Time unit representing sixty seconds
|
||||
*/
|
||||
MINUTES {
|
||||
public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); }
|
||||
public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); }
|
||||
public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); }
|
||||
public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
|
||||
public long toMinutes(long d) { return d; }
|
||||
public long toHours(long d) { return d/(C5/C4); }
|
||||
public long toDays(long d) { return d/(C6/C4); }
|
||||
public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
|
||||
int excessNanos(long d, long m) { return 0; }
|
||||
},
|
||||
|
||||
/**
|
||||
* Time unit representing sixty minutes
|
||||
*/
|
||||
HOURS {
|
||||
public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); }
|
||||
public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); }
|
||||
public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); }
|
||||
public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
|
||||
public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
|
||||
public long toHours(long d) { return d; }
|
||||
public long toDays(long d) { return d/(C6/C5); }
|
||||
public long convert(long d, TimeUnit u) { return u.toHours(d); }
|
||||
int excessNanos(long d, long m) { return 0; }
|
||||
},
|
||||
|
||||
/**
|
||||
* Time unit representing twenty four hours
|
||||
*/
|
||||
DAYS {
|
||||
public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); }
|
||||
public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); }
|
||||
public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); }
|
||||
public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
|
||||
public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
|
||||
public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); }
|
||||
public long toDays(long d) { return d; }
|
||||
public long convert(long d, TimeUnit u) { return u.toDays(d); }
|
||||
int excessNanos(long d, long m) { return 0; }
|
||||
};
|
||||
|
||||
// Handy constants for conversion methods
|
||||
static final long C0 = 1L;
|
||||
static final long C1 = C0 * 1000L;
|
||||
static final long C2 = C1 * 1000L;
|
||||
static final long C3 = C2 * 1000L;
|
||||
static final long C4 = C3 * 60L;
|
||||
static final long C5 = C4 * 60L;
|
||||
static final long C6 = C5 * 24L;
|
||||
|
||||
static final long MAX = Long.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Scale d by m, checking for overflow.
|
||||
* This has a short name to make above code more readable.
|
||||
*/
|
||||
static long x(long d, long m, long over) {
|
||||
if (d > over) return Long.MAX_VALUE;
|
||||
if (d < -over) return Long.MIN_VALUE;
|
||||
return d * m;
|
||||
}
|
||||
|
||||
// To maintain full signature compatibility with 1.5, and to improve the
|
||||
// clarity of the generated javadoc (see 6287639: Abstract methods in
|
||||
// enum classes should not be listed as abstract), method convert
|
||||
// etc. are not declared abstract but otherwise act as abstract methods.
|
||||
|
||||
/**
|
||||
* Converts the given time duration in the given unit to this unit.
|
||||
* Conversions from finer to coarser granularities truncate, so
|
||||
* lose precision. For example, converting {@code 999} milliseconds
|
||||
* to seconds results in {@code 0}. Conversions from coarser to
|
||||
* finer granularities with arguments that would numerically
|
||||
* overflow saturate to {@code Long.MIN_VALUE} if negative or
|
||||
* {@code Long.MAX_VALUE} if positive.
|
||||
*
|
||||
* <p>For example, to convert 10 minutes to milliseconds, use:
|
||||
* {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
|
||||
*
|
||||
* @param sourceDuration the time duration in the given {@code sourceUnit}
|
||||
* @param sourceUnit the unit of the {@code sourceDuration} argument
|
||||
* @return the converted duration in this unit,
|
||||
* or {@code Long.MIN_VALUE} if conversion would negatively
|
||||
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
|
||||
*/
|
||||
public long convert(long sourceDuration, TimeUnit sourceUnit) {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to
|
||||
* {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
|
||||
* @param duration the duration
|
||||
* @return the converted duration,
|
||||
* or {@code Long.MIN_VALUE} if conversion would negatively
|
||||
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
|
||||
*/
|
||||
public long toNanos(long duration) {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to
|
||||
* {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
|
||||
* @param duration the duration
|
||||
* @return the converted duration,
|
||||
* or {@code Long.MIN_VALUE} if conversion would negatively
|
||||
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
|
||||
*/
|
||||
public long toMicros(long duration) {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to
|
||||
* {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
|
||||
* @param duration the duration
|
||||
* @return the converted duration,
|
||||
* or {@code Long.MIN_VALUE} if conversion would negatively
|
||||
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
|
||||
*/
|
||||
public long toMillis(long duration) {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to
|
||||
* {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}.
|
||||
* @param duration the duration
|
||||
* @return the converted duration,
|
||||
* or {@code Long.MIN_VALUE} if conversion would negatively
|
||||
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
|
||||
*/
|
||||
public long toSeconds(long duration) {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to
|
||||
* {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}.
|
||||
* @param duration the duration
|
||||
* @return the converted duration,
|
||||
* or {@code Long.MIN_VALUE} if conversion would negatively
|
||||
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
|
||||
* @since 1.6
|
||||
*/
|
||||
public long toMinutes(long duration) {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to
|
||||
* {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
|
||||
* @param duration the duration
|
||||
* @return the converted duration,
|
||||
* or {@code Long.MIN_VALUE} if conversion would negatively
|
||||
* overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
|
||||
* @since 1.6
|
||||
*/
|
||||
public long toHours(long duration) {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to
|
||||
* {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}.
|
||||
* @param duration the duration
|
||||
* @return the converted duration
|
||||
* @since 1.6
|
||||
*/
|
||||
public long toDays(long duration) {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to compute the excess-nanosecond argument to wait,
|
||||
* sleep, join.
|
||||
* @param d the duration
|
||||
* @param m the number of milliseconds
|
||||
* @return the number of nanoseconds
|
||||
*/
|
||||
abstract int excessNanos(long d, long m);
|
||||
|
||||
/**
|
||||
* Performs a timed {@link Object#wait(long, int) Object.wait}
|
||||
* using this time unit.
|
||||
* This is a convenience method that converts timeout arguments
|
||||
* into the form required by the {@code Object.wait} method.
|
||||
*
|
||||
* <p>For example, you could implement a blocking {@code poll}
|
||||
* method (see {@link BlockingQueue#poll BlockingQueue.poll})
|
||||
* using:
|
||||
*
|
||||
* <pre> {@code
|
||||
* public synchronized Object poll(long timeout, TimeUnit unit)
|
||||
* throws InterruptedException {
|
||||
* while (empty) {
|
||||
* unit.timedWait(this, timeout);
|
||||
* ...
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* @param obj the object to wait on
|
||||
* @param timeout the maximum time to wait. If less than
|
||||
* or equal to zero, do not wait at all.
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
public void timedWait(Object obj, long timeout)
|
||||
throws InterruptedException {
|
||||
if (timeout > 0) {
|
||||
long ms = toMillis(timeout);
|
||||
int ns = excessNanos(timeout, ms);
|
||||
obj.wait(ms, ns);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a timed {@link Thread#join(long, int) Thread.join}
|
||||
* using this time unit.
|
||||
* This is a convenience method that converts time arguments into the
|
||||
* form required by the {@code Thread.join} method.
|
||||
*
|
||||
* @param thread the thread to wait for
|
||||
* @param timeout the maximum time to wait. If less than
|
||||
* or equal to zero, do not wait at all.
|
||||
* @throws InterruptedException if interrupted while waiting
|
||||
*/
|
||||
public void timedJoin(Thread thread, long timeout)
|
||||
throws InterruptedException {
|
||||
if (timeout > 0) {
|
||||
long ms = toMillis(timeout);
|
||||
int ns = excessNanos(timeout, ms);
|
||||
thread.join(ms, ns);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a {@link Thread#sleep(long, int) Thread.sleep} using
|
||||
* this time unit.
|
||||
* This is a convenience method that converts time arguments into the
|
||||
* form required by the {@code Thread.sleep} method.
|
||||
*
|
||||
* @param timeout the minimum time to sleep. If less than
|
||||
* or equal to zero, do not sleep at all.
|
||||
* @throws InterruptedException if interrupted while sleeping
|
||||
*/
|
||||
public void sleep(long timeout) throws InterruptedException {
|
||||
if (timeout > 0) {
|
||||
long ms = toMillis(timeout);
|
||||
int ns = excessNanos(timeout, ms);
|
||||
Thread.sleep(ms, ns);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
67
jdkSrc/jdk8/java/util/concurrent/TimeoutException.java
Normal file
67
jdkSrc/jdk8/java/util/concurrent/TimeoutException.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* Exception thrown when a blocking operation times out. Blocking
|
||||
* operations for which a timeout is specified need a means to
|
||||
* indicate that the timeout has occurred. For many such operations it
|
||||
* is possible to return a value that indicates timeout; when that is
|
||||
* not possible or desirable then {@code TimeoutException} should be
|
||||
* declared and thrown.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class TimeoutException extends Exception {
|
||||
private static final long serialVersionUID = 1900926677490660714L;
|
||||
|
||||
/**
|
||||
* Constructs a {@code TimeoutException} with no specified detail
|
||||
* message.
|
||||
*/
|
||||
public TimeoutException() {}
|
||||
|
||||
/**
|
||||
* Constructs a {@code TimeoutException} with the specified detail
|
||||
* message.
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public TimeoutException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
161
jdkSrc/jdk8/java/util/concurrent/TransferQueue.java
Normal file
161
jdkSrc/jdk8/java/util/concurrent/TransferQueue.java
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
/**
|
||||
* A {@link BlockingQueue} in which producers may wait for consumers
|
||||
* to receive elements. A {@code TransferQueue} may be useful for
|
||||
* example in message passing applications in which producers
|
||||
* sometimes (using method {@link #transfer}) await receipt of
|
||||
* elements by consumers invoking {@code take} or {@code poll}, while
|
||||
* at other times enqueue elements (via method {@code put}) without
|
||||
* waiting for receipt.
|
||||
* {@linkplain #tryTransfer(Object) Non-blocking} and
|
||||
* {@linkplain #tryTransfer(Object,long,TimeUnit) time-out} versions of
|
||||
* {@code tryTransfer} are also available.
|
||||
* A {@code TransferQueue} may also be queried, via {@link
|
||||
* #hasWaitingConsumer}, whether there are any threads waiting for
|
||||
* items, which is a converse analogy to a {@code peek} operation.
|
||||
*
|
||||
* <p>Like other blocking queues, a {@code TransferQueue} may be
|
||||
* capacity bounded. If so, an attempted transfer operation may
|
||||
* initially block waiting for available space, and/or subsequently
|
||||
* block waiting for reception by a consumer. Note that in a queue
|
||||
* with zero capacity, such as {@link SynchronousQueue}, {@code put}
|
||||
* and {@code transfer} are effectively synonymous.
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @since 1.7
|
||||
* @author Doug Lea
|
||||
* @param <E> the type of elements held in this collection
|
||||
*/
|
||||
public interface TransferQueue<E> extends BlockingQueue<E> {
|
||||
/**
|
||||
* Transfers the element to a waiting consumer immediately, if possible.
|
||||
*
|
||||
* <p>More precisely, transfers the specified element immediately
|
||||
* if there exists a consumer already waiting to receive it (in
|
||||
* {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
|
||||
* otherwise returning {@code false} without enqueuing the element.
|
||||
*
|
||||
* @param e the element to transfer
|
||||
* @return {@code true} if the element was transferred, else
|
||||
* {@code false}
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this queue
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this queue
|
||||
*/
|
||||
boolean tryTransfer(E e);
|
||||
|
||||
/**
|
||||
* Transfers the element to a consumer, waiting if necessary to do so.
|
||||
*
|
||||
* <p>More precisely, transfers the specified element immediately
|
||||
* if there exists a consumer already waiting to receive it (in
|
||||
* {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
|
||||
* else waits until the element is received by a consumer.
|
||||
*
|
||||
* @param e the element to transfer
|
||||
* @throws InterruptedException if interrupted while waiting,
|
||||
* in which case the element is not left enqueued
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this queue
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this queue
|
||||
*/
|
||||
void transfer(E e) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Transfers the element to a consumer if it is possible to do so
|
||||
* before the timeout elapses.
|
||||
*
|
||||
* <p>More precisely, transfers the specified element immediately
|
||||
* if there exists a consumer already waiting to receive it (in
|
||||
* {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
|
||||
* else waits until the element is received by a consumer,
|
||||
* returning {@code false} if the specified wait time elapses
|
||||
* before the element can be transferred.
|
||||
*
|
||||
* @param e the element to transfer
|
||||
* @param timeout how long to wait before giving up, in units of
|
||||
* {@code unit}
|
||||
* @param unit a {@code TimeUnit} determining how to interpret the
|
||||
* {@code timeout} parameter
|
||||
* @return {@code true} if successful, or {@code false} if
|
||||
* the specified waiting time elapses before completion,
|
||||
* in which case the element is not left enqueued
|
||||
* @throws InterruptedException if interrupted while waiting,
|
||||
* in which case the element is not left enqueued
|
||||
* @throws ClassCastException if the class of the specified element
|
||||
* prevents it from being added to this queue
|
||||
* @throws NullPointerException if the specified element is null
|
||||
* @throws IllegalArgumentException if some property of the specified
|
||||
* element prevents it from being added to this queue
|
||||
*/
|
||||
boolean tryTransfer(E e, long timeout, TimeUnit unit)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Returns {@code true} if there is at least one consumer waiting
|
||||
* to receive an element via {@link #take} or
|
||||
* timed {@link #poll(long,TimeUnit) poll}.
|
||||
* The return value represents a momentary state of affairs.
|
||||
*
|
||||
* @return {@code true} if there is at least one waiting consumer
|
||||
*/
|
||||
boolean hasWaitingConsumer();
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of consumers waiting to
|
||||
* receive elements via {@link #take} or timed
|
||||
* {@link #poll(long,TimeUnit) poll}. The return value is an
|
||||
* approximation of a momentary state of affairs, that may be
|
||||
* inaccurate if consumers have completed or given up waiting.
|
||||
* The value may be useful for monitoring and heuristics, but
|
||||
* not for synchronization control. Implementations of this
|
||||
* method are likely to be noticeably slower than those for
|
||||
* {@link #hasWaitingConsumer}.
|
||||
*
|
||||
* @return the number of consumers waiting to receive elements
|
||||
*/
|
||||
int getWaitingConsumerCount();
|
||||
}
|
||||
164
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicBoolean.java
Normal file
164
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicBoolean.java
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* A {@code boolean} value that may be updated atomically. See the
|
||||
* {@link java.util.concurrent.atomic} package specification for
|
||||
* description of the properties of atomic variables. An
|
||||
* {@code AtomicBoolean} is used in applications such as atomically
|
||||
* updated flags, and cannot be used as a replacement for a
|
||||
* {@link java.lang.Boolean}.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class AtomicBoolean implements java.io.Serializable {
|
||||
private static final long serialVersionUID = 4654671469794556979L;
|
||||
// setup to use Unsafe.compareAndSwapInt for updates
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private static final long valueOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
valueOffset = unsafe.objectFieldOffset
|
||||
(AtomicBoolean.class.getDeclaredField("value"));
|
||||
} catch (Exception ex) { throw new Error(ex); }
|
||||
}
|
||||
|
||||
private volatile int value;
|
||||
|
||||
/**
|
||||
* Creates a new {@code AtomicBoolean} with the given initial value.
|
||||
*
|
||||
* @param initialValue the initial value
|
||||
*/
|
||||
public AtomicBoolean(boolean initialValue) {
|
||||
value = initialValue ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code AtomicBoolean} with initial value {@code false}.
|
||||
*/
|
||||
public AtomicBoolean() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value.
|
||||
*
|
||||
* @return the current value
|
||||
*/
|
||||
public final boolean get() {
|
||||
return value != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value to the given updated value
|
||||
* if the current value {@code ==} the expected value.
|
||||
*
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
*/
|
||||
public final boolean compareAndSet(boolean expect, boolean update) {
|
||||
int e = expect ? 1 : 0;
|
||||
int u = update ? 1 : 0;
|
||||
return unsafe.compareAndSwapInt(this, valueOffset, e, u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value to the given updated value
|
||||
* if the current value {@code ==} the expected value.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public boolean weakCompareAndSet(boolean expect, boolean update) {
|
||||
int e = expect ? 1 : 0;
|
||||
int u = update ? 1 : 0;
|
||||
return unsafe.compareAndSwapInt(this, valueOffset, e, u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally sets to the given value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
*/
|
||||
public final void set(boolean newValue) {
|
||||
value = newValue ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eventually sets to the given value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(boolean newValue) {
|
||||
int v = newValue ? 1 : 0;
|
||||
unsafe.putOrderedInt(this, valueOffset, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets to the given value and returns the previous value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
public final boolean getAndSet(boolean newValue) {
|
||||
boolean prev;
|
||||
do {
|
||||
prev = get();
|
||||
} while (!compareAndSet(prev, newValue));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the current value.
|
||||
* @return the String representation of the current value
|
||||
*/
|
||||
public String toString() {
|
||||
return Boolean.toString(get());
|
||||
}
|
||||
|
||||
}
|
||||
336
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicInteger.java
Normal file
336
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicInteger.java
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* An {@code int} value that may be updated atomically. See the
|
||||
* {@link java.util.concurrent.atomic} package specification for
|
||||
* description of the properties of atomic variables. An
|
||||
* {@code AtomicInteger} is used in applications such as atomically
|
||||
* incremented counters, and cannot be used as a replacement for an
|
||||
* {@link java.lang.Integer}. However, this class does extend
|
||||
* {@code Number} to allow uniform access by tools and utilities that
|
||||
* deal with numerically-based classes.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class AtomicInteger extends Number implements java.io.Serializable {
|
||||
private static final long serialVersionUID = 6214790243416807050L;
|
||||
|
||||
// setup to use Unsafe.compareAndSwapInt for updates
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private static final long valueOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
valueOffset = unsafe.objectFieldOffset
|
||||
(AtomicInteger.class.getDeclaredField("value"));
|
||||
} catch (Exception ex) { throw new Error(ex); }
|
||||
}
|
||||
|
||||
private volatile int value;
|
||||
|
||||
/**
|
||||
* Creates a new AtomicInteger with the given initial value.
|
||||
*
|
||||
* @param initialValue the initial value
|
||||
*/
|
||||
public AtomicInteger(int initialValue) {
|
||||
value = initialValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AtomicInteger with initial value {@code 0}.
|
||||
*/
|
||||
public AtomicInteger() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value.
|
||||
*
|
||||
* @return the current value
|
||||
*/
|
||||
public final int get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets to the given value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
*/
|
||||
public final void set(int newValue) {
|
||||
value = newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eventually sets to the given value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int newValue) {
|
||||
unsafe.putOrderedInt(this, valueOffset, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets to the given value and returns the old value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
public final int getAndSet(int newValue) {
|
||||
return unsafe.getAndSetInt(this, valueOffset, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value to the given updated value
|
||||
* if the current value {@code ==} the expected value.
|
||||
*
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
*/
|
||||
public final boolean compareAndSet(int expect, int update) {
|
||||
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value to the given updated value
|
||||
* if the current value {@code ==} the expected value.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public final boolean weakCompareAndSet(int expect, int update) {
|
||||
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the current value.
|
||||
*
|
||||
* @return the previous value
|
||||
*/
|
||||
public final int getAndIncrement() {
|
||||
return unsafe.getAndAddInt(this, valueOffset, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the current value.
|
||||
*
|
||||
* @return the previous value
|
||||
*/
|
||||
public final int getAndDecrement() {
|
||||
return unsafe.getAndAddInt(this, valueOffset, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the current value.
|
||||
*
|
||||
* @param delta the value to add
|
||||
* @return the previous value
|
||||
*/
|
||||
public final int getAndAdd(int delta) {
|
||||
return unsafe.getAndAddInt(this, valueOffset, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the current value.
|
||||
*
|
||||
* @return the updated value
|
||||
*/
|
||||
public final int incrementAndGet() {
|
||||
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the current value.
|
||||
*
|
||||
* @return the updated value
|
||||
*/
|
||||
public final int decrementAndGet() {
|
||||
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the current value.
|
||||
*
|
||||
* @param delta the value to add
|
||||
* @return the updated value
|
||||
*/
|
||||
public final int addAndGet(int delta) {
|
||||
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function, returning the previous value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int getAndUpdate(IntUnaryOperator updateFunction) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = updateFunction.applyAsInt(prev);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function, returning the updated value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int updateAndGet(IntUnaryOperator updateFunction) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = updateFunction.applyAsInt(prev);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function to the current and given values,
|
||||
* returning the previous value. The function should be
|
||||
* side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function
|
||||
* is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int getAndAccumulate(int x,
|
||||
IntBinaryOperator accumulatorFunction) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = accumulatorFunction.applyAsInt(prev, x);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function to the current and given values,
|
||||
* returning the updated value. The function should be
|
||||
* side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function
|
||||
* is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int accumulateAndGet(int x,
|
||||
IntBinaryOperator accumulatorFunction) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = accumulatorFunction.applyAsInt(prev, x);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the current value.
|
||||
* @return the String representation of the current value
|
||||
*/
|
||||
public String toString() {
|
||||
return Integer.toString(get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this {@code AtomicInteger} as an {@code int}.
|
||||
*/
|
||||
public int intValue() {
|
||||
return get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this {@code AtomicInteger} as a {@code long}
|
||||
* after a widening primitive conversion.
|
||||
* @jls 5.1.2 Widening Primitive Conversions
|
||||
*/
|
||||
public long longValue() {
|
||||
return (long)get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this {@code AtomicInteger} as a {@code float}
|
||||
* after a widening primitive conversion.
|
||||
* @jls 5.1.2 Widening Primitive Conversions
|
||||
*/
|
||||
public float floatValue() {
|
||||
return (float)get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this {@code AtomicInteger} as a {@code double}
|
||||
* after a widening primitive conversion.
|
||||
* @jls 5.1.2 Widening Primitive Conversions
|
||||
*/
|
||||
public double doubleValue() {
|
||||
return (double)get();
|
||||
}
|
||||
|
||||
}
|
||||
364
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicIntegerArray.java
Normal file
364
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicIntegerArray.java
Normal file
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* An {@code int} array in which elements may be updated atomically.
|
||||
* See the {@link java.util.concurrent.atomic} package
|
||||
* specification for description of the properties of atomic
|
||||
* variables.
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class AtomicIntegerArray implements java.io.Serializable {
|
||||
private static final long serialVersionUID = 2862133569453604235L;
|
||||
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private static final int base = unsafe.arrayBaseOffset(int[].class);
|
||||
private static final int shift;
|
||||
private final int[] array;
|
||||
|
||||
static {
|
||||
int scale = unsafe.arrayIndexScale(int[].class);
|
||||
if ((scale & (scale - 1)) != 0)
|
||||
throw new Error("data type scale not a power of two");
|
||||
shift = 31 - Integer.numberOfLeadingZeros(scale);
|
||||
}
|
||||
|
||||
private long checkedByteOffset(int i) {
|
||||
if (i < 0 || i >= array.length)
|
||||
throw new IndexOutOfBoundsException("index " + i);
|
||||
|
||||
return byteOffset(i);
|
||||
}
|
||||
|
||||
private static long byteOffset(int i) {
|
||||
return ((long) i << shift) + base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AtomicIntegerArray of the given length, with all
|
||||
* elements initially zero.
|
||||
*
|
||||
* @param length the length of the array
|
||||
*/
|
||||
public AtomicIntegerArray(int length) {
|
||||
array = new int[length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AtomicIntegerArray with the same length as, and
|
||||
* all elements copied from, the given array.
|
||||
*
|
||||
* @param array the array to copy elements from
|
||||
* @throws NullPointerException if array is null
|
||||
*/
|
||||
public AtomicIntegerArray(int[] array) {
|
||||
// Visibility guaranteed by final field guarantees
|
||||
this.array = array.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the array.
|
||||
*
|
||||
* @return the length of the array
|
||||
*/
|
||||
public final int length() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value at position {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the current value
|
||||
*/
|
||||
public final int get(int i) {
|
||||
return getRaw(checkedByteOffset(i));
|
||||
}
|
||||
|
||||
private int getRaw(long offset) {
|
||||
return unsafe.getIntVolatile(array, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the element at position {@code i} to the given value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param newValue the new value
|
||||
*/
|
||||
public final void set(int i, int newValue) {
|
||||
unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Eventually sets the element at position {@code i} to the given value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param newValue the new value
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int i, int newValue) {
|
||||
unsafe.putOrderedInt(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the element at position {@code i} to the given
|
||||
* value and returns the old value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param newValue the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
public final int getAndSet(int i, int newValue) {
|
||||
return unsafe.getAndSetInt(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the element at position {@code i} to the given
|
||||
* updated value if the current value {@code ==} the expected value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
*/
|
||||
public final boolean compareAndSet(int i, int expect, int update) {
|
||||
return compareAndSetRaw(checkedByteOffset(i), expect, update);
|
||||
}
|
||||
|
||||
private boolean compareAndSetRaw(long offset, int expect, int update) {
|
||||
return unsafe.compareAndSwapInt(array, offset, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the element at position {@code i} to the given
|
||||
* updated value if the current value {@code ==} the expected value.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param i the index
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public final boolean weakCompareAndSet(int i, int expect, int update) {
|
||||
return compareAndSet(i, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the previous value
|
||||
*/
|
||||
public final int getAndIncrement(int i) {
|
||||
return getAndAdd(i, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the previous value
|
||||
*/
|
||||
public final int getAndDecrement(int i) {
|
||||
return getAndAdd(i, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @param delta the value to add
|
||||
* @return the previous value
|
||||
*/
|
||||
public final int getAndAdd(int i, int delta) {
|
||||
return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the updated value
|
||||
*/
|
||||
public final int incrementAndGet(int i) {
|
||||
return getAndAdd(i, 1) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the updated value
|
||||
*/
|
||||
public final int decrementAndGet(int i) {
|
||||
return getAndAdd(i, -1) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @param delta the value to add
|
||||
* @return the updated value
|
||||
*/
|
||||
public final int addAndGet(int i, int delta) {
|
||||
return getAndAdd(i, delta) + delta;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the results
|
||||
* of applying the given function, returning the previous value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param i the index
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
int prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = updateFunction.applyAsInt(prev);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the results
|
||||
* of applying the given function, returning the updated value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param i the index
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
int prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = updateFunction.applyAsInt(prev);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the
|
||||
* results of applying the given function to the current and
|
||||
* given values, returning the previous value. The function should
|
||||
* be side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function is
|
||||
* applied with the current value at index {@code i} as its first
|
||||
* argument, and the given update as the second argument.
|
||||
*
|
||||
* @param i the index
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int getAndAccumulate(int i, int x,
|
||||
IntBinaryOperator accumulatorFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
int prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = accumulatorFunction.applyAsInt(prev, x);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the
|
||||
* results of applying the given function to the current and
|
||||
* given values, returning the updated value. The function should
|
||||
* be side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function is
|
||||
* applied with the current value at index {@code i} as its first
|
||||
* argument, and the given update as the second argument.
|
||||
*
|
||||
* @param i the index
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int accumulateAndGet(int i, int x,
|
||||
IntBinaryOperator accumulatorFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
int prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = accumulatorFunction.applyAsInt(prev, x);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the current values of array.
|
||||
* @return the String representation of the current values of array
|
||||
*/
|
||||
public String toString() {
|
||||
int iMax = array.length - 1;
|
||||
if (iMax == -1)
|
||||
return "[]";
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append('[');
|
||||
for (int i = 0; ; i++) {
|
||||
b.append(getRaw(byteOffset(i)));
|
||||
if (i == iMax)
|
||||
return b.append(']').toString();
|
||||
b.append(',').append(' ');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,543 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Objects;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
/**
|
||||
* A reflection-based utility that enables atomic updates to
|
||||
* designated {@code volatile int} fields of designated classes.
|
||||
* This class is designed for use in atomic data structures in which
|
||||
* several fields of the same node are independently subject to atomic
|
||||
* updates.
|
||||
*
|
||||
* <p>Note that the guarantees of the {@code compareAndSet}
|
||||
* method in this class are weaker than in other atomic classes.
|
||||
* Because this class cannot ensure that all uses of the field
|
||||
* are appropriate for purposes of atomic access, it can
|
||||
* guarantee atomicity only with respect to other invocations of
|
||||
* {@code compareAndSet} and {@code set} on the same updater.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <T> The type of the object holding the updatable field
|
||||
*/
|
||||
public abstract class AtomicIntegerFieldUpdater<T> {
|
||||
/**
|
||||
* Creates and returns an updater for objects with the given field.
|
||||
* The Class argument is needed to check that reflective types and
|
||||
* generic types match.
|
||||
*
|
||||
* @param tclass the class of the objects holding the field
|
||||
* @param fieldName the name of the field to be updated
|
||||
* @param <U> the type of instances of tclass
|
||||
* @return the updater
|
||||
* @throws IllegalArgumentException if the field is not a
|
||||
* volatile integer type
|
||||
* @throws RuntimeException with a nested reflection-based
|
||||
* exception if the class does not hold field or is the wrong type,
|
||||
* or the field is inaccessible to the caller according to Java language
|
||||
* access control
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
|
||||
String fieldName) {
|
||||
return new AtomicIntegerFieldUpdaterImpl<U>
|
||||
(tclass, fieldName, Reflection.getCallerClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected do-nothing constructor for use by subclasses.
|
||||
*/
|
||||
protected AtomicIntegerFieldUpdater() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the field of the given object managed by this updater
|
||||
* to the given updated value if the current value {@code ==} the
|
||||
* expected value. This method is guaranteed to be atomic with respect to
|
||||
* other calls to {@code compareAndSet} and {@code set}, but not
|
||||
* necessarily with respect to other changes in the field.
|
||||
*
|
||||
* @param obj An object whose field to conditionally set
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
* @throws ClassCastException if {@code obj} is not an instance
|
||||
* of the class possessing the field established in the constructor
|
||||
*/
|
||||
public abstract boolean compareAndSet(T obj, int expect, int update);
|
||||
|
||||
/**
|
||||
* Atomically sets the field of the given object managed by this updater
|
||||
* to the given updated value if the current value {@code ==} the
|
||||
* expected value. This method is guaranteed to be atomic with respect to
|
||||
* other calls to {@code compareAndSet} and {@code set}, but not
|
||||
* necessarily with respect to other changes in the field.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param obj An object whose field to conditionally set
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
* @throws ClassCastException if {@code obj} is not an instance
|
||||
* of the class possessing the field established in the constructor
|
||||
*/
|
||||
public abstract boolean weakCompareAndSet(T obj, int expect, int update);
|
||||
|
||||
/**
|
||||
* Sets the field of the given object managed by this updater to the
|
||||
* given updated value. This operation is guaranteed to act as a volatile
|
||||
* store with respect to subsequent invocations of {@code compareAndSet}.
|
||||
*
|
||||
* @param obj An object whose field to set
|
||||
* @param newValue the new value
|
||||
*/
|
||||
public abstract void set(T obj, int newValue);
|
||||
|
||||
/**
|
||||
* Eventually sets the field of the given object managed by this
|
||||
* updater to the given updated value.
|
||||
*
|
||||
* @param obj An object whose field to set
|
||||
* @param newValue the new value
|
||||
* @since 1.6
|
||||
*/
|
||||
public abstract void lazySet(T obj, int newValue);
|
||||
|
||||
/**
|
||||
* Gets the current value held in the field of the given object managed
|
||||
* by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get
|
||||
* @return the current value
|
||||
*/
|
||||
public abstract int get(T obj);
|
||||
|
||||
/**
|
||||
* Atomically sets the field of the given object managed by this updater
|
||||
* to the given value and returns the old value.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param newValue the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
public int getAndSet(T obj, int newValue) {
|
||||
int prev;
|
||||
do {
|
||||
prev = get(obj);
|
||||
} while (!compareAndSet(obj, prev, newValue));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the current value of the field of the
|
||||
* given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @return the previous value
|
||||
*/
|
||||
public int getAndIncrement(T obj) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev + 1;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the current value of the field of the
|
||||
* given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @return the previous value
|
||||
*/
|
||||
public int getAndDecrement(T obj) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev - 1;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the current value of the field of
|
||||
* the given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param delta the value to add
|
||||
* @return the previous value
|
||||
*/
|
||||
public int getAndAdd(T obj, int delta) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev + delta;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the current value of the field of the
|
||||
* given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @return the updated value
|
||||
*/
|
||||
public int incrementAndGet(T obj) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev + 1;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the current value of the field of the
|
||||
* given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @return the updated value
|
||||
*/
|
||||
public int decrementAndGet(T obj) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev - 1;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the current value of the field of
|
||||
* the given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param delta the value to add
|
||||
* @return the updated value
|
||||
*/
|
||||
public int addAndGet(T obj, int delta) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev + delta;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this updater
|
||||
* with the results of applying the given function, returning the previous
|
||||
* value. The function should be side-effect-free, since it may be
|
||||
* re-applied when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int getAndUpdate(T obj, IntUnaryOperator updateFunction) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = updateFunction.applyAsInt(prev);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this updater
|
||||
* with the results of applying the given function, returning the updated
|
||||
* value. The function should be side-effect-free, since it may be
|
||||
* re-applied when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int updateAndGet(T obj, IntUnaryOperator updateFunction) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = updateFunction.applyAsInt(prev);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this
|
||||
* updater with the results of applying the given function to the
|
||||
* current and given values, returning the previous value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads. The
|
||||
* function is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int getAndAccumulate(T obj, int x,
|
||||
IntBinaryOperator accumulatorFunction) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = accumulatorFunction.applyAsInt(prev, x);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this
|
||||
* updater with the results of applying the given function to the
|
||||
* current and given values, returning the updated value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads. The
|
||||
* function is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final int accumulateAndGet(T obj, int x,
|
||||
IntBinaryOperator accumulatorFunction) {
|
||||
int prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = accumulatorFunction.applyAsInt(prev, x);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard hotspot implementation using intrinsics.
|
||||
*/
|
||||
private static final class AtomicIntegerFieldUpdaterImpl<T>
|
||||
extends AtomicIntegerFieldUpdater<T> {
|
||||
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
|
||||
private final long offset;
|
||||
/**
|
||||
* if field is protected, the subclass constructing updater, else
|
||||
* the same as tclass
|
||||
*/
|
||||
private final Class<?> cclass;
|
||||
/** class holding the field */
|
||||
private final Class<T> tclass;
|
||||
|
||||
AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
|
||||
final String fieldName,
|
||||
final Class<?> caller) {
|
||||
final Field field;
|
||||
final int modifiers;
|
||||
try {
|
||||
field = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Field>() {
|
||||
public Field run() throws NoSuchFieldException {
|
||||
return tclass.getDeclaredField(fieldName);
|
||||
}
|
||||
});
|
||||
modifiers = field.getModifiers();
|
||||
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
|
||||
caller, tclass, null, modifiers);
|
||||
ClassLoader cl = tclass.getClassLoader();
|
||||
ClassLoader ccl = caller.getClassLoader();
|
||||
if ((ccl != null) && (ccl != cl) &&
|
||||
((cl == null) || !isAncestor(cl, ccl))) {
|
||||
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
|
||||
}
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw new RuntimeException(pae.getException());
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
if (field.getType() != int.class)
|
||||
throw new IllegalArgumentException("Must be integer type");
|
||||
|
||||
if (!Modifier.isVolatile(modifiers))
|
||||
throw new IllegalArgumentException("Must be volatile type");
|
||||
|
||||
// Access to protected field members is restricted to receivers only
|
||||
// of the accessing class, or one of its subclasses, and the
|
||||
// accessing class must in turn be a subclass (or package sibling)
|
||||
// of the protected member's defining class.
|
||||
// If the updater refers to a protected field of a declaring class
|
||||
// outside the current package, the receiver argument will be
|
||||
// narrowed to the type of the accessing class.
|
||||
this.cclass = (Modifier.isProtected(modifiers) &&
|
||||
tclass.isAssignableFrom(caller) &&
|
||||
!isSamePackage(tclass, caller))
|
||||
? caller : tclass;
|
||||
this.tclass = tclass;
|
||||
this.offset = U.objectFieldOffset(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the second classloader can be found in the first
|
||||
* classloader's delegation chain.
|
||||
* Equivalent to the inaccessible: first.isAncestor(second).
|
||||
*/
|
||||
private static boolean isAncestor(ClassLoader first, ClassLoader second) {
|
||||
ClassLoader acl = first;
|
||||
do {
|
||||
acl = acl.getParent();
|
||||
if (second == acl) {
|
||||
return true;
|
||||
}
|
||||
} while (acl != null);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the two classes have the same class loader and
|
||||
* package qualifier
|
||||
*/
|
||||
private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
|
||||
return class1.getClassLoader() == class2.getClassLoader()
|
||||
&& Objects.equals(getPackageName(class1), getPackageName(class2));
|
||||
}
|
||||
|
||||
private static String getPackageName(Class<?> cls) {
|
||||
String cn = cls.getName();
|
||||
int dot = cn.lastIndexOf('.');
|
||||
return (dot != -1) ? cn.substring(0, dot) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that target argument is instance of cclass. On
|
||||
* failure, throws cause.
|
||||
*/
|
||||
private final void accessCheck(T obj) {
|
||||
if (!cclass.isInstance(obj))
|
||||
throwAccessCheckException(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws access exception if accessCheck failed due to
|
||||
* protected access, else ClassCastException.
|
||||
*/
|
||||
private final void throwAccessCheckException(T obj) {
|
||||
if (cclass == tclass)
|
||||
throw new ClassCastException();
|
||||
else
|
||||
throw new RuntimeException(
|
||||
new IllegalAccessException(
|
||||
"Class " +
|
||||
cclass.getName() +
|
||||
" can not access a protected member of class " +
|
||||
tclass.getName() +
|
||||
" using an instance of " +
|
||||
obj.getClass().getName()));
|
||||
}
|
||||
|
||||
public final boolean compareAndSet(T obj, int expect, int update) {
|
||||
accessCheck(obj);
|
||||
return U.compareAndSwapInt(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
public final boolean weakCompareAndSet(T obj, int expect, int update) {
|
||||
accessCheck(obj);
|
||||
return U.compareAndSwapInt(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
public final void set(T obj, int newValue) {
|
||||
accessCheck(obj);
|
||||
U.putIntVolatile(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final void lazySet(T obj, int newValue) {
|
||||
accessCheck(obj);
|
||||
U.putOrderedInt(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final int get(T obj) {
|
||||
accessCheck(obj);
|
||||
return U.getIntVolatile(obj, offset);
|
||||
}
|
||||
|
||||
public final int getAndSet(T obj, int newValue) {
|
||||
accessCheck(obj);
|
||||
return U.getAndSetInt(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final int getAndAdd(T obj, int delta) {
|
||||
accessCheck(obj);
|
||||
return U.getAndAddInt(obj, offset, delta);
|
||||
}
|
||||
|
||||
public final int getAndIncrement(T obj) {
|
||||
return getAndAdd(obj, 1);
|
||||
}
|
||||
|
||||
public final int getAndDecrement(T obj) {
|
||||
return getAndAdd(obj, -1);
|
||||
}
|
||||
|
||||
public final int incrementAndGet(T obj) {
|
||||
return getAndAdd(obj, 1) + 1;
|
||||
}
|
||||
|
||||
public final int decrementAndGet(T obj) {
|
||||
return getAndAdd(obj, -1) - 1;
|
||||
}
|
||||
|
||||
public final int addAndGet(T obj, int delta) {
|
||||
return getAndAdd(obj, delta) + delta;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
350
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicLong.java
Normal file
350
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicLong.java
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.util.function.LongUnaryOperator;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* A {@code long} value that may be updated atomically. See the
|
||||
* {@link java.util.concurrent.atomic} package specification for
|
||||
* description of the properties of atomic variables. An
|
||||
* {@code AtomicLong} is used in applications such as atomically
|
||||
* incremented sequence numbers, and cannot be used as a replacement
|
||||
* for a {@link java.lang.Long}. However, this class does extend
|
||||
* {@code Number} to allow uniform access by tools and utilities that
|
||||
* deal with numerically-based classes.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class AtomicLong extends Number implements java.io.Serializable {
|
||||
private static final long serialVersionUID = 1927816293512124184L;
|
||||
|
||||
// setup to use Unsafe.compareAndSwapLong for updates
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private static final long valueOffset;
|
||||
|
||||
/**
|
||||
* Records whether the underlying JVM supports lockless
|
||||
* compareAndSwap for longs. While the Unsafe.compareAndSwapLong
|
||||
* method works in either case, some constructions should be
|
||||
* handled at Java level to avoid locking user-visible locks.
|
||||
*/
|
||||
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
|
||||
|
||||
/**
|
||||
* Returns whether underlying JVM supports lockless CompareAndSet
|
||||
* for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
|
||||
*/
|
||||
private static native boolean VMSupportsCS8();
|
||||
|
||||
static {
|
||||
try {
|
||||
valueOffset = unsafe.objectFieldOffset
|
||||
(AtomicLong.class.getDeclaredField("value"));
|
||||
} catch (Exception ex) { throw new Error(ex); }
|
||||
}
|
||||
|
||||
private volatile long value;
|
||||
|
||||
/**
|
||||
* Creates a new AtomicLong with the given initial value.
|
||||
*
|
||||
* @param initialValue the initial value
|
||||
*/
|
||||
public AtomicLong(long initialValue) {
|
||||
value = initialValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AtomicLong with initial value {@code 0}.
|
||||
*/
|
||||
public AtomicLong() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value.
|
||||
*
|
||||
* @return the current value
|
||||
*/
|
||||
public final long get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets to the given value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
*/
|
||||
public final void set(long newValue) {
|
||||
value = newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eventually sets to the given value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(long newValue) {
|
||||
unsafe.putOrderedLong(this, valueOffset, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets to the given value and returns the old value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
public final long getAndSet(long newValue) {
|
||||
return unsafe.getAndSetLong(this, valueOffset, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value to the given updated value
|
||||
* if the current value {@code ==} the expected value.
|
||||
*
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
*/
|
||||
public final boolean compareAndSet(long expect, long update) {
|
||||
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value to the given updated value
|
||||
* if the current value {@code ==} the expected value.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public final boolean weakCompareAndSet(long expect, long update) {
|
||||
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the current value.
|
||||
*
|
||||
* @return the previous value
|
||||
*/
|
||||
public final long getAndIncrement() {
|
||||
return unsafe.getAndAddLong(this, valueOffset, 1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the current value.
|
||||
*
|
||||
* @return the previous value
|
||||
*/
|
||||
public final long getAndDecrement() {
|
||||
return unsafe.getAndAddLong(this, valueOffset, -1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the current value.
|
||||
*
|
||||
* @param delta the value to add
|
||||
* @return the previous value
|
||||
*/
|
||||
public final long getAndAdd(long delta) {
|
||||
return unsafe.getAndAddLong(this, valueOffset, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the current value.
|
||||
*
|
||||
* @return the updated value
|
||||
*/
|
||||
public final long incrementAndGet() {
|
||||
return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the current value.
|
||||
*
|
||||
* @return the updated value
|
||||
*/
|
||||
public final long decrementAndGet() {
|
||||
return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the current value.
|
||||
*
|
||||
* @param delta the value to add
|
||||
* @return the updated value
|
||||
*/
|
||||
public final long addAndGet(long delta) {
|
||||
return unsafe.getAndAddLong(this, valueOffset, delta) + delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function, returning the previous value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long getAndUpdate(LongUnaryOperator updateFunction) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = updateFunction.applyAsLong(prev);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function, returning the updated value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long updateAndGet(LongUnaryOperator updateFunction) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = updateFunction.applyAsLong(prev);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function to the current and given values,
|
||||
* returning the previous value. The function should be
|
||||
* side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function
|
||||
* is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long getAndAccumulate(long x,
|
||||
LongBinaryOperator accumulatorFunction) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = accumulatorFunction.applyAsLong(prev, x);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function to the current and given values,
|
||||
* returning the updated value. The function should be
|
||||
* side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function
|
||||
* is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long accumulateAndGet(long x,
|
||||
LongBinaryOperator accumulatorFunction) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = accumulatorFunction.applyAsLong(prev, x);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the current value.
|
||||
* @return the String representation of the current value
|
||||
*/
|
||||
public String toString() {
|
||||
return Long.toString(get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this {@code AtomicLong} as an {@code int}
|
||||
* after a narrowing primitive conversion.
|
||||
* @jls 5.1.3 Narrowing Primitive Conversions
|
||||
*/
|
||||
public int intValue() {
|
||||
return (int)get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this {@code AtomicLong} as a {@code long}.
|
||||
*/
|
||||
public long longValue() {
|
||||
return get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this {@code AtomicLong} as a {@code float}
|
||||
* after a widening primitive conversion.
|
||||
* @jls 5.1.2 Widening Primitive Conversions
|
||||
*/
|
||||
public float floatValue() {
|
||||
return (float)get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this {@code AtomicLong} as a {@code double}
|
||||
* after a widening primitive conversion.
|
||||
* @jls 5.1.2 Widening Primitive Conversions
|
||||
*/
|
||||
public double doubleValue() {
|
||||
return (double)get();
|
||||
}
|
||||
|
||||
}
|
||||
362
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicLongArray.java
Normal file
362
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicLongArray.java
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.util.function.LongUnaryOperator;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* A {@code long} array in which elements may be updated atomically.
|
||||
* See the {@link java.util.concurrent.atomic} package specification
|
||||
* for description of the properties of atomic variables.
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class AtomicLongArray implements java.io.Serializable {
|
||||
private static final long serialVersionUID = -2308431214976778248L;
|
||||
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private static final int base = unsafe.arrayBaseOffset(long[].class);
|
||||
private static final int shift;
|
||||
private final long[] array;
|
||||
|
||||
static {
|
||||
int scale = unsafe.arrayIndexScale(long[].class);
|
||||
if ((scale & (scale - 1)) != 0)
|
||||
throw new Error("data type scale not a power of two");
|
||||
shift = 31 - Integer.numberOfLeadingZeros(scale);
|
||||
}
|
||||
|
||||
private long checkedByteOffset(int i) {
|
||||
if (i < 0 || i >= array.length)
|
||||
throw new IndexOutOfBoundsException("index " + i);
|
||||
|
||||
return byteOffset(i);
|
||||
}
|
||||
|
||||
private static long byteOffset(int i) {
|
||||
return ((long) i << shift) + base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AtomicLongArray of the given length, with all
|
||||
* elements initially zero.
|
||||
*
|
||||
* @param length the length of the array
|
||||
*/
|
||||
public AtomicLongArray(int length) {
|
||||
array = new long[length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AtomicLongArray with the same length as, and
|
||||
* all elements copied from, the given array.
|
||||
*
|
||||
* @param array the array to copy elements from
|
||||
* @throws NullPointerException if array is null
|
||||
*/
|
||||
public AtomicLongArray(long[] array) {
|
||||
// Visibility guaranteed by final field guarantees
|
||||
this.array = array.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the array.
|
||||
*
|
||||
* @return the length of the array
|
||||
*/
|
||||
public final int length() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value at position {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the current value
|
||||
*/
|
||||
public final long get(int i) {
|
||||
return getRaw(checkedByteOffset(i));
|
||||
}
|
||||
|
||||
private long getRaw(long offset) {
|
||||
return unsafe.getLongVolatile(array, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the element at position {@code i} to the given value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param newValue the new value
|
||||
*/
|
||||
public final void set(int i, long newValue) {
|
||||
unsafe.putLongVolatile(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Eventually sets the element at position {@code i} to the given value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param newValue the new value
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int i, long newValue) {
|
||||
unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the element at position {@code i} to the given value
|
||||
* and returns the old value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param newValue the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
public final long getAndSet(int i, long newValue) {
|
||||
return unsafe.getAndSetLong(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the element at position {@code i} to the given
|
||||
* updated value if the current value {@code ==} the expected value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
*/
|
||||
public final boolean compareAndSet(int i, long expect, long update) {
|
||||
return compareAndSetRaw(checkedByteOffset(i), expect, update);
|
||||
}
|
||||
|
||||
private boolean compareAndSetRaw(long offset, long expect, long update) {
|
||||
return unsafe.compareAndSwapLong(array, offset, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the element at position {@code i} to the given
|
||||
* updated value if the current value {@code ==} the expected value.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param i the index
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public final boolean weakCompareAndSet(int i, long expect, long update) {
|
||||
return compareAndSet(i, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the previous value
|
||||
*/
|
||||
public final long getAndIncrement(int i) {
|
||||
return getAndAdd(i, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the previous value
|
||||
*/
|
||||
public final long getAndDecrement(int i) {
|
||||
return getAndAdd(i, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @param delta the value to add
|
||||
* @return the previous value
|
||||
*/
|
||||
public final long getAndAdd(int i, long delta) {
|
||||
return unsafe.getAndAddLong(array, checkedByteOffset(i), delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the updated value
|
||||
*/
|
||||
public final long incrementAndGet(int i) {
|
||||
return getAndAdd(i, 1) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the updated value
|
||||
*/
|
||||
public final long decrementAndGet(int i) {
|
||||
return getAndAdd(i, -1) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the element at index {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @param delta the value to add
|
||||
* @return the updated value
|
||||
*/
|
||||
public long addAndGet(int i, long delta) {
|
||||
return getAndAdd(i, delta) + delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the results
|
||||
* of applying the given function, returning the previous value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param i the index
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long getAndUpdate(int i, LongUnaryOperator updateFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
long prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = updateFunction.applyAsLong(prev);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the results
|
||||
* of applying the given function, returning the updated value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param i the index
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long updateAndGet(int i, LongUnaryOperator updateFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
long prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = updateFunction.applyAsLong(prev);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the
|
||||
* results of applying the given function to the current and
|
||||
* given values, returning the previous value. The function should
|
||||
* be side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function is
|
||||
* applied with the current value at index {@code i} as its first
|
||||
* argument, and the given update as the second argument.
|
||||
*
|
||||
* @param i the index
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long getAndAccumulate(int i, long x,
|
||||
LongBinaryOperator accumulatorFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
long prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = accumulatorFunction.applyAsLong(prev, x);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the
|
||||
* results of applying the given function to the current and
|
||||
* given values, returning the updated value. The function should
|
||||
* be side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function is
|
||||
* applied with the current value at index {@code i} as its first
|
||||
* argument, and the given update as the second argument.
|
||||
*
|
||||
* @param i the index
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long accumulateAndGet(int i, long x,
|
||||
LongBinaryOperator accumulatorFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
long prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = accumulatorFunction.applyAsLong(prev, x);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the current values of array.
|
||||
* @return the String representation of the current values of array
|
||||
*/
|
||||
public String toString() {
|
||||
int iMax = array.length - 1;
|
||||
if (iMax == -1)
|
||||
return "[]";
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append('[');
|
||||
for (int i = 0; ; i++) {
|
||||
b.append(getRaw(byteOffset(i)));
|
||||
if (i == iMax)
|
||||
return b.append(']').toString();
|
||||
b.append(',').append(' ');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Objects;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import java.util.function.LongUnaryOperator;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
/**
|
||||
* A reflection-based utility that enables atomic updates to
|
||||
* designated {@code volatile long} fields of designated classes.
|
||||
* This class is designed for use in atomic data structures in which
|
||||
* several fields of the same node are independently subject to atomic
|
||||
* updates.
|
||||
*
|
||||
* <p>Note that the guarantees of the {@code compareAndSet}
|
||||
* method in this class are weaker than in other atomic classes.
|
||||
* Because this class cannot ensure that all uses of the field
|
||||
* are appropriate for purposes of atomic access, it can
|
||||
* guarantee atomicity only with respect to other invocations of
|
||||
* {@code compareAndSet} and {@code set} on the same updater.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <T> The type of the object holding the updatable field
|
||||
*/
|
||||
public abstract class AtomicLongFieldUpdater<T> {
|
||||
/**
|
||||
* Creates and returns an updater for objects with the given field.
|
||||
* The Class argument is needed to check that reflective types and
|
||||
* generic types match.
|
||||
*
|
||||
* @param tclass the class of the objects holding the field
|
||||
* @param fieldName the name of the field to be updated
|
||||
* @param <U> the type of instances of tclass
|
||||
* @return the updater
|
||||
* @throws IllegalArgumentException if the field is not a
|
||||
* volatile long type
|
||||
* @throws RuntimeException with a nested reflection-based
|
||||
* exception if the class does not hold field or is the wrong type,
|
||||
* or the field is inaccessible to the caller according to Java language
|
||||
* access control
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
|
||||
String fieldName) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
if (AtomicLong.VM_SUPPORTS_LONG_CAS)
|
||||
return new CASUpdater<U>(tclass, fieldName, caller);
|
||||
else
|
||||
return new LockedUpdater<U>(tclass, fieldName, caller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected do-nothing constructor for use by subclasses.
|
||||
*/
|
||||
protected AtomicLongFieldUpdater() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the field of the given object managed by this updater
|
||||
* to the given updated value if the current value {@code ==} the
|
||||
* expected value. This method is guaranteed to be atomic with respect to
|
||||
* other calls to {@code compareAndSet} and {@code set}, but not
|
||||
* necessarily with respect to other changes in the field.
|
||||
*
|
||||
* @param obj An object whose field to conditionally set
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
* @throws ClassCastException if {@code obj} is not an instance
|
||||
* of the class possessing the field established in the constructor
|
||||
*/
|
||||
public abstract boolean compareAndSet(T obj, long expect, long update);
|
||||
|
||||
/**
|
||||
* Atomically sets the field of the given object managed by this updater
|
||||
* to the given updated value if the current value {@code ==} the
|
||||
* expected value. This method is guaranteed to be atomic with respect to
|
||||
* other calls to {@code compareAndSet} and {@code set}, but not
|
||||
* necessarily with respect to other changes in the field.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param obj An object whose field to conditionally set
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
* @throws ClassCastException if {@code obj} is not an instance
|
||||
* of the class possessing the field established in the constructor
|
||||
*/
|
||||
public abstract boolean weakCompareAndSet(T obj, long expect, long update);
|
||||
|
||||
/**
|
||||
* Sets the field of the given object managed by this updater to the
|
||||
* given updated value. This operation is guaranteed to act as a volatile
|
||||
* store with respect to subsequent invocations of {@code compareAndSet}.
|
||||
*
|
||||
* @param obj An object whose field to set
|
||||
* @param newValue the new value
|
||||
*/
|
||||
public abstract void set(T obj, long newValue);
|
||||
|
||||
/**
|
||||
* Eventually sets the field of the given object managed by this
|
||||
* updater to the given updated value.
|
||||
*
|
||||
* @param obj An object whose field to set
|
||||
* @param newValue the new value
|
||||
* @since 1.6
|
||||
*/
|
||||
public abstract void lazySet(T obj, long newValue);
|
||||
|
||||
/**
|
||||
* Gets the current value held in the field of the given object managed
|
||||
* by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get
|
||||
* @return the current value
|
||||
*/
|
||||
public abstract long get(T obj);
|
||||
|
||||
/**
|
||||
* Atomically sets the field of the given object managed by this updater
|
||||
* to the given value and returns the old value.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param newValue the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
public long getAndSet(T obj, long newValue) {
|
||||
long prev;
|
||||
do {
|
||||
prev = get(obj);
|
||||
} while (!compareAndSet(obj, prev, newValue));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the current value of the field of the
|
||||
* given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @return the previous value
|
||||
*/
|
||||
public long getAndIncrement(T obj) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev + 1;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the current value of the field of the
|
||||
* given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @return the previous value
|
||||
*/
|
||||
public long getAndDecrement(T obj) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev - 1;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the current value of the field of
|
||||
* the given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param delta the value to add
|
||||
* @return the previous value
|
||||
*/
|
||||
public long getAndAdd(T obj, long delta) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev + delta;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the current value of the field of the
|
||||
* given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @return the updated value
|
||||
*/
|
||||
public long incrementAndGet(T obj) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev + 1;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements by one the current value of the field of the
|
||||
* given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @return the updated value
|
||||
*/
|
||||
public long decrementAndGet(T obj) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev - 1;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically adds the given value to the current value of the field of
|
||||
* the given object managed by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param delta the value to add
|
||||
* @return the updated value
|
||||
*/
|
||||
public long addAndGet(T obj, long delta) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = prev + delta;
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this updater
|
||||
* with the results of applying the given function, returning the previous
|
||||
* value. The function should be side-effect-free, since it may be
|
||||
* re-applied when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = updateFunction.applyAsLong(prev);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this updater
|
||||
* with the results of applying the given function, returning the updated
|
||||
* value. The function should be side-effect-free, since it may be
|
||||
* re-applied when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long updateAndGet(T obj, LongUnaryOperator updateFunction) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = updateFunction.applyAsLong(prev);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this
|
||||
* updater with the results of applying the given function to the
|
||||
* current and given values, returning the previous value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads. The
|
||||
* function is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long getAndAccumulate(T obj, long x,
|
||||
LongBinaryOperator accumulatorFunction) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = accumulatorFunction.applyAsLong(prev, x);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this
|
||||
* updater with the results of applying the given function to the
|
||||
* current and given values, returning the updated value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads. The
|
||||
* function is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final long accumulateAndGet(T obj, long x,
|
||||
LongBinaryOperator accumulatorFunction) {
|
||||
long prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = accumulatorFunction.applyAsLong(prev, x);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
|
||||
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
|
||||
private final long offset;
|
||||
/**
|
||||
* if field is protected, the subclass constructing updater, else
|
||||
* the same as tclass
|
||||
*/
|
||||
private final Class<?> cclass;
|
||||
/** class holding the field */
|
||||
private final Class<T> tclass;
|
||||
|
||||
CASUpdater(final Class<T> tclass, final String fieldName,
|
||||
final Class<?> caller) {
|
||||
final Field field;
|
||||
final int modifiers;
|
||||
try {
|
||||
field = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Field>() {
|
||||
public Field run() throws NoSuchFieldException {
|
||||
return tclass.getDeclaredField(fieldName);
|
||||
}
|
||||
});
|
||||
modifiers = field.getModifiers();
|
||||
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
|
||||
caller, tclass, null, modifiers);
|
||||
ClassLoader cl = tclass.getClassLoader();
|
||||
ClassLoader ccl = caller.getClassLoader();
|
||||
if ((ccl != null) && (ccl != cl) &&
|
||||
((cl == null) || !isAncestor(cl, ccl))) {
|
||||
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
|
||||
}
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw new RuntimeException(pae.getException());
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
if (field.getType() != long.class)
|
||||
throw new IllegalArgumentException("Must be long type");
|
||||
|
||||
if (!Modifier.isVolatile(modifiers))
|
||||
throw new IllegalArgumentException("Must be volatile type");
|
||||
|
||||
// Access to protected field members is restricted to receivers only
|
||||
// of the accessing class, or one of its subclasses, and the
|
||||
// accessing class must in turn be a subclass (or package sibling)
|
||||
// of the protected member's defining class.
|
||||
// If the updater refers to a protected field of a declaring class
|
||||
// outside the current package, the receiver argument will be
|
||||
// narrowed to the type of the accessing class.
|
||||
this.cclass = (Modifier.isProtected(modifiers) &&
|
||||
tclass.isAssignableFrom(caller) &&
|
||||
!isSamePackage(tclass, caller))
|
||||
? caller : tclass;
|
||||
this.tclass = tclass;
|
||||
this.offset = U.objectFieldOffset(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that target argument is instance of cclass. On
|
||||
* failure, throws cause.
|
||||
*/
|
||||
private final void accessCheck(T obj) {
|
||||
if (!cclass.isInstance(obj))
|
||||
throwAccessCheckException(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws access exception if accessCheck failed due to
|
||||
* protected access, else ClassCastException.
|
||||
*/
|
||||
private final void throwAccessCheckException(T obj) {
|
||||
if (cclass == tclass)
|
||||
throw new ClassCastException();
|
||||
else
|
||||
throw new RuntimeException(
|
||||
new IllegalAccessException(
|
||||
"Class " +
|
||||
cclass.getName() +
|
||||
" can not access a protected member of class " +
|
||||
tclass.getName() +
|
||||
" using an instance of " +
|
||||
obj.getClass().getName()));
|
||||
}
|
||||
|
||||
public final boolean compareAndSet(T obj, long expect, long update) {
|
||||
accessCheck(obj);
|
||||
return U.compareAndSwapLong(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
public final boolean weakCompareAndSet(T obj, long expect, long update) {
|
||||
accessCheck(obj);
|
||||
return U.compareAndSwapLong(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
public final void set(T obj, long newValue) {
|
||||
accessCheck(obj);
|
||||
U.putLongVolatile(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final void lazySet(T obj, long newValue) {
|
||||
accessCheck(obj);
|
||||
U.putOrderedLong(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final long get(T obj) {
|
||||
accessCheck(obj);
|
||||
return U.getLongVolatile(obj, offset);
|
||||
}
|
||||
|
||||
public final long getAndSet(T obj, long newValue) {
|
||||
accessCheck(obj);
|
||||
return U.getAndSetLong(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final long getAndAdd(T obj, long delta) {
|
||||
accessCheck(obj);
|
||||
return U.getAndAddLong(obj, offset, delta);
|
||||
}
|
||||
|
||||
public final long getAndIncrement(T obj) {
|
||||
return getAndAdd(obj, 1);
|
||||
}
|
||||
|
||||
public final long getAndDecrement(T obj) {
|
||||
return getAndAdd(obj, -1);
|
||||
}
|
||||
|
||||
public final long incrementAndGet(T obj) {
|
||||
return getAndAdd(obj, 1) + 1;
|
||||
}
|
||||
|
||||
public final long decrementAndGet(T obj) {
|
||||
return getAndAdd(obj, -1) - 1;
|
||||
}
|
||||
|
||||
public final long addAndGet(T obj, long delta) {
|
||||
return getAndAdd(obj, delta) + delta;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
|
||||
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
|
||||
private final long offset;
|
||||
/**
|
||||
* if field is protected, the subclass constructing updater, else
|
||||
* the same as tclass
|
||||
*/
|
||||
private final Class<?> cclass;
|
||||
/** class holding the field */
|
||||
private final Class<T> tclass;
|
||||
|
||||
LockedUpdater(final Class<T> tclass, final String fieldName,
|
||||
final Class<?> caller) {
|
||||
Field field = null;
|
||||
int modifiers = 0;
|
||||
try {
|
||||
field = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Field>() {
|
||||
public Field run() throws NoSuchFieldException {
|
||||
return tclass.getDeclaredField(fieldName);
|
||||
}
|
||||
});
|
||||
modifiers = field.getModifiers();
|
||||
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
|
||||
caller, tclass, null, modifiers);
|
||||
ClassLoader cl = tclass.getClassLoader();
|
||||
ClassLoader ccl = caller.getClassLoader();
|
||||
if ((ccl != null) && (ccl != cl) &&
|
||||
((cl == null) || !isAncestor(cl, ccl))) {
|
||||
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
|
||||
}
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw new RuntimeException(pae.getException());
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
if (field.getType() != long.class)
|
||||
throw new IllegalArgumentException("Must be long type");
|
||||
|
||||
if (!Modifier.isVolatile(modifiers))
|
||||
throw new IllegalArgumentException("Must be volatile type");
|
||||
|
||||
// Access to protected field members is restricted to receivers only
|
||||
// of the accessing class, or one of its subclasses, and the
|
||||
// accessing class must in turn be a subclass (or package sibling)
|
||||
// of the protected member's defining class.
|
||||
// If the updater refers to a protected field of a declaring class
|
||||
// outside the current package, the receiver argument will be
|
||||
// narrowed to the type of the accessing class.
|
||||
this.cclass = (Modifier.isProtected(modifiers) &&
|
||||
tclass.isAssignableFrom(caller) &&
|
||||
!isSamePackage(tclass, caller))
|
||||
? caller : tclass;
|
||||
this.tclass = tclass;
|
||||
this.offset = U.objectFieldOffset(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that target argument is instance of cclass. On
|
||||
* failure, throws cause.
|
||||
*/
|
||||
private final void accessCheck(T obj) {
|
||||
if (!cclass.isInstance(obj))
|
||||
throw accessCheckException(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns access exception if accessCheck failed due to
|
||||
* protected access, else ClassCastException.
|
||||
*/
|
||||
private final RuntimeException accessCheckException(T obj) {
|
||||
if (cclass == tclass)
|
||||
return new ClassCastException();
|
||||
else
|
||||
return new RuntimeException(
|
||||
new IllegalAccessException(
|
||||
"Class " +
|
||||
cclass.getName() +
|
||||
" can not access a protected member of class " +
|
||||
tclass.getName() +
|
||||
" using an instance of " +
|
||||
obj.getClass().getName()));
|
||||
}
|
||||
|
||||
public final boolean compareAndSet(T obj, long expect, long update) {
|
||||
accessCheck(obj);
|
||||
synchronized (this) {
|
||||
long v = U.getLong(obj, offset);
|
||||
if (v != expect)
|
||||
return false;
|
||||
U.putLong(obj, offset, update);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean weakCompareAndSet(T obj, long expect, long update) {
|
||||
return compareAndSet(obj, expect, update);
|
||||
}
|
||||
|
||||
public final void set(T obj, long newValue) {
|
||||
accessCheck(obj);
|
||||
synchronized (this) {
|
||||
U.putLong(obj, offset, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
public final void lazySet(T obj, long newValue) {
|
||||
set(obj, newValue);
|
||||
}
|
||||
|
||||
public final long get(T obj) {
|
||||
accessCheck(obj);
|
||||
synchronized (this) {
|
||||
return U.getLong(obj, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the second classloader can be found in the first
|
||||
* classloader's delegation chain.
|
||||
* Equivalent to the inaccessible: first.isAncestor(second).
|
||||
*/
|
||||
static boolean isAncestor(ClassLoader first, ClassLoader second) {
|
||||
ClassLoader acl = first;
|
||||
do {
|
||||
acl = acl.getParent();
|
||||
if (second == acl) {
|
||||
return true;
|
||||
}
|
||||
} while (acl != null);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the two classes have the same class loader and
|
||||
* package qualifier
|
||||
*/
|
||||
private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
|
||||
return class1.getClassLoader() == class2.getClassLoader()
|
||||
&& Objects.equals(getPackageName(class1), getPackageName(class2));
|
||||
}
|
||||
|
||||
private static String getPackageName(Class<?> cls) {
|
||||
String cn = cls.getName();
|
||||
int dot = cn.lastIndexOf('.');
|
||||
return (dot != -1) ? cn.substring(0, dot) : "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
|
||||
/**
|
||||
* An {@code AtomicMarkableReference} maintains an object reference
|
||||
* along with a mark bit, that can be updated atomically.
|
||||
*
|
||||
* <p>Implementation note: This implementation maintains markable
|
||||
* references by creating internal objects representing "boxed"
|
||||
* [reference, boolean] pairs.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <V> The type of object referred to by this reference
|
||||
*/
|
||||
public class AtomicMarkableReference<V> {
|
||||
|
||||
private static class Pair<T> {
|
||||
final T reference;
|
||||
final boolean mark;
|
||||
private Pair(T reference, boolean mark) {
|
||||
this.reference = reference;
|
||||
this.mark = mark;
|
||||
}
|
||||
static <T> Pair<T> of(T reference, boolean mark) {
|
||||
return new Pair<T>(reference, mark);
|
||||
}
|
||||
}
|
||||
|
||||
private volatile Pair<V> pair;
|
||||
|
||||
/**
|
||||
* Creates a new {@code AtomicMarkableReference} with the given
|
||||
* initial values.
|
||||
*
|
||||
* @param initialRef the initial reference
|
||||
* @param initialMark the initial mark
|
||||
*/
|
||||
public AtomicMarkableReference(V initialRef, boolean initialMark) {
|
||||
pair = Pair.of(initialRef, initialMark);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value of the reference.
|
||||
*
|
||||
* @return the current value of the reference
|
||||
*/
|
||||
public V getReference() {
|
||||
return pair.reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value of the mark.
|
||||
*
|
||||
* @return the current value of the mark
|
||||
*/
|
||||
public boolean isMarked() {
|
||||
return pair.mark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current values of both the reference and the mark.
|
||||
* Typical usage is {@code boolean[1] holder; ref = v.get(holder); }.
|
||||
*
|
||||
* @param markHolder an array of size of at least one. On return,
|
||||
* {@code markholder[0]} will hold the value of the mark.
|
||||
* @return the current value of the reference
|
||||
*/
|
||||
public V get(boolean[] markHolder) {
|
||||
Pair<V> pair = this.pair;
|
||||
markHolder[0] = pair.mark;
|
||||
return pair.reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value of both the reference and mark
|
||||
* to the given update values if the
|
||||
* current reference is {@code ==} to the expected reference
|
||||
* and the current mark is equal to the expected mark.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param expectedReference the expected value of the reference
|
||||
* @param newReference the new value for the reference
|
||||
* @param expectedMark the expected value of the mark
|
||||
* @param newMark the new value for the mark
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public boolean weakCompareAndSet(V expectedReference,
|
||||
V newReference,
|
||||
boolean expectedMark,
|
||||
boolean newMark) {
|
||||
return compareAndSet(expectedReference, newReference,
|
||||
expectedMark, newMark);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value of both the reference and mark
|
||||
* to the given update values if the
|
||||
* current reference is {@code ==} to the expected reference
|
||||
* and the current mark is equal to the expected mark.
|
||||
*
|
||||
* @param expectedReference the expected value of the reference
|
||||
* @param newReference the new value for the reference
|
||||
* @param expectedMark the expected value of the mark
|
||||
* @param newMark the new value for the mark
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public boolean compareAndSet(V expectedReference,
|
||||
V newReference,
|
||||
boolean expectedMark,
|
||||
boolean newMark) {
|
||||
Pair<V> current = pair;
|
||||
return
|
||||
expectedReference == current.reference &&
|
||||
expectedMark == current.mark &&
|
||||
((newReference == current.reference &&
|
||||
newMark == current.mark) ||
|
||||
casPair(current, Pair.of(newReference, newMark)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally sets the value of both the reference and mark.
|
||||
*
|
||||
* @param newReference the new value for the reference
|
||||
* @param newMark the new value for the mark
|
||||
*/
|
||||
public void set(V newReference, boolean newMark) {
|
||||
Pair<V> current = pair;
|
||||
if (newReference != current.reference || newMark != current.mark)
|
||||
this.pair = Pair.of(newReference, newMark);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value of the mark to the given update value
|
||||
* if the current reference is {@code ==} to the expected
|
||||
* reference. Any given invocation of this operation may fail
|
||||
* (return {@code false}) spuriously, but repeated invocation
|
||||
* when the current value holds the expected value and no other
|
||||
* thread is also attempting to set the value will eventually
|
||||
* succeed.
|
||||
*
|
||||
* @param expectedReference the expected value of the reference
|
||||
* @param newMark the new value for the mark
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public boolean attemptMark(V expectedReference, boolean newMark) {
|
||||
Pair<V> current = pair;
|
||||
return
|
||||
expectedReference == current.reference &&
|
||||
(newMark == current.mark ||
|
||||
casPair(current, Pair.of(expectedReference, newMark)));
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long pairOffset =
|
||||
objectFieldOffset(UNSAFE, "pair", AtomicMarkableReference.class);
|
||||
|
||||
private boolean casPair(Pair<V> cmp, Pair<V> val) {
|
||||
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
|
||||
}
|
||||
|
||||
static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
|
||||
String field, Class<?> klazz) {
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Convert Exception to corresponding Error
|
||||
NoSuchFieldError error = new NoSuchFieldError(field);
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
240
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicReference.java
Normal file
240
jdkSrc/jdk8/java/util/concurrent/atomic/AtomicReference.java
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.function.BinaryOperator;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* An object reference that may be updated atomically. See the {@link
|
||||
* java.util.concurrent.atomic} package specification for description
|
||||
* of the properties of atomic variables.
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <V> The type of object referred to by this reference
|
||||
*/
|
||||
public class AtomicReference<V> implements java.io.Serializable {
|
||||
private static final long serialVersionUID = -1848883965231344442L;
|
||||
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private static final long valueOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
valueOffset = unsafe.objectFieldOffset
|
||||
(AtomicReference.class.getDeclaredField("value"));
|
||||
} catch (Exception ex) { throw new Error(ex); }
|
||||
}
|
||||
|
||||
private volatile V value;
|
||||
|
||||
/**
|
||||
* Creates a new AtomicReference with the given initial value.
|
||||
*
|
||||
* @param initialValue the initial value
|
||||
*/
|
||||
public AtomicReference(V initialValue) {
|
||||
value = initialValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AtomicReference with null initial value.
|
||||
*/
|
||||
public AtomicReference() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value.
|
||||
*
|
||||
* @return the current value
|
||||
*/
|
||||
public final V get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets to the given value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
*/
|
||||
public final void set(V newValue) {
|
||||
value = newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eventually sets to the given value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(V newValue) {
|
||||
unsafe.putOrderedObject(this, valueOffset, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value to the given updated value
|
||||
* if the current value {@code ==} the expected value.
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
*/
|
||||
public final boolean compareAndSet(V expect, V update) {
|
||||
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value to the given updated value
|
||||
* if the current value {@code ==} the expected value.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public final boolean weakCompareAndSet(V expect, V update) {
|
||||
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets to the given value and returns the old value.
|
||||
*
|
||||
* @param newValue the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final V getAndSet(V newValue) {
|
||||
return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function, returning the previous value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final V getAndUpdate(UnaryOperator<V> updateFunction) {
|
||||
V prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = updateFunction.apply(prev);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function, returning the updated value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final V updateAndGet(UnaryOperator<V> updateFunction) {
|
||||
V prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = updateFunction.apply(prev);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function to the current and given values,
|
||||
* returning the previous value. The function should be
|
||||
* side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function
|
||||
* is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final V getAndAccumulate(V x,
|
||||
BinaryOperator<V> accumulatorFunction) {
|
||||
V prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = accumulatorFunction.apply(prev, x);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the current value with the results of
|
||||
* applying the given function to the current and given values,
|
||||
* returning the updated value. The function should be
|
||||
* side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function
|
||||
* is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final V accumulateAndGet(V x,
|
||||
BinaryOperator<V> accumulatorFunction) {
|
||||
V prev, next;
|
||||
do {
|
||||
prev = get();
|
||||
next = accumulatorFunction.apply(prev, x);
|
||||
} while (!compareAndSet(prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the current value.
|
||||
* @return the String representation of the current value
|
||||
*/
|
||||
public String toString() {
|
||||
return String.valueOf(get());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.Arrays;
|
||||
import java.lang.reflect.Array;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* An array of object references in which elements may be updated
|
||||
* atomically. See the {@link java.util.concurrent.atomic} package
|
||||
* specification for description of the properties of atomic
|
||||
* variables.
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <E> The base class of elements held in this array
|
||||
*/
|
||||
public class AtomicReferenceArray<E> implements java.io.Serializable {
|
||||
private static final long serialVersionUID = -6209656149925076980L;
|
||||
|
||||
private static final Unsafe unsafe;
|
||||
private static final int base;
|
||||
private static final int shift;
|
||||
private static final long arrayFieldOffset;
|
||||
private final Object[] array; // must have exact type Object[]
|
||||
|
||||
static {
|
||||
try {
|
||||
unsafe = Unsafe.getUnsafe();
|
||||
arrayFieldOffset = unsafe.objectFieldOffset
|
||||
(AtomicReferenceArray.class.getDeclaredField("array"));
|
||||
base = unsafe.arrayBaseOffset(Object[].class);
|
||||
int scale = unsafe.arrayIndexScale(Object[].class);
|
||||
if ((scale & (scale - 1)) != 0)
|
||||
throw new Error("data type scale not a power of two");
|
||||
shift = 31 - Integer.numberOfLeadingZeros(scale);
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private long checkedByteOffset(int i) {
|
||||
if (i < 0 || i >= array.length)
|
||||
throw new IndexOutOfBoundsException("index " + i);
|
||||
|
||||
return byteOffset(i);
|
||||
}
|
||||
|
||||
private static long byteOffset(int i) {
|
||||
return ((long) i << shift) + base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AtomicReferenceArray of the given length, with all
|
||||
* elements initially null.
|
||||
*
|
||||
* @param length the length of the array
|
||||
*/
|
||||
public AtomicReferenceArray(int length) {
|
||||
array = new Object[length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AtomicReferenceArray with the same length as, and
|
||||
* all elements copied from, the given array.
|
||||
*
|
||||
* @param array the array to copy elements from
|
||||
* @throws NullPointerException if array is null
|
||||
*/
|
||||
public AtomicReferenceArray(E[] array) {
|
||||
// Visibility guaranteed by final field guarantees
|
||||
this.array = Arrays.copyOf(array, array.length, Object[].class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the array.
|
||||
*
|
||||
* @return the length of the array
|
||||
*/
|
||||
public final int length() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value at position {@code i}.
|
||||
*
|
||||
* @param i the index
|
||||
* @return the current value
|
||||
*/
|
||||
public final E get(int i) {
|
||||
return getRaw(checkedByteOffset(i));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private E getRaw(long offset) {
|
||||
return (E) unsafe.getObjectVolatile(array, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the element at position {@code i} to the given value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param newValue the new value
|
||||
*/
|
||||
public final void set(int i, E newValue) {
|
||||
unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Eventually sets the element at position {@code i} to the given value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param newValue the new value
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int i, E newValue) {
|
||||
unsafe.putOrderedObject(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the element at position {@code i} to the given
|
||||
* value and returns the old value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param newValue the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final E getAndSet(int i, E newValue) {
|
||||
return (E)unsafe.getAndSetObject(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the element at position {@code i} to the given
|
||||
* updated value if the current value {@code ==} the expected value.
|
||||
*
|
||||
* @param i the index
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful. False return indicates that
|
||||
* the actual value was not equal to the expected value.
|
||||
*/
|
||||
public final boolean compareAndSet(int i, E expect, E update) {
|
||||
return compareAndSetRaw(checkedByteOffset(i), expect, update);
|
||||
}
|
||||
|
||||
private boolean compareAndSetRaw(long offset, E expect, E update) {
|
||||
return unsafe.compareAndSwapObject(array, offset, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the element at position {@code i} to the given
|
||||
* updated value if the current value {@code ==} the expected value.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param i the index
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public final boolean weakCompareAndSet(int i, E expect, E update) {
|
||||
return compareAndSet(i, expect, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the results
|
||||
* of applying the given function, returning the previous value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param i the index
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final E getAndUpdate(int i, UnaryOperator<E> updateFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
E prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = updateFunction.apply(prev);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the results
|
||||
* of applying the given function, returning the updated value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param i the index
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final E updateAndGet(int i, UnaryOperator<E> updateFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
E prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = updateFunction.apply(prev);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the
|
||||
* results of applying the given function to the current and
|
||||
* given values, returning the previous value. The function should
|
||||
* be side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function is
|
||||
* applied with the current value at index {@code i} as its first
|
||||
* argument, and the given update as the second argument.
|
||||
*
|
||||
* @param i the index
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final E getAndAccumulate(int i, E x,
|
||||
BinaryOperator<E> accumulatorFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
E prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = accumulatorFunction.apply(prev, x);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the element at index {@code i} with the
|
||||
* results of applying the given function to the current and
|
||||
* given values, returning the updated value. The function should
|
||||
* be side-effect-free, since it may be re-applied when attempted
|
||||
* updates fail due to contention among threads. The function is
|
||||
* applied with the current value at index {@code i} as its first
|
||||
* argument, and the given update as the second argument.
|
||||
*
|
||||
* @param i the index
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final E accumulateAndGet(int i, E x,
|
||||
BinaryOperator<E> accumulatorFunction) {
|
||||
long offset = checkedByteOffset(i);
|
||||
E prev, next;
|
||||
do {
|
||||
prev = getRaw(offset);
|
||||
next = accumulatorFunction.apply(prev, x);
|
||||
} while (!compareAndSetRaw(offset, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the current values of array.
|
||||
* @return the String representation of the current values of array
|
||||
*/
|
||||
public String toString() {
|
||||
int iMax = array.length - 1;
|
||||
if (iMax == -1)
|
||||
return "[]";
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append('[');
|
||||
for (int i = 0; ; i++) {
|
||||
b.append(getRaw(byteOffset(i)));
|
||||
if (i == iMax)
|
||||
return b.append(']').toString();
|
||||
b.append(',').append(' ');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitutes the instance from a stream (that is, deserializes it).
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException,
|
||||
java.io.InvalidObjectException {
|
||||
// Note: This must be changed if any additional fields are defined
|
||||
Object a = s.readFields().get("array", null);
|
||||
if (a == null || !a.getClass().isArray())
|
||||
throw new java.io.InvalidObjectException("Not array type");
|
||||
if (a.getClass() != Object[].class)
|
||||
a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class);
|
||||
unsafe.putObjectVolatile(this, arrayFieldOffset, a);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.UnaryOperator;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
/**
|
||||
* A reflection-based utility that enables atomic updates to
|
||||
* designated {@code volatile} reference fields of designated
|
||||
* classes. This class is designed for use in atomic data structures
|
||||
* in which several reference fields of the same node are
|
||||
* independently subject to atomic updates. For example, a tree node
|
||||
* might be declared as
|
||||
*
|
||||
* <pre> {@code
|
||||
* class Node {
|
||||
* private volatile Node left, right;
|
||||
*
|
||||
* private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
|
||||
* AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
|
||||
* private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
|
||||
* AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
|
||||
*
|
||||
* Node getLeft() { return left; }
|
||||
* boolean compareAndSetLeft(Node expect, Node update) {
|
||||
* return leftUpdater.compareAndSet(this, expect, update);
|
||||
* }
|
||||
* // ... and so on
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>Note that the guarantees of the {@code compareAndSet}
|
||||
* method in this class are weaker than in other atomic classes.
|
||||
* Because this class cannot ensure that all uses of the field
|
||||
* are appropriate for purposes of atomic access, it can
|
||||
* guarantee atomicity only with respect to other invocations of
|
||||
* {@code compareAndSet} and {@code set} on the same updater.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <T> The type of the object holding the updatable field
|
||||
* @param <V> The type of the field
|
||||
*/
|
||||
public abstract class AtomicReferenceFieldUpdater<T,V> {
|
||||
|
||||
/**
|
||||
* Creates and returns an updater for objects with the given field.
|
||||
* The Class arguments are needed to check that reflective types and
|
||||
* generic types match.
|
||||
*
|
||||
* @param tclass the class of the objects holding the field
|
||||
* @param vclass the class of the field
|
||||
* @param fieldName the name of the field to be updated
|
||||
* @param <U> the type of instances of tclass
|
||||
* @param <W> the type of instances of vclass
|
||||
* @return the updater
|
||||
* @throws ClassCastException if the field is of the wrong type
|
||||
* @throws IllegalArgumentException if the field is not volatile
|
||||
* @throws RuntimeException with a nested reflection-based
|
||||
* exception if the class does not hold field or is the wrong type,
|
||||
* or the field is inaccessible to the caller according to Java language
|
||||
* access control
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass,
|
||||
Class<W> vclass,
|
||||
String fieldName) {
|
||||
return new AtomicReferenceFieldUpdaterImpl<U,W>
|
||||
(tclass, vclass, fieldName, Reflection.getCallerClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected do-nothing constructor for use by subclasses.
|
||||
*/
|
||||
protected AtomicReferenceFieldUpdater() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the field of the given object managed by this updater
|
||||
* to the given updated value if the current value {@code ==} the
|
||||
* expected value. This method is guaranteed to be atomic with respect to
|
||||
* other calls to {@code compareAndSet} and {@code set}, but not
|
||||
* necessarily with respect to other changes in the field.
|
||||
*
|
||||
* @param obj An object whose field to conditionally set
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public abstract boolean compareAndSet(T obj, V expect, V update);
|
||||
|
||||
/**
|
||||
* Atomically sets the field of the given object managed by this updater
|
||||
* to the given updated value if the current value {@code ==} the
|
||||
* expected value. This method is guaranteed to be atomic with respect to
|
||||
* other calls to {@code compareAndSet} and {@code set}, but not
|
||||
* necessarily with respect to other changes in the field.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param obj An object whose field to conditionally set
|
||||
* @param expect the expected value
|
||||
* @param update the new value
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public abstract boolean weakCompareAndSet(T obj, V expect, V update);
|
||||
|
||||
/**
|
||||
* Sets the field of the given object managed by this updater to the
|
||||
* given updated value. This operation is guaranteed to act as a volatile
|
||||
* store with respect to subsequent invocations of {@code compareAndSet}.
|
||||
*
|
||||
* @param obj An object whose field to set
|
||||
* @param newValue the new value
|
||||
*/
|
||||
public abstract void set(T obj, V newValue);
|
||||
|
||||
/**
|
||||
* Eventually sets the field of the given object managed by this
|
||||
* updater to the given updated value.
|
||||
*
|
||||
* @param obj An object whose field to set
|
||||
* @param newValue the new value
|
||||
* @since 1.6
|
||||
*/
|
||||
public abstract void lazySet(T obj, V newValue);
|
||||
|
||||
/**
|
||||
* Gets the current value held in the field of the given object managed
|
||||
* by this updater.
|
||||
*
|
||||
* @param obj An object whose field to get
|
||||
* @return the current value
|
||||
*/
|
||||
public abstract V get(T obj);
|
||||
|
||||
/**
|
||||
* Atomically sets the field of the given object managed by this updater
|
||||
* to the given value and returns the old value.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param newValue the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
public V getAndSet(T obj, V newValue) {
|
||||
V prev;
|
||||
do {
|
||||
prev = get(obj);
|
||||
} while (!compareAndSet(obj, prev, newValue));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this updater
|
||||
* with the results of applying the given function, returning the previous
|
||||
* value. The function should be side-effect-free, since it may be
|
||||
* re-applied when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final V getAndUpdate(T obj, UnaryOperator<V> updateFunction) {
|
||||
V prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = updateFunction.apply(prev);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this updater
|
||||
* with the results of applying the given function, returning the updated
|
||||
* value. The function should be side-effect-free, since it may be
|
||||
* re-applied when attempted updates fail due to contention among threads.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param updateFunction a side-effect-free function
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final V updateAndGet(T obj, UnaryOperator<V> updateFunction) {
|
||||
V prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = updateFunction.apply(prev);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this
|
||||
* updater with the results of applying the given function to the
|
||||
* current and given values, returning the previous value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads. The
|
||||
* function is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the previous value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final V getAndAccumulate(T obj, V x,
|
||||
BinaryOperator<V> accumulatorFunction) {
|
||||
V prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = accumulatorFunction.apply(prev, x);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically updates the field of the given object managed by this
|
||||
* updater with the results of applying the given function to the
|
||||
* current and given values, returning the updated value. The
|
||||
* function should be side-effect-free, since it may be re-applied
|
||||
* when attempted updates fail due to contention among threads. The
|
||||
* function is applied with the current value as its first argument,
|
||||
* and the given update as the second argument.
|
||||
*
|
||||
* @param obj An object whose field to get and set
|
||||
* @param x the update value
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @return the updated value
|
||||
* @since 1.8
|
||||
*/
|
||||
public final V accumulateAndGet(T obj, V x,
|
||||
BinaryOperator<V> accumulatorFunction) {
|
||||
V prev, next;
|
||||
do {
|
||||
prev = get(obj);
|
||||
next = accumulatorFunction.apply(prev, x);
|
||||
} while (!compareAndSet(obj, prev, next));
|
||||
return next;
|
||||
}
|
||||
|
||||
private static final class AtomicReferenceFieldUpdaterImpl<T,V>
|
||||
extends AtomicReferenceFieldUpdater<T,V> {
|
||||
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
|
||||
private final long offset;
|
||||
/**
|
||||
* if field is protected, the subclass constructing updater, else
|
||||
* the same as tclass
|
||||
*/
|
||||
private final Class<?> cclass;
|
||||
/** class holding the field */
|
||||
private final Class<T> tclass;
|
||||
/** field value type */
|
||||
private final Class<V> vclass;
|
||||
|
||||
/*
|
||||
* Internal type checks within all update methods contain
|
||||
* internal inlined optimizations checking for the common
|
||||
* cases where the class is final (in which case a simple
|
||||
* getClass comparison suffices) or is of type Object (in
|
||||
* which case no check is needed because all objects are
|
||||
* instances of Object). The Object case is handled simply by
|
||||
* setting vclass to null in constructor. The targetCheck and
|
||||
* updateCheck methods are invoked when these faster
|
||||
* screenings fail.
|
||||
*/
|
||||
|
||||
AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
|
||||
final Class<V> vclass,
|
||||
final String fieldName,
|
||||
final Class<?> caller) {
|
||||
final Field field;
|
||||
final Class<?> fieldClass;
|
||||
final int modifiers;
|
||||
try {
|
||||
field = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Field>() {
|
||||
public Field run() throws NoSuchFieldException {
|
||||
return tclass.getDeclaredField(fieldName);
|
||||
}
|
||||
});
|
||||
modifiers = field.getModifiers();
|
||||
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
|
||||
caller, tclass, null, modifiers);
|
||||
ClassLoader cl = tclass.getClassLoader();
|
||||
ClassLoader ccl = caller.getClassLoader();
|
||||
if ((ccl != null) && (ccl != cl) &&
|
||||
((cl == null) || !isAncestor(cl, ccl))) {
|
||||
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
|
||||
}
|
||||
fieldClass = field.getType();
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw new RuntimeException(pae.getException());
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
if (vclass != fieldClass)
|
||||
throw new ClassCastException();
|
||||
if (vclass.isPrimitive())
|
||||
throw new IllegalArgumentException("Must be reference type");
|
||||
|
||||
if (!Modifier.isVolatile(modifiers))
|
||||
throw new IllegalArgumentException("Must be volatile type");
|
||||
|
||||
// Access to protected field members is restricted to receivers only
|
||||
// of the accessing class, or one of its subclasses, and the
|
||||
// accessing class must in turn be a subclass (or package sibling)
|
||||
// of the protected member's defining class.
|
||||
// If the updater refers to a protected field of a declaring class
|
||||
// outside the current package, the receiver argument will be
|
||||
// narrowed to the type of the accessing class.
|
||||
this.cclass = (Modifier.isProtected(modifiers) &&
|
||||
tclass.isAssignableFrom(caller) &&
|
||||
!isSamePackage(tclass, caller))
|
||||
? caller : tclass;
|
||||
this.tclass = tclass;
|
||||
this.vclass = vclass;
|
||||
this.offset = U.objectFieldOffset(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the second classloader can be found in the first
|
||||
* classloader's delegation chain.
|
||||
* Equivalent to the inaccessible: first.isAncestor(second).
|
||||
*/
|
||||
private static boolean isAncestor(ClassLoader first, ClassLoader second) {
|
||||
ClassLoader acl = first;
|
||||
do {
|
||||
acl = acl.getParent();
|
||||
if (second == acl) {
|
||||
return true;
|
||||
}
|
||||
} while (acl != null);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the two classes have the same class loader and
|
||||
* package qualifier
|
||||
*/
|
||||
private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
|
||||
return class1.getClassLoader() == class2.getClassLoader()
|
||||
&& Objects.equals(getPackageName(class1), getPackageName(class2));
|
||||
}
|
||||
|
||||
private static String getPackageName(Class<?> cls) {
|
||||
String cn = cls.getName();
|
||||
int dot = cn.lastIndexOf('.');
|
||||
return (dot != -1) ? cn.substring(0, dot) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that target argument is instance of cclass. On
|
||||
* failure, throws cause.
|
||||
*/
|
||||
private final void accessCheck(T obj) {
|
||||
if (!cclass.isInstance(obj))
|
||||
throwAccessCheckException(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws access exception if accessCheck failed due to
|
||||
* protected access, else ClassCastException.
|
||||
*/
|
||||
private final void throwAccessCheckException(T obj) {
|
||||
if (cclass == tclass)
|
||||
throw new ClassCastException();
|
||||
else
|
||||
throw new RuntimeException(
|
||||
new IllegalAccessException(
|
||||
"Class " +
|
||||
cclass.getName() +
|
||||
" can not access a protected member of class " +
|
||||
tclass.getName() +
|
||||
" using an instance of " +
|
||||
obj.getClass().getName()));
|
||||
}
|
||||
|
||||
private final void valueCheck(V v) {
|
||||
if (v != null && !(vclass.isInstance(v)))
|
||||
throwCCE();
|
||||
}
|
||||
|
||||
static void throwCCE() {
|
||||
throw new ClassCastException();
|
||||
}
|
||||
|
||||
public final boolean compareAndSet(T obj, V expect, V update) {
|
||||
accessCheck(obj);
|
||||
valueCheck(update);
|
||||
return U.compareAndSwapObject(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
public final boolean weakCompareAndSet(T obj, V expect, V update) {
|
||||
// same implementation as strong form for now
|
||||
accessCheck(obj);
|
||||
valueCheck(update);
|
||||
return U.compareAndSwapObject(obj, offset, expect, update);
|
||||
}
|
||||
|
||||
public final void set(T obj, V newValue) {
|
||||
accessCheck(obj);
|
||||
valueCheck(newValue);
|
||||
U.putObjectVolatile(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final void lazySet(T obj, V newValue) {
|
||||
accessCheck(obj);
|
||||
valueCheck(newValue);
|
||||
U.putOrderedObject(obj, offset, newValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final V get(T obj) {
|
||||
accessCheck(obj);
|
||||
return (V)U.getObjectVolatile(obj, offset);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final V getAndSet(T obj, V newValue) {
|
||||
accessCheck(obj);
|
||||
valueCheck(newValue);
|
||||
return (V)U.getAndSetObject(obj, offset, newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
|
||||
/**
|
||||
* An {@code AtomicStampedReference} maintains an object reference
|
||||
* along with an integer "stamp", that can be updated atomically.
|
||||
*
|
||||
* <p>Implementation note: This implementation maintains stamped
|
||||
* references by creating internal objects representing "boxed"
|
||||
* [reference, integer] pairs.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
* @param <V> The type of object referred to by this reference
|
||||
*/
|
||||
public class AtomicStampedReference<V> {
|
||||
|
||||
private static class Pair<T> {
|
||||
final T reference;
|
||||
final int stamp;
|
||||
private Pair(T reference, int stamp) {
|
||||
this.reference = reference;
|
||||
this.stamp = stamp;
|
||||
}
|
||||
static <T> Pair<T> of(T reference, int stamp) {
|
||||
return new Pair<T>(reference, stamp);
|
||||
}
|
||||
}
|
||||
|
||||
private volatile Pair<V> pair;
|
||||
|
||||
/**
|
||||
* Creates a new {@code AtomicStampedReference} with the given
|
||||
* initial values.
|
||||
*
|
||||
* @param initialRef the initial reference
|
||||
* @param initialStamp the initial stamp
|
||||
*/
|
||||
public AtomicStampedReference(V initialRef, int initialStamp) {
|
||||
pair = Pair.of(initialRef, initialStamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value of the reference.
|
||||
*
|
||||
* @return the current value of the reference
|
||||
*/
|
||||
public V getReference() {
|
||||
return pair.reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value of the stamp.
|
||||
*
|
||||
* @return the current value of the stamp
|
||||
*/
|
||||
public int getStamp() {
|
||||
return pair.stamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current values of both the reference and the stamp.
|
||||
* Typical usage is {@code int[1] holder; ref = v.get(holder); }.
|
||||
*
|
||||
* @param stampHolder an array of size of at least one. On return,
|
||||
* {@code stampholder[0]} will hold the value of the stamp.
|
||||
* @return the current value of the reference
|
||||
*/
|
||||
public V get(int[] stampHolder) {
|
||||
Pair<V> pair = this.pair;
|
||||
stampHolder[0] = pair.stamp;
|
||||
return pair.reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value of both the reference and stamp
|
||||
* to the given update values if the
|
||||
* current reference is {@code ==} to the expected reference
|
||||
* and the current stamp is equal to the expected stamp.
|
||||
*
|
||||
* <p><a href="package-summary.html#weakCompareAndSet">May fail
|
||||
* spuriously and does not provide ordering guarantees</a>, so is
|
||||
* only rarely an appropriate alternative to {@code compareAndSet}.
|
||||
*
|
||||
* @param expectedReference the expected value of the reference
|
||||
* @param newReference the new value for the reference
|
||||
* @param expectedStamp the expected value of the stamp
|
||||
* @param newStamp the new value for the stamp
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public boolean weakCompareAndSet(V expectedReference,
|
||||
V newReference,
|
||||
int expectedStamp,
|
||||
int newStamp) {
|
||||
return compareAndSet(expectedReference, newReference,
|
||||
expectedStamp, newStamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value of both the reference and stamp
|
||||
* to the given update values if the
|
||||
* current reference is {@code ==} to the expected reference
|
||||
* and the current stamp is equal to the expected stamp.
|
||||
*
|
||||
* @param expectedReference the expected value of the reference
|
||||
* @param newReference the new value for the reference
|
||||
* @param expectedStamp the expected value of the stamp
|
||||
* @param newStamp the new value for the stamp
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public boolean compareAndSet(V expectedReference,
|
||||
V newReference,
|
||||
int expectedStamp,
|
||||
int newStamp) {
|
||||
Pair<V> current = pair;
|
||||
return
|
||||
expectedReference == current.reference &&
|
||||
expectedStamp == current.stamp &&
|
||||
((newReference == current.reference &&
|
||||
newStamp == current.stamp) ||
|
||||
casPair(current, Pair.of(newReference, newStamp)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally sets the value of both the reference and stamp.
|
||||
*
|
||||
* @param newReference the new value for the reference
|
||||
* @param newStamp the new value for the stamp
|
||||
*/
|
||||
public void set(V newReference, int newStamp) {
|
||||
Pair<V> current = pair;
|
||||
if (newReference != current.reference || newStamp != current.stamp)
|
||||
this.pair = Pair.of(newReference, newStamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically sets the value of the stamp to the given update value
|
||||
* if the current reference is {@code ==} to the expected
|
||||
* reference. Any given invocation of this operation may fail
|
||||
* (return {@code false}) spuriously, but repeated invocation
|
||||
* when the current value holds the expected value and no other
|
||||
* thread is also attempting to set the value will eventually
|
||||
* succeed.
|
||||
*
|
||||
* @param expectedReference the expected value of the reference
|
||||
* @param newStamp the new value for the stamp
|
||||
* @return {@code true} if successful
|
||||
*/
|
||||
public boolean attemptStamp(V expectedReference, int newStamp) {
|
||||
Pair<V> current = pair;
|
||||
return
|
||||
expectedReference == current.reference &&
|
||||
(newStamp == current.stamp ||
|
||||
casPair(current, Pair.of(expectedReference, newStamp)));
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long pairOffset =
|
||||
objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class);
|
||||
|
||||
private boolean casPair(Pair<V> cmp, Pair<V> val) {
|
||||
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
|
||||
}
|
||||
|
||||
static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
|
||||
String field, Class<?> klazz) {
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Convert Exception to corresponding Error
|
||||
NoSuchFieldError error = new NoSuchFieldError(field);
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
294
jdkSrc/jdk8/java/util/concurrent/atomic/DoubleAccumulator.java
Normal file
294
jdkSrc/jdk8/java/util/concurrent/atomic/DoubleAccumulator.java
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.io.Serializable;
|
||||
import java.util.function.DoubleBinaryOperator;
|
||||
|
||||
/**
|
||||
* One or more variables that together maintain a running {@code double}
|
||||
* value updated using a supplied function. When updates (method
|
||||
* {@link #accumulate}) are contended across threads, the set of variables
|
||||
* may grow dynamically to reduce contention. Method {@link #get}
|
||||
* (or, equivalently, {@link #doubleValue}) returns the current value
|
||||
* across the variables maintaining updates.
|
||||
*
|
||||
* <p>This class is usually preferable to alternatives when multiple
|
||||
* threads update a common value that is used for purposes such as
|
||||
* summary statistics that are frequently updated but less frequently
|
||||
* read.
|
||||
*
|
||||
* <p>The supplied accumulator function should be side-effect-free,
|
||||
* since it may be re-applied when attempted updates fail due to
|
||||
* contention among threads. The function is applied with the current
|
||||
* value as its first argument, and the given update as the second
|
||||
* argument. For example, to maintain a running maximum value, you
|
||||
* could supply {@code Double::max} along with {@code
|
||||
* Double.NEGATIVE_INFINITY} as the identity. The order of
|
||||
* accumulation within or across threads is not guaranteed. Thus, this
|
||||
* class may not be applicable if numerical stability is required,
|
||||
* especially when combining values of substantially different orders
|
||||
* of magnitude.
|
||||
*
|
||||
* <p>Class {@link DoubleAdder} provides analogs of the functionality
|
||||
* of this class for the common special case of maintaining sums. The
|
||||
* call {@code new DoubleAdder()} is equivalent to {@code new
|
||||
* DoubleAccumulator((x, y) -> x + y, 0.0)}.
|
||||
*
|
||||
* <p>This class extends {@link Number}, but does <em>not</em> define
|
||||
* methods such as {@code equals}, {@code hashCode} and {@code
|
||||
* compareTo} because instances are expected to be mutated, and so are
|
||||
* not useful as collection keys.
|
||||
*
|
||||
* @since 1.8
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class DoubleAccumulator extends Striped64 implements Serializable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
private final DoubleBinaryOperator function;
|
||||
private final long identity; // use long representation
|
||||
|
||||
/**
|
||||
* Creates a new instance using the given accumulator function
|
||||
* and identity element.
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @param identity identity (initial value) for the accumulator function
|
||||
*/
|
||||
public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
|
||||
double identity) {
|
||||
this.function = accumulatorFunction;
|
||||
base = this.identity = Double.doubleToRawLongBits(identity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates with the given value.
|
||||
*
|
||||
* @param x the value
|
||||
*/
|
||||
public void accumulate(double x) {
|
||||
Cell[] as; long b, v, r; int m; Cell a;
|
||||
if ((as = cells) != null ||
|
||||
(r = Double.doubleToRawLongBits
|
||||
(function.applyAsDouble
|
||||
(Double.longBitsToDouble(b = base), x))) != b && !casBase(b, r)) {
|
||||
boolean uncontended = true;
|
||||
if (as == null || (m = as.length - 1) < 0 ||
|
||||
(a = as[getProbe() & m]) == null ||
|
||||
!(uncontended =
|
||||
(r = Double.doubleToRawLongBits
|
||||
(function.applyAsDouble
|
||||
(Double.longBitsToDouble(v = a.value), x))) == v ||
|
||||
a.cas(v, r)))
|
||||
doubleAccumulate(x, function, uncontended);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value. The returned value is <em>NOT</em>
|
||||
* an atomic snapshot; invocation in the absence of concurrent
|
||||
* updates returns an accurate result, but concurrent updates that
|
||||
* occur while the value is being calculated might not be
|
||||
* incorporated.
|
||||
*
|
||||
* @return the current value
|
||||
*/
|
||||
public double get() {
|
||||
Cell[] as = cells; Cell a;
|
||||
double result = Double.longBitsToDouble(base);
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null)
|
||||
result = function.applyAsDouble
|
||||
(result, Double.longBitsToDouble(a.value));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets variables maintaining updates to the identity value.
|
||||
* This method may be a useful alternative to creating a new
|
||||
* updater, but is only effective if there are no concurrent
|
||||
* updates. Because this method is intrinsically racy, it should
|
||||
* only be used when it is known that no threads are concurrently
|
||||
* updating.
|
||||
*/
|
||||
public void reset() {
|
||||
Cell[] as = cells; Cell a;
|
||||
base = identity;
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null)
|
||||
a.value = identity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent in effect to {@link #get} followed by {@link
|
||||
* #reset}. This method may apply for example during quiescent
|
||||
* points between multithreaded computations. If there are
|
||||
* updates concurrent with this method, the returned value is
|
||||
* <em>not</em> guaranteed to be the final value occurring before
|
||||
* the reset.
|
||||
*
|
||||
* @return the value before reset
|
||||
*/
|
||||
public double getThenReset() {
|
||||
Cell[] as = cells; Cell a;
|
||||
double result = Double.longBitsToDouble(base);
|
||||
base = identity;
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null) {
|
||||
double v = Double.longBitsToDouble(a.value);
|
||||
a.value = identity;
|
||||
result = function.applyAsDouble(result, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the current value.
|
||||
* @return the String representation of the current value
|
||||
*/
|
||||
public String toString() {
|
||||
return Double.toString(get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@link #get}.
|
||||
*
|
||||
* @return the current value
|
||||
*/
|
||||
public double doubleValue() {
|
||||
return get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@linkplain #get current value} as a {@code long}
|
||||
* after a narrowing primitive conversion.
|
||||
*/
|
||||
public long longValue() {
|
||||
return (long)get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@linkplain #get current value} as an {@code int}
|
||||
* after a narrowing primitive conversion.
|
||||
*/
|
||||
public int intValue() {
|
||||
return (int)get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@linkplain #get current value} as a {@code float}
|
||||
* after a narrowing primitive conversion.
|
||||
*/
|
||||
public float floatValue() {
|
||||
return (float)get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialization proxy, used to avoid reference to the non-public
|
||||
* Striped64 superclass in serialized forms.
|
||||
* @serial include
|
||||
*/
|
||||
private static class SerializationProxy implements Serializable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
/**
|
||||
* The current value returned by get().
|
||||
* @serial
|
||||
*/
|
||||
private final double value;
|
||||
/**
|
||||
* The function used for updates.
|
||||
* @serial
|
||||
*/
|
||||
private final DoubleBinaryOperator function;
|
||||
/**
|
||||
* The identity value
|
||||
* @serial
|
||||
*/
|
||||
private final long identity;
|
||||
|
||||
SerializationProxy(DoubleAccumulator a) {
|
||||
function = a.function;
|
||||
identity = a.identity;
|
||||
value = a.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code DoubleAccumulator} object with initial state
|
||||
* held by this proxy.
|
||||
*
|
||||
* @return a {@code DoubleAccumulator} object with initial state
|
||||
* held by this proxy.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
double d = Double.longBitsToDouble(identity);
|
||||
DoubleAccumulator a = new DoubleAccumulator(function, d);
|
||||
a.base = Double.doubleToRawLongBits(value);
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a
|
||||
* <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAccumulator.SerializationProxy">
|
||||
* SerializationProxy</a>
|
||||
* representing the state of this instance.
|
||||
*
|
||||
* @return a {@link SerializationProxy}
|
||||
* representing the state of this instance
|
||||
*/
|
||||
private Object writeReplace() {
|
||||
return new SerializationProxy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s the stream
|
||||
* @throws java.io.InvalidObjectException always
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.InvalidObjectException {
|
||||
throw new java.io.InvalidObjectException("Proxy required");
|
||||
}
|
||||
|
||||
}
|
||||
267
jdkSrc/jdk8/java/util/concurrent/atomic/DoubleAdder.java
Normal file
267
jdkSrc/jdk8/java/util/concurrent/atomic/DoubleAdder.java
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* One or more variables that together maintain an initially zero
|
||||
* {@code double} sum. When updates (method {@link #add}) are
|
||||
* contended across threads, the set of variables may grow dynamically
|
||||
* to reduce contention. Method {@link #sum} (or, equivalently {@link
|
||||
* #doubleValue}) returns the current total combined across the
|
||||
* variables maintaining the sum. The order of accumulation within or
|
||||
* across threads is not guaranteed. Thus, this class may not be
|
||||
* applicable if numerical stability is required, especially when
|
||||
* combining values of substantially different orders of magnitude.
|
||||
*
|
||||
* <p>This class is usually preferable to alternatives when multiple
|
||||
* threads update a common value that is used for purposes such as
|
||||
* summary statistics that are frequently updated but less frequently
|
||||
* read.
|
||||
*
|
||||
* <p>This class extends {@link Number}, but does <em>not</em> define
|
||||
* methods such as {@code equals}, {@code hashCode} and {@code
|
||||
* compareTo} because instances are expected to be mutated, and so are
|
||||
* not useful as collection keys.
|
||||
*
|
||||
* @since 1.8
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class DoubleAdder extends Striped64 implements Serializable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
/*
|
||||
* Note that we must use "long" for underlying representations,
|
||||
* because there is no compareAndSet for double, due to the fact
|
||||
* that the bitwise equals used in any CAS implementation is not
|
||||
* the same as double-precision equals. However, we use CAS only
|
||||
* to detect and alleviate contention, for which bitwise equals
|
||||
* works best anyway. In principle, the long/double conversions
|
||||
* used here should be essentially free on most platforms since
|
||||
* they just re-interpret bits.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new adder with initial sum of zero.
|
||||
*/
|
||||
public DoubleAdder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given value.
|
||||
*
|
||||
* @param x the value to add
|
||||
*/
|
||||
public void add(double x) {
|
||||
Cell[] as; long b, v; int m; Cell a;
|
||||
if ((as = cells) != null ||
|
||||
!casBase(b = base,
|
||||
Double.doubleToRawLongBits
|
||||
(Double.longBitsToDouble(b) + x))) {
|
||||
boolean uncontended = true;
|
||||
if (as == null || (m = as.length - 1) < 0 ||
|
||||
(a = as[getProbe() & m]) == null ||
|
||||
!(uncontended = a.cas(v = a.value,
|
||||
Double.doubleToRawLongBits
|
||||
(Double.longBitsToDouble(v) + x))))
|
||||
doubleAccumulate(x, null, uncontended);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current sum. The returned value is <em>NOT</em> an
|
||||
* atomic snapshot; invocation in the absence of concurrent
|
||||
* updates returns an accurate result, but concurrent updates that
|
||||
* occur while the sum is being calculated might not be
|
||||
* incorporated. Also, because floating-point arithmetic is not
|
||||
* strictly associative, the returned result need not be identical
|
||||
* to the value that would be obtained in a sequential series of
|
||||
* updates to a single variable.
|
||||
*
|
||||
* @return the sum
|
||||
*/
|
||||
public double sum() {
|
||||
Cell[] as = cells; Cell a;
|
||||
double sum = Double.longBitsToDouble(base);
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null)
|
||||
sum += Double.longBitsToDouble(a.value);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets variables maintaining the sum to zero. This method may
|
||||
* be a useful alternative to creating a new adder, but is only
|
||||
* effective if there are no concurrent updates. Because this
|
||||
* method is intrinsically racy, it should only be used when it is
|
||||
* known that no threads are concurrently updating.
|
||||
*/
|
||||
public void reset() {
|
||||
Cell[] as = cells; Cell a;
|
||||
base = 0L; // relies on fact that double 0 must have same rep as long
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null)
|
||||
a.value = 0L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent in effect to {@link #sum} followed by {@link
|
||||
* #reset}. This method may apply for example during quiescent
|
||||
* points between multithreaded computations. If there are
|
||||
* updates concurrent with this method, the returned value is
|
||||
* <em>not</em> guaranteed to be the final value occurring before
|
||||
* the reset.
|
||||
*
|
||||
* @return the sum
|
||||
*/
|
||||
public double sumThenReset() {
|
||||
Cell[] as = cells; Cell a;
|
||||
double sum = Double.longBitsToDouble(base);
|
||||
base = 0L;
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null) {
|
||||
long v = a.value;
|
||||
a.value = 0L;
|
||||
sum += Double.longBitsToDouble(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the {@link #sum}.
|
||||
* @return the String representation of the {@link #sum}
|
||||
*/
|
||||
public String toString() {
|
||||
return Double.toString(sum());
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@link #sum}.
|
||||
*
|
||||
* @return the sum
|
||||
*/
|
||||
public double doubleValue() {
|
||||
return sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link #sum} as a {@code long} after a
|
||||
* narrowing primitive conversion.
|
||||
*/
|
||||
public long longValue() {
|
||||
return (long)sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link #sum} as an {@code int} after a
|
||||
* narrowing primitive conversion.
|
||||
*/
|
||||
public int intValue() {
|
||||
return (int)sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link #sum} as a {@code float}
|
||||
* after a narrowing primitive conversion.
|
||||
*/
|
||||
public float floatValue() {
|
||||
return (float)sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialization proxy, used to avoid reference to the non-public
|
||||
* Striped64 superclass in serialized forms.
|
||||
* @serial include
|
||||
*/
|
||||
private static class SerializationProxy implements Serializable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
/**
|
||||
* The current value returned by sum().
|
||||
* @serial
|
||||
*/
|
||||
private final double value;
|
||||
|
||||
SerializationProxy(DoubleAdder a) {
|
||||
value = a.sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code DoubleAdder} object with initial state
|
||||
* held by this proxy.
|
||||
*
|
||||
* @return a {@code DoubleAdder} object with initial state
|
||||
* held by this proxy.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
DoubleAdder a = new DoubleAdder();
|
||||
a.base = Double.doubleToRawLongBits(value);
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a
|
||||
* <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAdder.SerializationProxy">
|
||||
* SerializationProxy</a>
|
||||
* representing the state of this instance.
|
||||
*
|
||||
* @return a {@link SerializationProxy}
|
||||
* representing the state of this instance
|
||||
*/
|
||||
private Object writeReplace() {
|
||||
return new SerializationProxy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s the stream
|
||||
* @throws java.io.InvalidObjectException always
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.InvalidObjectException {
|
||||
throw new java.io.InvalidObjectException("Proxy required");
|
||||
}
|
||||
|
||||
}
|
||||
290
jdkSrc/jdk8/java/util/concurrent/atomic/LongAccumulator.java
Normal file
290
jdkSrc/jdk8/java/util/concurrent/atomic/LongAccumulator.java
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.io.Serializable;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
|
||||
/**
|
||||
* One or more variables that together maintain a running {@code long}
|
||||
* value updated using a supplied function. When updates (method
|
||||
* {@link #accumulate}) are contended across threads, the set of variables
|
||||
* may grow dynamically to reduce contention. Method {@link #get}
|
||||
* (or, equivalently, {@link #longValue}) returns the current value
|
||||
* across the variables maintaining updates.
|
||||
*
|
||||
* <p>This class is usually preferable to {@link AtomicLong} when
|
||||
* multiple threads update a common value that is used for purposes such
|
||||
* as collecting statistics, not for fine-grained synchronization
|
||||
* control. Under low update contention, the two classes have similar
|
||||
* characteristics. But under high contention, expected throughput of
|
||||
* this class is significantly higher, at the expense of higher space
|
||||
* consumption.
|
||||
*
|
||||
* <p>The order of accumulation within or across threads is not
|
||||
* guaranteed and cannot be depended upon, so this class is only
|
||||
* applicable to functions for which the order of accumulation does
|
||||
* not matter. The supplied accumulator function should be
|
||||
* side-effect-free, since it may be re-applied when attempted updates
|
||||
* fail due to contention among threads. The function is applied with
|
||||
* the current value as its first argument, and the given update as
|
||||
* the second argument. For example, to maintain a running maximum
|
||||
* value, you could supply {@code Long::max} along with {@code
|
||||
* Long.MIN_VALUE} as the identity.
|
||||
*
|
||||
* <p>Class {@link LongAdder} provides analogs of the functionality of
|
||||
* this class for the common special case of maintaining counts and
|
||||
* sums. The call {@code new LongAdder()} is equivalent to {@code new
|
||||
* LongAccumulator((x, y) -> x + y, 0L}.
|
||||
*
|
||||
* <p>This class extends {@link Number}, but does <em>not</em> define
|
||||
* methods such as {@code equals}, {@code hashCode} and {@code
|
||||
* compareTo} because instances are expected to be mutated, and so are
|
||||
* not useful as collection keys.
|
||||
*
|
||||
* @since 1.8
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class LongAccumulator extends Striped64 implements Serializable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
private final LongBinaryOperator function;
|
||||
private final long identity;
|
||||
|
||||
/**
|
||||
* Creates a new instance using the given accumulator function
|
||||
* and identity element.
|
||||
* @param accumulatorFunction a side-effect-free function of two arguments
|
||||
* @param identity identity (initial value) for the accumulator function
|
||||
*/
|
||||
public LongAccumulator(LongBinaryOperator accumulatorFunction,
|
||||
long identity) {
|
||||
this.function = accumulatorFunction;
|
||||
base = this.identity = identity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates with the given value.
|
||||
*
|
||||
* @param x the value
|
||||
*/
|
||||
public void accumulate(long x) {
|
||||
Cell[] as; long b, v, r; int m; Cell a;
|
||||
if ((as = cells) != null ||
|
||||
(r = function.applyAsLong(b = base, x)) != b && !casBase(b, r)) {
|
||||
boolean uncontended = true;
|
||||
if (as == null || (m = as.length - 1) < 0 ||
|
||||
(a = as[getProbe() & m]) == null ||
|
||||
!(uncontended =
|
||||
(r = function.applyAsLong(v = a.value, x)) == v ||
|
||||
a.cas(v, r)))
|
||||
longAccumulate(x, function, uncontended);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value. The returned value is <em>NOT</em>
|
||||
* an atomic snapshot; invocation in the absence of concurrent
|
||||
* updates returns an accurate result, but concurrent updates that
|
||||
* occur while the value is being calculated might not be
|
||||
* incorporated.
|
||||
*
|
||||
* @return the current value
|
||||
*/
|
||||
public long get() {
|
||||
Cell[] as = cells; Cell a;
|
||||
long result = base;
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null)
|
||||
result = function.applyAsLong(result, a.value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets variables maintaining updates to the identity value.
|
||||
* This method may be a useful alternative to creating a new
|
||||
* updater, but is only effective if there are no concurrent
|
||||
* updates. Because this method is intrinsically racy, it should
|
||||
* only be used when it is known that no threads are concurrently
|
||||
* updating.
|
||||
*/
|
||||
public void reset() {
|
||||
Cell[] as = cells; Cell a;
|
||||
base = identity;
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null)
|
||||
a.value = identity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent in effect to {@link #get} followed by {@link
|
||||
* #reset}. This method may apply for example during quiescent
|
||||
* points between multithreaded computations. If there are
|
||||
* updates concurrent with this method, the returned value is
|
||||
* <em>not</em> guaranteed to be the final value occurring before
|
||||
* the reset.
|
||||
*
|
||||
* @return the value before reset
|
||||
*/
|
||||
public long getThenReset() {
|
||||
Cell[] as = cells; Cell a;
|
||||
long result = base;
|
||||
base = identity;
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null) {
|
||||
long v = a.value;
|
||||
a.value = identity;
|
||||
result = function.applyAsLong(result, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the current value.
|
||||
* @return the String representation of the current value
|
||||
*/
|
||||
public String toString() {
|
||||
return Long.toString(get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@link #get}.
|
||||
*
|
||||
* @return the current value
|
||||
*/
|
||||
public long longValue() {
|
||||
return get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@linkplain #get current value} as an {@code int}
|
||||
* after a narrowing primitive conversion.
|
||||
*/
|
||||
public int intValue() {
|
||||
return (int)get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@linkplain #get current value} as a {@code float}
|
||||
* after a widening primitive conversion.
|
||||
*/
|
||||
public float floatValue() {
|
||||
return (float)get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@linkplain #get current value} as a {@code double}
|
||||
* after a widening primitive conversion.
|
||||
*/
|
||||
public double doubleValue() {
|
||||
return (double)get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialization proxy, used to avoid reference to the non-public
|
||||
* Striped64 superclass in serialized forms.
|
||||
* @serial include
|
||||
*/
|
||||
private static class SerializationProxy implements Serializable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
/**
|
||||
* The current value returned by get().
|
||||
* @serial
|
||||
*/
|
||||
private final long value;
|
||||
/**
|
||||
* The function used for updates.
|
||||
* @serial
|
||||
*/
|
||||
private final LongBinaryOperator function;
|
||||
/**
|
||||
* The identity value
|
||||
* @serial
|
||||
*/
|
||||
private final long identity;
|
||||
|
||||
SerializationProxy(LongAccumulator a) {
|
||||
function = a.function;
|
||||
identity = a.identity;
|
||||
value = a.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code LongAccumulator} object with initial state
|
||||
* held by this proxy.
|
||||
*
|
||||
* @return a {@code LongAccumulator} object with initial state
|
||||
* held by this proxy.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
LongAccumulator a = new LongAccumulator(function, identity);
|
||||
a.base = value;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a
|
||||
* <a href="../../../../serialized-form.html#java.util.concurrent.atomic.LongAccumulator.SerializationProxy">
|
||||
* SerializationProxy</a>
|
||||
* representing the state of this instance.
|
||||
*
|
||||
* @return a {@link SerializationProxy}
|
||||
* representing the state of this instance
|
||||
*/
|
||||
private Object writeReplace() {
|
||||
return new SerializationProxy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s the stream
|
||||
* @throws java.io.InvalidObjectException always
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.InvalidObjectException {
|
||||
throw new java.io.InvalidObjectException("Proxy required");
|
||||
}
|
||||
|
||||
}
|
||||
268
jdkSrc/jdk8/java/util/concurrent/atomic/LongAdder.java
Normal file
268
jdkSrc/jdk8/java/util/concurrent/atomic/LongAdder.java
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* One or more variables that together maintain an initially zero
|
||||
* {@code long} sum. When updates (method {@link #add}) are contended
|
||||
* across threads, the set of variables may grow dynamically to reduce
|
||||
* contention. Method {@link #sum} (or, equivalently, {@link
|
||||
* #longValue}) returns the current total combined across the
|
||||
* variables maintaining the sum.
|
||||
*
|
||||
* <p>This class is usually preferable to {@link AtomicLong} when
|
||||
* multiple threads update a common sum that is used for purposes such
|
||||
* as collecting statistics, not for fine-grained synchronization
|
||||
* control. Under low update contention, the two classes have similar
|
||||
* characteristics. But under high contention, expected throughput of
|
||||
* this class is significantly higher, at the expense of higher space
|
||||
* consumption.
|
||||
*
|
||||
* <p>LongAdders can be used with a {@link
|
||||
* java.util.concurrent.ConcurrentHashMap} to maintain a scalable
|
||||
* frequency map (a form of histogram or multiset). For example, to
|
||||
* add a count to a {@code ConcurrentHashMap<String,LongAdder> freqs},
|
||||
* initializing if not already present, you can use {@code
|
||||
* freqs.computeIfAbsent(k -> new LongAdder()).increment();}
|
||||
*
|
||||
* <p>This class extends {@link Number}, but does <em>not</em> define
|
||||
* methods such as {@code equals}, {@code hashCode} and {@code
|
||||
* compareTo} because instances are expected to be mutated, and so are
|
||||
* not useful as collection keys.
|
||||
*
|
||||
* @since 1.8
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class LongAdder extends Striped64 implements Serializable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
/**
|
||||
* Creates a new adder with initial sum of zero.
|
||||
*/
|
||||
public LongAdder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given value.
|
||||
*
|
||||
* @param x the value to add
|
||||
*/
|
||||
public void add(long x) {
|
||||
Cell[] as; long b, v; int m; Cell a;
|
||||
if ((as = cells) != null || !casBase(b = base, b + x)) {
|
||||
boolean uncontended = true;
|
||||
if (as == null || (m = as.length - 1) < 0 ||
|
||||
(a = as[getProbe() & m]) == null ||
|
||||
!(uncontended = a.cas(v = a.value, v + x)))
|
||||
longAccumulate(x, null, uncontended);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@code add(1)}.
|
||||
*/
|
||||
public void increment() {
|
||||
add(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@code add(-1)}.
|
||||
*/
|
||||
public void decrement() {
|
||||
add(-1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current sum. The returned value is <em>NOT</em> an
|
||||
* atomic snapshot; invocation in the absence of concurrent
|
||||
* updates returns an accurate result, but concurrent updates that
|
||||
* occur while the sum is being calculated might not be
|
||||
* incorporated.
|
||||
*
|
||||
* @return the sum
|
||||
*/
|
||||
public long sum() {
|
||||
Cell[] as = cells; Cell a;
|
||||
long sum = base;
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null)
|
||||
sum += a.value;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets variables maintaining the sum to zero. This method may
|
||||
* be a useful alternative to creating a new adder, but is only
|
||||
* effective if there are no concurrent updates. Because this
|
||||
* method is intrinsically racy, it should only be used when it is
|
||||
* known that no threads are concurrently updating.
|
||||
*/
|
||||
public void reset() {
|
||||
Cell[] as = cells; Cell a;
|
||||
base = 0L;
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null)
|
||||
a.value = 0L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent in effect to {@link #sum} followed by {@link
|
||||
* #reset}. This method may apply for example during quiescent
|
||||
* points between multithreaded computations. If there are
|
||||
* updates concurrent with this method, the returned value is
|
||||
* <em>not</em> guaranteed to be the final value occurring before
|
||||
* the reset.
|
||||
*
|
||||
* @return the sum
|
||||
*/
|
||||
public long sumThenReset() {
|
||||
Cell[] as = cells; Cell a;
|
||||
long sum = base;
|
||||
base = 0L;
|
||||
if (as != null) {
|
||||
for (int i = 0; i < as.length; ++i) {
|
||||
if ((a = as[i]) != null) {
|
||||
sum += a.value;
|
||||
a.value = 0L;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the {@link #sum}.
|
||||
* @return the String representation of the {@link #sum}
|
||||
*/
|
||||
public String toString() {
|
||||
return Long.toString(sum());
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@link #sum}.
|
||||
*
|
||||
* @return the sum
|
||||
*/
|
||||
public long longValue() {
|
||||
return sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link #sum} as an {@code int} after a narrowing
|
||||
* primitive conversion.
|
||||
*/
|
||||
public int intValue() {
|
||||
return (int)sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link #sum} as a {@code float}
|
||||
* after a widening primitive conversion.
|
||||
*/
|
||||
public float floatValue() {
|
||||
return (float)sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link #sum} as a {@code double} after a widening
|
||||
* primitive conversion.
|
||||
*/
|
||||
public double doubleValue() {
|
||||
return (double)sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialization proxy, used to avoid reference to the non-public
|
||||
* Striped64 superclass in serialized forms.
|
||||
* @serial include
|
||||
*/
|
||||
private static class SerializationProxy implements Serializable {
|
||||
private static final long serialVersionUID = 7249069246863182397L;
|
||||
|
||||
/**
|
||||
* The current value returned by sum().
|
||||
* @serial
|
||||
*/
|
||||
private final long value;
|
||||
|
||||
SerializationProxy(LongAdder a) {
|
||||
value = a.sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@code LongAdder} object with initial state
|
||||
* held by this proxy.
|
||||
*
|
||||
* @return a {@code LongAdder} object with initial state
|
||||
* held by this proxy.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
LongAdder a = new LongAdder();
|
||||
a.base = value;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a
|
||||
* <a href="../../../../serialized-form.html#java.util.concurrent.atomic.LongAdder.SerializationProxy">
|
||||
* SerializationProxy</a>
|
||||
* representing the state of this instance.
|
||||
*
|
||||
* @return a {@link SerializationProxy}
|
||||
* representing the state of this instance
|
||||
*/
|
||||
private Object writeReplace() {
|
||||
return new SerializationProxy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s the stream
|
||||
* @throws java.io.InvalidObjectException always
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.InvalidObjectException {
|
||||
throw new java.io.InvalidObjectException("Proxy required");
|
||||
}
|
||||
|
||||
}
|
||||
413
jdkSrc/jdk8/java/util/concurrent/atomic/Striped64.java
Normal file
413
jdkSrc/jdk8/java/util/concurrent/atomic/Striped64.java
Normal file
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.atomic;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import java.util.function.DoubleBinaryOperator;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* A package-local class holding common representation and mechanics
|
||||
* for classes supporting dynamic striping on 64bit values. The class
|
||||
* extends Number so that concrete subclasses must publicly do so.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
abstract class Striped64 extends Number {
|
||||
/*
|
||||
* This class maintains a lazily-initialized table of atomically
|
||||
* updated variables, plus an extra "base" field. The table size
|
||||
* is a power of two. Indexing uses masked per-thread hash codes.
|
||||
* Nearly all declarations in this class are package-private,
|
||||
* accessed directly by subclasses.
|
||||
*
|
||||
* Table entries are of class Cell; a variant of AtomicLong padded
|
||||
* (via @sun.misc.Contended) to reduce cache contention. Padding
|
||||
* is overkill for most Atomics because they are usually
|
||||
* irregularly scattered in memory and thus don't interfere much
|
||||
* with each other. But Atomic objects residing in arrays will
|
||||
* tend to be placed adjacent to each other, and so will most
|
||||
* often share cache lines (with a huge negative performance
|
||||
* impact) without this precaution.
|
||||
*
|
||||
* In part because Cells are relatively large, we avoid creating
|
||||
* them until they are needed. When there is no contention, all
|
||||
* updates are made to the base field. Upon first contention (a
|
||||
* failed CAS on base update), the table is initialized to size 2.
|
||||
* The table size is doubled upon further contention until
|
||||
* reaching the nearest power of two greater than or equal to the
|
||||
* number of CPUS. Table slots remain empty (null) until they are
|
||||
* needed.
|
||||
*
|
||||
* A single spinlock ("cellsBusy") is used for initializing and
|
||||
* resizing the table, as well as populating slots with new Cells.
|
||||
* There is no need for a blocking lock; when the lock is not
|
||||
* available, threads try other slots (or the base). During these
|
||||
* retries, there is increased contention and reduced locality,
|
||||
* which is still better than alternatives.
|
||||
*
|
||||
* The Thread probe fields maintained via ThreadLocalRandom serve
|
||||
* as per-thread hash codes. We let them remain uninitialized as
|
||||
* zero (if they come in this way) until they contend at slot
|
||||
* 0. They are then initialized to values that typically do not
|
||||
* often conflict with others. Contention and/or table collisions
|
||||
* are indicated by failed CASes when performing an update
|
||||
* operation. Upon a collision, if the table size is less than
|
||||
* the capacity, it is doubled in size unless some other thread
|
||||
* holds the lock. If a hashed slot is empty, and lock is
|
||||
* available, a new Cell is created. Otherwise, if the slot
|
||||
* exists, a CAS is tried. Retries proceed by "double hashing",
|
||||
* using a secondary hash (Marsaglia XorShift) to try to find a
|
||||
* free slot.
|
||||
*
|
||||
* The table size is capped because, when there are more threads
|
||||
* than CPUs, supposing that each thread were bound to a CPU,
|
||||
* there would exist a perfect hash function mapping threads to
|
||||
* slots that eliminates collisions. When we reach capacity, we
|
||||
* search for this mapping by randomly varying the hash codes of
|
||||
* colliding threads. Because search is random, and collisions
|
||||
* only become known via CAS failures, convergence can be slow,
|
||||
* and because threads are typically not bound to CPUS forever,
|
||||
* may not occur at all. However, despite these limitations,
|
||||
* observed contention rates are typically low in these cases.
|
||||
*
|
||||
* It is possible for a Cell to become unused when threads that
|
||||
* once hashed to it terminate, as well as in the case where
|
||||
* doubling the table causes no thread to hash to it under
|
||||
* expanded mask. We do not try to detect or remove such cells,
|
||||
* under the assumption that for long-running instances, observed
|
||||
* contention levels will recur, so the cells will eventually be
|
||||
* needed again; and for short-lived ones, it does not matter.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Padded variant of AtomicLong supporting only raw accesses plus CAS.
|
||||
*
|
||||
* JVM intrinsics note: It would be possible to use a release-only
|
||||
* form of CAS here, if it were provided.
|
||||
*/
|
||||
@sun.misc.Contended static final class Cell {
|
||||
volatile long value;
|
||||
Cell(long x) { value = x; }
|
||||
final boolean cas(long cmp, long val) {
|
||||
return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long valueOffset;
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class<?> ak = Cell.class;
|
||||
valueOffset = UNSAFE.objectFieldOffset
|
||||
(ak.getDeclaredField("value"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Number of CPUS, to place bound on table size */
|
||||
static final int NCPU = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
/**
|
||||
* Table of cells. When non-null, size is a power of 2.
|
||||
*/
|
||||
transient volatile Cell[] cells;
|
||||
|
||||
/**
|
||||
* Base value, used mainly when there is no contention, but also as
|
||||
* a fallback during table initialization races. Updated via CAS.
|
||||
*/
|
||||
transient volatile long base;
|
||||
|
||||
/**
|
||||
* Spinlock (locked via CAS) used when resizing and/or creating Cells.
|
||||
*/
|
||||
transient volatile int cellsBusy;
|
||||
|
||||
/**
|
||||
* Package-private default constructor
|
||||
*/
|
||||
Striped64() {
|
||||
}
|
||||
|
||||
/**
|
||||
* CASes the base field.
|
||||
*/
|
||||
final boolean casBase(long cmp, long val) {
|
||||
return UNSAFE.compareAndSwapLong(this, BASE, cmp, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* CASes the cellsBusy field from 0 to 1 to acquire lock.
|
||||
*/
|
||||
final boolean casCellsBusy() {
|
||||
return UNSAFE.compareAndSwapInt(this, CELLSBUSY, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the probe value for the current thread.
|
||||
* Duplicated from ThreadLocalRandom because of packaging restrictions.
|
||||
*/
|
||||
static final int getProbe() {
|
||||
return UNSAFE.getInt(Thread.currentThread(), PROBE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pseudo-randomly advances and records the given probe value for the
|
||||
* given thread.
|
||||
* Duplicated from ThreadLocalRandom because of packaging restrictions.
|
||||
*/
|
||||
static final int advanceProbe(int probe) {
|
||||
probe ^= probe << 13; // xorshift
|
||||
probe ^= probe >>> 17;
|
||||
probe ^= probe << 5;
|
||||
UNSAFE.putInt(Thread.currentThread(), PROBE, probe);
|
||||
return probe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles cases of updates involving initialization, resizing,
|
||||
* creating new Cells, and/or contention. See above for
|
||||
* explanation. This method suffers the usual non-modularity
|
||||
* problems of optimistic retry code, relying on rechecked sets of
|
||||
* reads.
|
||||
*
|
||||
* @param x the value
|
||||
* @param fn the update function, or null for add (this convention
|
||||
* avoids the need for an extra field or function in LongAdder).
|
||||
* @param wasUncontended false if CAS failed before call
|
||||
*/
|
||||
final void longAccumulate(long x, LongBinaryOperator fn,
|
||||
boolean wasUncontended) {
|
||||
int h;
|
||||
if ((h = getProbe()) == 0) {
|
||||
ThreadLocalRandom.current(); // force initialization
|
||||
h = getProbe();
|
||||
wasUncontended = true;
|
||||
}
|
||||
boolean collide = false; // True if last slot nonempty
|
||||
for (;;) {
|
||||
Cell[] as; Cell a; int n; long v;
|
||||
if ((as = cells) != null && (n = as.length) > 0) {
|
||||
if ((a = as[(n - 1) & h]) == null) {
|
||||
if (cellsBusy == 0) { // Try to attach new Cell
|
||||
Cell r = new Cell(x); // Optimistically create
|
||||
if (cellsBusy == 0 && casCellsBusy()) {
|
||||
boolean created = false;
|
||||
try { // Recheck under lock
|
||||
Cell[] rs; int m, j;
|
||||
if ((rs = cells) != null &&
|
||||
(m = rs.length) > 0 &&
|
||||
rs[j = (m - 1) & h] == null) {
|
||||
rs[j] = r;
|
||||
created = true;
|
||||
}
|
||||
} finally {
|
||||
cellsBusy = 0;
|
||||
}
|
||||
if (created)
|
||||
break;
|
||||
continue; // Slot is now non-empty
|
||||
}
|
||||
}
|
||||
collide = false;
|
||||
}
|
||||
else if (!wasUncontended) // CAS already known to fail
|
||||
wasUncontended = true; // Continue after rehash
|
||||
else if (a.cas(v = a.value, ((fn == null) ? v + x :
|
||||
fn.applyAsLong(v, x))))
|
||||
break;
|
||||
else if (n >= NCPU || cells != as)
|
||||
collide = false; // At max size or stale
|
||||
else if (!collide)
|
||||
collide = true;
|
||||
else if (cellsBusy == 0 && casCellsBusy()) {
|
||||
try {
|
||||
if (cells == as) { // Expand table unless stale
|
||||
Cell[] rs = new Cell[n << 1];
|
||||
for (int i = 0; i < n; ++i)
|
||||
rs[i] = as[i];
|
||||
cells = rs;
|
||||
}
|
||||
} finally {
|
||||
cellsBusy = 0;
|
||||
}
|
||||
collide = false;
|
||||
continue; // Retry with expanded table
|
||||
}
|
||||
h = advanceProbe(h);
|
||||
}
|
||||
else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
|
||||
boolean init = false;
|
||||
try { // Initialize table
|
||||
if (cells == as) {
|
||||
Cell[] rs = new Cell[2];
|
||||
rs[h & 1] = new Cell(x);
|
||||
cells = rs;
|
||||
init = true;
|
||||
}
|
||||
} finally {
|
||||
cellsBusy = 0;
|
||||
}
|
||||
if (init)
|
||||
break;
|
||||
}
|
||||
else if (casBase(v = base, ((fn == null) ? v + x :
|
||||
fn.applyAsLong(v, x))))
|
||||
break; // Fall back on using base
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as longAccumulate, but injecting long/double conversions
|
||||
* in too many places to sensibly merge with long version, given
|
||||
* the low-overhead requirements of this class. So must instead be
|
||||
* maintained by copy/paste/adapt.
|
||||
*/
|
||||
final void doubleAccumulate(double x, DoubleBinaryOperator fn,
|
||||
boolean wasUncontended) {
|
||||
int h;
|
||||
if ((h = getProbe()) == 0) {
|
||||
ThreadLocalRandom.current(); // force initialization
|
||||
h = getProbe();
|
||||
wasUncontended = true;
|
||||
}
|
||||
boolean collide = false; // True if last slot nonempty
|
||||
for (;;) {
|
||||
Cell[] as; Cell a; int n; long v;
|
||||
if ((as = cells) != null && (n = as.length) > 0) {
|
||||
if ((a = as[(n - 1) & h]) == null) {
|
||||
if (cellsBusy == 0) { // Try to attach new Cell
|
||||
Cell r = new Cell(Double.doubleToRawLongBits(x));
|
||||
if (cellsBusy == 0 && casCellsBusy()) {
|
||||
boolean created = false;
|
||||
try { // Recheck under lock
|
||||
Cell[] rs; int m, j;
|
||||
if ((rs = cells) != null &&
|
||||
(m = rs.length) > 0 &&
|
||||
rs[j = (m - 1) & h] == null) {
|
||||
rs[j] = r;
|
||||
created = true;
|
||||
}
|
||||
} finally {
|
||||
cellsBusy = 0;
|
||||
}
|
||||
if (created)
|
||||
break;
|
||||
continue; // Slot is now non-empty
|
||||
}
|
||||
}
|
||||
collide = false;
|
||||
}
|
||||
else if (!wasUncontended) // CAS already known to fail
|
||||
wasUncontended = true; // Continue after rehash
|
||||
else if (a.cas(v = a.value,
|
||||
((fn == null) ?
|
||||
Double.doubleToRawLongBits
|
||||
(Double.longBitsToDouble(v) + x) :
|
||||
Double.doubleToRawLongBits
|
||||
(fn.applyAsDouble
|
||||
(Double.longBitsToDouble(v), x)))))
|
||||
break;
|
||||
else if (n >= NCPU || cells != as)
|
||||
collide = false; // At max size or stale
|
||||
else if (!collide)
|
||||
collide = true;
|
||||
else if (cellsBusy == 0 && casCellsBusy()) {
|
||||
try {
|
||||
if (cells == as) { // Expand table unless stale
|
||||
Cell[] rs = new Cell[n << 1];
|
||||
for (int i = 0; i < n; ++i)
|
||||
rs[i] = as[i];
|
||||
cells = rs;
|
||||
}
|
||||
} finally {
|
||||
cellsBusy = 0;
|
||||
}
|
||||
collide = false;
|
||||
continue; // Retry with expanded table
|
||||
}
|
||||
h = advanceProbe(h);
|
||||
}
|
||||
else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
|
||||
boolean init = false;
|
||||
try { // Initialize table
|
||||
if (cells == as) {
|
||||
Cell[] rs = new Cell[2];
|
||||
rs[h & 1] = new Cell(Double.doubleToRawLongBits(x));
|
||||
cells = rs;
|
||||
init = true;
|
||||
}
|
||||
} finally {
|
||||
cellsBusy = 0;
|
||||
}
|
||||
if (init)
|
||||
break;
|
||||
}
|
||||
else if (casBase(v = base,
|
||||
((fn == null) ?
|
||||
Double.doubleToRawLongBits
|
||||
(Double.longBitsToDouble(v) + x) :
|
||||
Double.doubleToRawLongBits
|
||||
(fn.applyAsDouble
|
||||
(Double.longBitsToDouble(v), x)))))
|
||||
break; // Fall back on using base
|
||||
}
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long BASE;
|
||||
private static final long CELLSBUSY;
|
||||
private static final long PROBE;
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class<?> sk = Striped64.class;
|
||||
BASE = UNSAFE.objectFieldOffset
|
||||
(sk.getDeclaredField("base"));
|
||||
CELLSBUSY = UNSAFE.objectFieldOffset
|
||||
(sk.getDeclaredField("cellsBusy"));
|
||||
Class<?> tk = Thread.class;
|
||||
PROBE = UNSAFE.objectFieldOffset
|
||||
(tk.getDeclaredField("threadLocalRandomProbe"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
212
jdkSrc/jdk8/java/util/concurrent/atomic/package-info.java
Normal file
212
jdkSrc/jdk8/java/util/concurrent/atomic/package-info.java
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* A small toolkit of classes that support lock-free thread-safe
|
||||
* programming on single variables. In essence, the classes in this
|
||||
* package extend the notion of {@code volatile} values, fields, and
|
||||
* array elements to those that also provide an atomic conditional update
|
||||
* operation of the form:
|
||||
*
|
||||
* <pre> {@code boolean compareAndSet(expectedValue, updateValue);}</pre>
|
||||
*
|
||||
* <p>This method (which varies in argument types across different
|
||||
* classes) atomically sets a variable to the {@code updateValue} if it
|
||||
* currently holds the {@code expectedValue}, reporting {@code true} on
|
||||
* success. The classes in this package also contain methods to get and
|
||||
* unconditionally set values, as well as a weaker conditional atomic
|
||||
* update operation {@code weakCompareAndSet} described below.
|
||||
*
|
||||
* <p>The specifications of these methods enable implementations to
|
||||
* employ efficient machine-level atomic instructions that are available
|
||||
* on contemporary processors. However on some platforms, support may
|
||||
* entail some form of internal locking. Thus the methods are not
|
||||
* strictly guaranteed to be non-blocking --
|
||||
* a thread may block transiently before performing the operation.
|
||||
*
|
||||
* <p>Instances of classes
|
||||
* {@link java.util.concurrent.atomic.AtomicBoolean},
|
||||
* {@link java.util.concurrent.atomic.AtomicInteger},
|
||||
* {@link java.util.concurrent.atomic.AtomicLong}, and
|
||||
* {@link java.util.concurrent.atomic.AtomicReference}
|
||||
* each provide access and updates to a single variable of the
|
||||
* corresponding type. Each class also provides appropriate utility
|
||||
* methods for that type. For example, classes {@code AtomicLong} and
|
||||
* {@code AtomicInteger} provide atomic increment methods. One
|
||||
* application is to generate sequence numbers, as in:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class Sequencer {
|
||||
* private final AtomicLong sequenceNumber
|
||||
* = new AtomicLong(0);
|
||||
* public long next() {
|
||||
* return sequenceNumber.getAndIncrement();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>It is straightforward to define new utility functions that, like
|
||||
* {@code getAndIncrement}, apply a function to a value atomically.
|
||||
* For example, given some transformation
|
||||
* <pre> {@code long transform(long input)}</pre>
|
||||
*
|
||||
* write your utility method as follows:
|
||||
* <pre> {@code
|
||||
* long getAndTransform(AtomicLong var) {
|
||||
* long prev, next;
|
||||
* do {
|
||||
* prev = var.get();
|
||||
* next = transform(prev);
|
||||
* } while (!var.compareAndSet(prev, next));
|
||||
* return prev; // return next; for transformAndGet
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>The memory effects for accesses and updates of atomics generally
|
||||
* follow the rules for volatiles, as stated in
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4">
|
||||
* The Java Language Specification (17.4 Memory Model)</a>:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li> {@code get} has the memory effects of reading a
|
||||
* {@code volatile} variable.
|
||||
*
|
||||
* <li> {@code set} has the memory effects of writing (assigning) a
|
||||
* {@code volatile} variable.
|
||||
*
|
||||
* <li> {@code lazySet} has the memory effects of writing (assigning)
|
||||
* a {@code volatile} variable except that it permits reorderings with
|
||||
* subsequent (but not previous) memory actions that do not themselves
|
||||
* impose reordering constraints with ordinary non-{@code volatile}
|
||||
* writes. Among other usage contexts, {@code lazySet} may apply when
|
||||
* nulling out, for the sake of garbage collection, a reference that is
|
||||
* never accessed again.
|
||||
*
|
||||
* <li>{@code weakCompareAndSet} atomically reads and conditionally
|
||||
* writes a variable but does <em>not</em>
|
||||
* create any happens-before orderings, so provides no guarantees
|
||||
* with respect to previous or subsequent reads and writes of any
|
||||
* variables other than the target of the {@code weakCompareAndSet}.
|
||||
*
|
||||
* <li> {@code compareAndSet}
|
||||
* and all other read-and-update operations such as {@code getAndIncrement}
|
||||
* have the memory effects of both reading and
|
||||
* writing {@code volatile} variables.
|
||||
* </ul>
|
||||
*
|
||||
* <p>In addition to classes representing single values, this package
|
||||
* contains <em>Updater</em> classes that can be used to obtain
|
||||
* {@code compareAndSet} operations on any selected {@code volatile}
|
||||
* field of any selected class.
|
||||
*
|
||||
* {@link java.util.concurrent.atomic.AtomicReferenceFieldUpdater},
|
||||
* {@link java.util.concurrent.atomic.AtomicIntegerFieldUpdater}, and
|
||||
* {@link java.util.concurrent.atomic.AtomicLongFieldUpdater} are
|
||||
* reflection-based utilities that provide access to the associated
|
||||
* field types. These are mainly of use in atomic data structures in
|
||||
* which several {@code volatile} fields of the same node (for
|
||||
* example, the links of a tree node) are independently subject to
|
||||
* atomic updates. These classes enable greater flexibility in how
|
||||
* and when to use atomic updates, at the expense of more awkward
|
||||
* reflection-based setup, less convenient usage, and weaker
|
||||
* guarantees.
|
||||
*
|
||||
* <p>The
|
||||
* {@link java.util.concurrent.atomic.AtomicIntegerArray},
|
||||
* {@link java.util.concurrent.atomic.AtomicLongArray}, and
|
||||
* {@link java.util.concurrent.atomic.AtomicReferenceArray} classes
|
||||
* further extend atomic operation support to arrays of these types.
|
||||
* These classes are also notable in providing {@code volatile} access
|
||||
* semantics for their array elements, which is not supported for
|
||||
* ordinary arrays.
|
||||
*
|
||||
* <p id="weakCompareAndSet">The atomic classes also support method
|
||||
* {@code weakCompareAndSet}, which has limited applicability. On some
|
||||
* platforms, the weak version may be more efficient than {@code
|
||||
* compareAndSet} in the normal case, but differs in that any given
|
||||
* invocation of the {@code weakCompareAndSet} method may return {@code
|
||||
* false} <em>spuriously</em> (that is, for no apparent reason). A
|
||||
* {@code false} return means only that the operation may be retried if
|
||||
* desired, relying on the guarantee that repeated invocation when the
|
||||
* variable holds {@code expectedValue} and no other thread is also
|
||||
* attempting to set the variable will eventually succeed. (Such
|
||||
* spurious failures may for example be due to memory contention effects
|
||||
* that are unrelated to whether the expected and current values are
|
||||
* equal.) Additionally {@code weakCompareAndSet} does not provide
|
||||
* ordering guarantees that are usually needed for synchronization
|
||||
* control. However, the method may be useful for updating counters and
|
||||
* statistics when such updates are unrelated to the other
|
||||
* happens-before orderings of a program. When a thread sees an update
|
||||
* to an atomic variable caused by a {@code weakCompareAndSet}, it does
|
||||
* not necessarily see updates to any <em>other</em> variables that
|
||||
* occurred before the {@code weakCompareAndSet}. This may be
|
||||
* acceptable when, for example, updating performance statistics, but
|
||||
* rarely otherwise.
|
||||
*
|
||||
* <p>The {@link java.util.concurrent.atomic.AtomicMarkableReference}
|
||||
* class associates a single boolean with a reference. For example, this
|
||||
* bit might be used inside a data structure to mean that the object
|
||||
* being referenced has logically been deleted.
|
||||
*
|
||||
* The {@link java.util.concurrent.atomic.AtomicStampedReference}
|
||||
* class associates an integer value with a reference. This may be
|
||||
* used for example, to represent version numbers corresponding to
|
||||
* series of updates.
|
||||
*
|
||||
* <p>Atomic classes are designed primarily as building blocks for
|
||||
* implementing non-blocking data structures and related infrastructure
|
||||
* classes. The {@code compareAndSet} method is not a general
|
||||
* replacement for locking. It applies only when critical updates for an
|
||||
* object are confined to a <em>single</em> variable.
|
||||
*
|
||||
* <p>Atomic classes are not general purpose replacements for
|
||||
* {@code java.lang.Integer} and related classes. They do <em>not</em>
|
||||
* define methods such as {@code equals}, {@code hashCode} and
|
||||
* {@code compareTo}. (Because atomic variables are expected to be
|
||||
* mutated, they are poor choices for hash table keys.) Additionally,
|
||||
* classes are provided only for those types that are commonly useful in
|
||||
* intended applications. For example, there is no atomic class for
|
||||
* representing {@code byte}. In those infrequent cases where you would
|
||||
* like to do so, you can use an {@code AtomicInteger} to hold
|
||||
* {@code byte} values, and cast appropriately.
|
||||
*
|
||||
* You can also hold floats using
|
||||
* {@link java.lang.Float#floatToRawIntBits} and
|
||||
* {@link java.lang.Float#intBitsToFloat} conversions, and doubles using
|
||||
* {@link java.lang.Double#doubleToRawLongBits} and
|
||||
* {@link java.lang.Double#longBitsToDouble} conversions.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
package java.util.concurrent.atomic;
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
|
||||
/**
|
||||
* A synchronizer that may be exclusively owned by a thread. This
|
||||
* class provides a basis for creating locks and related synchronizers
|
||||
* that may entail a notion of ownership. The
|
||||
* {@code AbstractOwnableSynchronizer} class itself does not manage or
|
||||
* use this information. However, subclasses and tools may use
|
||||
* appropriately maintained values to help control and monitor access
|
||||
* and provide diagnostics.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public abstract class AbstractOwnableSynchronizer
|
||||
implements java.io.Serializable {
|
||||
|
||||
/** Use serial ID even though all fields transient. */
|
||||
private static final long serialVersionUID = 3737899427754241961L;
|
||||
|
||||
/**
|
||||
* Empty constructor for use by subclasses.
|
||||
*/
|
||||
protected AbstractOwnableSynchronizer() { }
|
||||
|
||||
/**
|
||||
* The current owner of exclusive mode synchronization.
|
||||
*/
|
||||
private transient Thread exclusiveOwnerThread;
|
||||
|
||||
/**
|
||||
* Sets the thread that currently owns exclusive access.
|
||||
* A {@code null} argument indicates that no thread owns access.
|
||||
* This method does not otherwise impose any synchronization or
|
||||
* {@code volatile} field accesses.
|
||||
* @param thread the owner thread
|
||||
*/
|
||||
protected final void setExclusiveOwnerThread(Thread thread) {
|
||||
exclusiveOwnerThread = thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thread last set by {@code setExclusiveOwnerThread},
|
||||
* or {@code null} if never set. This method does not otherwise
|
||||
* impose any synchronization or {@code volatile} field accesses.
|
||||
* @return the owner thread
|
||||
*/
|
||||
protected final Thread getExclusiveOwnerThread() {
|
||||
return exclusiveOwnerThread;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
487
jdkSrc/jdk8/java/util/concurrent/locks/Condition.java
Normal file
487
jdkSrc/jdk8/java/util/concurrent/locks/Condition.java
Normal file
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* {@code Condition} factors out the {@code Object} monitor
|
||||
* methods ({@link Object#wait() wait}, {@link Object#notify notify}
|
||||
* and {@link Object#notifyAll notifyAll}) into distinct objects to
|
||||
* give the effect of having multiple wait-sets per object, by
|
||||
* combining them with the use of arbitrary {@link Lock} implementations.
|
||||
* Where a {@code Lock} replaces the use of {@code synchronized} methods
|
||||
* and statements, a {@code Condition} replaces the use of the Object
|
||||
* monitor methods.
|
||||
*
|
||||
* <p>Conditions (also known as <em>condition queues</em> or
|
||||
* <em>condition variables</em>) provide a means for one thread to
|
||||
* suspend execution (to "wait") until notified by another
|
||||
* thread that some state condition may now be true. Because access
|
||||
* to this shared state information occurs in different threads, it
|
||||
* must be protected, so a lock of some form is associated with the
|
||||
* condition. The key property that waiting for a condition provides
|
||||
* is that it <em>atomically</em> releases the associated lock and
|
||||
* suspends the current thread, just like {@code Object.wait}.
|
||||
*
|
||||
* <p>A {@code Condition} instance is intrinsically bound to a lock.
|
||||
* To obtain a {@code Condition} instance for a particular {@link Lock}
|
||||
* instance use its {@link Lock#newCondition newCondition()} method.
|
||||
*
|
||||
* <p>As an example, suppose we have a bounded buffer which supports
|
||||
* {@code put} and {@code take} methods. If a
|
||||
* {@code take} is attempted on an empty buffer, then the thread will block
|
||||
* until an item becomes available; if a {@code put} is attempted on a
|
||||
* full buffer, then the thread will block until a space becomes available.
|
||||
* We would like to keep waiting {@code put} threads and {@code take}
|
||||
* threads in separate wait-sets so that we can use the optimization of
|
||||
* only notifying a single thread at a time when items or spaces become
|
||||
* available in the buffer. This can be achieved using two
|
||||
* {@link Condition} instances.
|
||||
* <pre>
|
||||
* class BoundedBuffer {
|
||||
* <b>final Lock lock = new ReentrantLock();</b>
|
||||
* final Condition notFull = <b>lock.newCondition(); </b>
|
||||
* final Condition notEmpty = <b>lock.newCondition(); </b>
|
||||
*
|
||||
* final Object[] items = new Object[100];
|
||||
* int putptr, takeptr, count;
|
||||
*
|
||||
* public void put(Object x) throws InterruptedException {
|
||||
* <b>lock.lock();
|
||||
* try {</b>
|
||||
* while (count == items.length)
|
||||
* <b>notFull.await();</b>
|
||||
* items[putptr] = x;
|
||||
* if (++putptr == items.length) putptr = 0;
|
||||
* ++count;
|
||||
* <b>notEmpty.signal();</b>
|
||||
* <b>} finally {
|
||||
* lock.unlock();
|
||||
* }</b>
|
||||
* }
|
||||
*
|
||||
* public Object take() throws InterruptedException {
|
||||
* <b>lock.lock();
|
||||
* try {</b>
|
||||
* while (count == 0)
|
||||
* <b>notEmpty.await();</b>
|
||||
* Object x = items[takeptr];
|
||||
* if (++takeptr == items.length) takeptr = 0;
|
||||
* --count;
|
||||
* <b>notFull.signal();</b>
|
||||
* return x;
|
||||
* <b>} finally {
|
||||
* lock.unlock();
|
||||
* }</b>
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* (The {@link java.util.concurrent.ArrayBlockingQueue} class provides
|
||||
* this functionality, so there is no reason to implement this
|
||||
* sample usage class.)
|
||||
*
|
||||
* <p>A {@code Condition} implementation can provide behavior and semantics
|
||||
* that is
|
||||
* different from that of the {@code Object} monitor methods, such as
|
||||
* guaranteed ordering for notifications, or not requiring a lock to be held
|
||||
* when performing notifications.
|
||||
* If an implementation provides such specialized semantics then the
|
||||
* implementation must document those semantics.
|
||||
*
|
||||
* <p>Note that {@code Condition} instances are just normal objects and can
|
||||
* themselves be used as the target in a {@code synchronized} statement,
|
||||
* and can have their own monitor {@link Object#wait wait} and
|
||||
* {@link Object#notify notification} methods invoked.
|
||||
* Acquiring the monitor lock of a {@code Condition} instance, or using its
|
||||
* monitor methods, has no specified relationship with acquiring the
|
||||
* {@link Lock} associated with that {@code Condition} or the use of its
|
||||
* {@linkplain #await waiting} and {@linkplain #signal signalling} methods.
|
||||
* It is recommended that to avoid confusion you never use {@code Condition}
|
||||
* instances in this way, except perhaps within their own implementation.
|
||||
*
|
||||
* <p>Except where noted, passing a {@code null} value for any parameter
|
||||
* will result in a {@link NullPointerException} being thrown.
|
||||
*
|
||||
* <h3>Implementation Considerations</h3>
|
||||
*
|
||||
* <p>When waiting upon a {@code Condition}, a "<em>spurious
|
||||
* wakeup</em>" is permitted to occur, in
|
||||
* general, as a concession to the underlying platform semantics.
|
||||
* This has little practical impact on most application programs as a
|
||||
* {@code Condition} should always be waited upon in a loop, testing
|
||||
* the state predicate that is being waited for. An implementation is
|
||||
* free to remove the possibility of spurious wakeups but it is
|
||||
* recommended that applications programmers always assume that they can
|
||||
* occur and so always wait in a loop.
|
||||
*
|
||||
* <p>The three forms of condition waiting
|
||||
* (interruptible, non-interruptible, and timed) may differ in their ease of
|
||||
* implementation on some platforms and in their performance characteristics.
|
||||
* In particular, it may be difficult to provide these features and maintain
|
||||
* specific semantics such as ordering guarantees.
|
||||
* Further, the ability to interrupt the actual suspension of the thread may
|
||||
* not always be feasible to implement on all platforms.
|
||||
*
|
||||
* <p>Consequently, an implementation is not required to define exactly the
|
||||
* same guarantees or semantics for all three forms of waiting, nor is it
|
||||
* required to support interruption of the actual suspension of the thread.
|
||||
*
|
||||
* <p>An implementation is required to
|
||||
* clearly document the semantics and guarantees provided by each of the
|
||||
* waiting methods, and when an implementation does support interruption of
|
||||
* thread suspension then it must obey the interruption semantics as defined
|
||||
* in this interface.
|
||||
*
|
||||
* <p>As interruption generally implies cancellation, and checks for
|
||||
* interruption are often infrequent, an implementation can favor responding
|
||||
* to an interrupt over normal method return. This is true even if it can be
|
||||
* shown that the interrupt occurred after another action that may have
|
||||
* unblocked the thread. An implementation should document this behavior.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface Condition {
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until it is signalled or
|
||||
* {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>The lock associated with this {@code Condition} is atomically
|
||||
* released and the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until <em>one</em> of four things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes the {@link #signal} method for this
|
||||
* {@code Condition} and the current thread happens to be chosen as the
|
||||
* thread to be awakened; or
|
||||
* <li>Some other thread invokes the {@link #signalAll} method for this
|
||||
* {@code Condition}; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread, and interruption of thread suspension is supported; or
|
||||
* <li>A "<em>spurious wakeup</em>" occurs.
|
||||
* </ul>
|
||||
*
|
||||
* <p>In all cases, before this method can return the current thread must
|
||||
* re-acquire the lock associated with this condition. When the
|
||||
* thread returns it is <em>guaranteed</em> to hold this lock.
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* and interruption of thread suspension is supported,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared. It is not specified, in the first
|
||||
* case, whether or not the test for interruption occurs before the lock
|
||||
* is released.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The current thread is assumed to hold the lock associated with this
|
||||
* {@code Condition} when this method is called.
|
||||
* It is up to the implementation to determine if this is
|
||||
* the case and if not, how to respond. Typically, an exception will be
|
||||
* thrown (such as {@link IllegalMonitorStateException}) and the
|
||||
* implementation must document that fact.
|
||||
*
|
||||
* <p>An implementation can favor responding to an interrupt over normal
|
||||
* method return in response to a signal. In that case the implementation
|
||||
* must ensure that the signal is redirected to another waiting thread, if
|
||||
* there is one.
|
||||
*
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* (and interruption of thread suspension is supported)
|
||||
*/
|
||||
void await() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until it is signalled.
|
||||
*
|
||||
* <p>The lock associated with this condition is atomically
|
||||
* released and the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until <em>one</em> of three things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes the {@link #signal} method for this
|
||||
* {@code Condition} and the current thread happens to be chosen as the
|
||||
* thread to be awakened; or
|
||||
* <li>Some other thread invokes the {@link #signalAll} method for this
|
||||
* {@code Condition}; or
|
||||
* <li>A "<em>spurious wakeup</em>" occurs.
|
||||
* </ul>
|
||||
*
|
||||
* <p>In all cases, before this method can return the current thread must
|
||||
* re-acquire the lock associated with this condition. When the
|
||||
* thread returns it is <em>guaranteed</em> to hold this lock.
|
||||
*
|
||||
* <p>If the current thread's interrupted status is set when it enters
|
||||
* this method, or it is {@linkplain Thread#interrupt interrupted}
|
||||
* while waiting, it will continue to wait until signalled. When it finally
|
||||
* returns from this method its interrupted status will still
|
||||
* be set.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The current thread is assumed to hold the lock associated with this
|
||||
* {@code Condition} when this method is called.
|
||||
* It is up to the implementation to determine if this is
|
||||
* the case and if not, how to respond. Typically, an exception will be
|
||||
* thrown (such as {@link IllegalMonitorStateException}) and the
|
||||
* implementation must document that fact.
|
||||
*/
|
||||
void awaitUninterruptibly();
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until it is signalled or interrupted,
|
||||
* or the specified waiting time elapses.
|
||||
*
|
||||
* <p>The lock associated with this condition is atomically
|
||||
* released and the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until <em>one</em> of five things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes the {@link #signal} method for this
|
||||
* {@code Condition} and the current thread happens to be chosen as the
|
||||
* thread to be awakened; or
|
||||
* <li>Some other thread invokes the {@link #signalAll} method for this
|
||||
* {@code Condition}; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread, and interruption of thread suspension is supported; or
|
||||
* <li>The specified waiting time elapses; or
|
||||
* <li>A "<em>spurious wakeup</em>" occurs.
|
||||
* </ul>
|
||||
*
|
||||
* <p>In all cases, before this method can return the current thread must
|
||||
* re-acquire the lock associated with this condition. When the
|
||||
* thread returns it is <em>guaranteed</em> to hold this lock.
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* and interruption of thread suspension is supported,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared. It is not specified, in the first
|
||||
* case, whether or not the test for interruption occurs before the lock
|
||||
* is released.
|
||||
*
|
||||
* <p>The method returns an estimate of the number of nanoseconds
|
||||
* remaining to wait given the supplied {@code nanosTimeout}
|
||||
* value upon return, or a value less than or equal to zero if it
|
||||
* timed out. This value can be used to determine whether and how
|
||||
* long to re-wait in cases where the wait returns but an awaited
|
||||
* condition still does not hold. Typical uses of this method take
|
||||
* the following form:
|
||||
*
|
||||
* <pre> {@code
|
||||
* boolean aMethod(long timeout, TimeUnit unit) {
|
||||
* long nanos = unit.toNanos(timeout);
|
||||
* lock.lock();
|
||||
* try {
|
||||
* while (!conditionBeingWaitedFor()) {
|
||||
* if (nanos <= 0L)
|
||||
* return false;
|
||||
* nanos = theCondition.awaitNanos(nanos);
|
||||
* }
|
||||
* // ...
|
||||
* } finally {
|
||||
* lock.unlock();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>Design note: This method requires a nanosecond argument so
|
||||
* as to avoid truncation errors in reporting remaining times.
|
||||
* Such precision loss would make it difficult for programmers to
|
||||
* ensure that total waiting times are not systematically shorter
|
||||
* than specified when re-waits occur.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The current thread is assumed to hold the lock associated with this
|
||||
* {@code Condition} when this method is called.
|
||||
* It is up to the implementation to determine if this is
|
||||
* the case and if not, how to respond. Typically, an exception will be
|
||||
* thrown (such as {@link IllegalMonitorStateException}) and the
|
||||
* implementation must document that fact.
|
||||
*
|
||||
* <p>An implementation can favor responding to an interrupt over normal
|
||||
* method return in response to a signal, or over indicating the elapse
|
||||
* of the specified waiting time. In either case the implementation
|
||||
* must ensure that the signal is redirected to another waiting thread, if
|
||||
* there is one.
|
||||
*
|
||||
* @param nanosTimeout the maximum time to wait, in nanoseconds
|
||||
* @return an estimate of the {@code nanosTimeout} value minus
|
||||
* the time spent waiting upon return from this method.
|
||||
* A positive value may be used as the argument to a
|
||||
* subsequent call to this method to finish waiting out
|
||||
* the desired time. A value less than or equal to zero
|
||||
* indicates that no time remains.
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* (and interruption of thread suspension is supported)
|
||||
*/
|
||||
long awaitNanos(long nanosTimeout) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until it is signalled or interrupted,
|
||||
* or the specified waiting time elapses. This method is behaviorally
|
||||
* equivalent to:
|
||||
* <pre> {@code awaitNanos(unit.toNanos(time)) > 0}</pre>
|
||||
*
|
||||
* @param time the maximum time to wait
|
||||
* @param unit the time unit of the {@code time} argument
|
||||
* @return {@code false} if the waiting time detectably elapsed
|
||||
* before return from the method, else {@code true}
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* (and interruption of thread suspension is supported)
|
||||
*/
|
||||
boolean await(long time, TimeUnit unit) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Causes the current thread to wait until it is signalled or interrupted,
|
||||
* or the specified deadline elapses.
|
||||
*
|
||||
* <p>The lock associated with this condition is atomically
|
||||
* released and the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until <em>one</em> of five things happens:
|
||||
* <ul>
|
||||
* <li>Some other thread invokes the {@link #signal} method for this
|
||||
* {@code Condition} and the current thread happens to be chosen as the
|
||||
* thread to be awakened; or
|
||||
* <li>Some other thread invokes the {@link #signalAll} method for this
|
||||
* {@code Condition}; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread, and interruption of thread suspension is supported; or
|
||||
* <li>The specified deadline elapses; or
|
||||
* <li>A "<em>spurious wakeup</em>" occurs.
|
||||
* </ul>
|
||||
*
|
||||
* <p>In all cases, before this method can return the current thread must
|
||||
* re-acquire the lock associated with this condition. When the
|
||||
* thread returns it is <em>guaranteed</em> to hold this lock.
|
||||
*
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
|
||||
* and interruption of thread suspension is supported,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared. It is not specified, in the first
|
||||
* case, whether or not the test for interruption occurs before the lock
|
||||
* is released.
|
||||
*
|
||||
*
|
||||
* <p>The return value indicates whether the deadline has elapsed,
|
||||
* which can be used as follows:
|
||||
* <pre> {@code
|
||||
* boolean aMethod(Date deadline) {
|
||||
* boolean stillWaiting = true;
|
||||
* lock.lock();
|
||||
* try {
|
||||
* while (!conditionBeingWaitedFor()) {
|
||||
* if (!stillWaiting)
|
||||
* return false;
|
||||
* stillWaiting = theCondition.awaitUntil(deadline);
|
||||
* }
|
||||
* // ...
|
||||
* } finally {
|
||||
* lock.unlock();
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The current thread is assumed to hold the lock associated with this
|
||||
* {@code Condition} when this method is called.
|
||||
* It is up to the implementation to determine if this is
|
||||
* the case and if not, how to respond. Typically, an exception will be
|
||||
* thrown (such as {@link IllegalMonitorStateException}) and the
|
||||
* implementation must document that fact.
|
||||
*
|
||||
* <p>An implementation can favor responding to an interrupt over normal
|
||||
* method return in response to a signal, or over indicating the passing
|
||||
* of the specified deadline. In either case the implementation
|
||||
* must ensure that the signal is redirected to another waiting thread, if
|
||||
* there is one.
|
||||
*
|
||||
* @param deadline the absolute time to wait until
|
||||
* @return {@code false} if the deadline has elapsed upon return, else
|
||||
* {@code true}
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* (and interruption of thread suspension is supported)
|
||||
*/
|
||||
boolean awaitUntil(Date deadline) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Wakes up one waiting thread.
|
||||
*
|
||||
* <p>If any threads are waiting on this condition then one
|
||||
* is selected for waking up. That thread must then re-acquire the
|
||||
* lock before returning from {@code await}.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>An implementation may (and typically does) require that the
|
||||
* current thread hold the lock associated with this {@code
|
||||
* Condition} when this method is called. Implementations must
|
||||
* document this precondition and any actions taken if the lock is
|
||||
* not held. Typically, an exception such as {@link
|
||||
* IllegalMonitorStateException} will be thrown.
|
||||
*/
|
||||
void signal();
|
||||
|
||||
/**
|
||||
* Wakes up all waiting threads.
|
||||
*
|
||||
* <p>If any threads are waiting on this condition then they are
|
||||
* all woken up. Each thread must re-acquire the lock before it can
|
||||
* return from {@code await}.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>An implementation may (and typically does) require that the
|
||||
* current thread hold the lock associated with this {@code
|
||||
* Condition} when this method is called. Implementations must
|
||||
* document this precondition and any actions taken if the lock is
|
||||
* not held. Typically, an exception such as {@link
|
||||
* IllegalMonitorStateException} will be thrown.
|
||||
*/
|
||||
void signalAll();
|
||||
}
|
||||
357
jdkSrc/jdk8/java/util/concurrent/locks/Lock.java
Normal file
357
jdkSrc/jdk8/java/util/concurrent/locks/Lock.java
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* {@code Lock} implementations provide more extensive locking
|
||||
* operations than can be obtained using {@code synchronized} methods
|
||||
* and statements. They allow more flexible structuring, may have
|
||||
* quite different properties, and may support multiple associated
|
||||
* {@link Condition} objects.
|
||||
*
|
||||
* <p>A lock is a tool for controlling access to a shared resource by
|
||||
* multiple threads. Commonly, a lock provides exclusive access to a
|
||||
* shared resource: only one thread at a time can acquire the lock and
|
||||
* all access to the shared resource requires that the lock be
|
||||
* acquired first. However, some locks may allow concurrent access to
|
||||
* a shared resource, such as the read lock of a {@link ReadWriteLock}.
|
||||
*
|
||||
* <p>The use of {@code synchronized} methods or statements provides
|
||||
* access to the implicit monitor lock associated with every object, but
|
||||
* forces all lock acquisition and release to occur in a block-structured way:
|
||||
* when multiple locks are acquired they must be released in the opposite
|
||||
* order, and all locks must be released in the same lexical scope in which
|
||||
* they were acquired.
|
||||
*
|
||||
* <p>While the scoping mechanism for {@code synchronized} methods
|
||||
* and statements makes it much easier to program with monitor locks,
|
||||
* and helps avoid many common programming errors involving locks,
|
||||
* there are occasions where you need to work with locks in a more
|
||||
* flexible way. For example, some algorithms for traversing
|
||||
* concurrently accessed data structures require the use of
|
||||
* "hand-over-hand" or "chain locking": you
|
||||
* acquire the lock of node A, then node B, then release A and acquire
|
||||
* C, then release B and acquire D and so on. Implementations of the
|
||||
* {@code Lock} interface enable the use of such techniques by
|
||||
* allowing a lock to be acquired and released in different scopes,
|
||||
* and allowing multiple locks to be acquired and released in any
|
||||
* order.
|
||||
*
|
||||
* <p>With this increased flexibility comes additional
|
||||
* responsibility. The absence of block-structured locking removes the
|
||||
* automatic release of locks that occurs with {@code synchronized}
|
||||
* methods and statements. In most cases, the following idiom
|
||||
* should be used:
|
||||
*
|
||||
* <pre> {@code
|
||||
* Lock l = ...;
|
||||
* l.lock();
|
||||
* try {
|
||||
* // access the resource protected by this lock
|
||||
* } finally {
|
||||
* l.unlock();
|
||||
* }}</pre>
|
||||
*
|
||||
* When locking and unlocking occur in different scopes, care must be
|
||||
* taken to ensure that all code that is executed while the lock is
|
||||
* held is protected by try-finally or try-catch to ensure that the
|
||||
* lock is released when necessary.
|
||||
*
|
||||
* <p>{@code Lock} implementations provide additional functionality
|
||||
* over the use of {@code synchronized} methods and statements by
|
||||
* providing a non-blocking attempt to acquire a lock ({@link
|
||||
* #tryLock()}), an attempt to acquire the lock that can be
|
||||
* interrupted ({@link #lockInterruptibly}, and an attempt to acquire
|
||||
* the lock that can timeout ({@link #tryLock(long, TimeUnit)}).
|
||||
*
|
||||
* <p>A {@code Lock} class can also provide behavior and semantics
|
||||
* that is quite different from that of the implicit monitor lock,
|
||||
* such as guaranteed ordering, non-reentrant usage, or deadlock
|
||||
* detection. If an implementation provides such specialized semantics
|
||||
* then the implementation must document those semantics.
|
||||
*
|
||||
* <p>Note that {@code Lock} instances are just normal objects and can
|
||||
* themselves be used as the target in a {@code synchronized} statement.
|
||||
* Acquiring the
|
||||
* monitor lock of a {@code Lock} instance has no specified relationship
|
||||
* with invoking any of the {@link #lock} methods of that instance.
|
||||
* It is recommended that to avoid confusion you never use {@code Lock}
|
||||
* instances in this way, except within their own implementation.
|
||||
*
|
||||
* <p>Except where noted, passing a {@code null} value for any
|
||||
* parameter will result in a {@link NullPointerException} being
|
||||
* thrown.
|
||||
*
|
||||
* <h3>Memory Synchronization</h3>
|
||||
*
|
||||
* <p>All {@code Lock} implementations <em>must</em> enforce the same
|
||||
* memory synchronization semantics as provided by the built-in monitor
|
||||
* lock, as described in
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4">
|
||||
* The Java Language Specification (17.4 Memory Model)</a>:
|
||||
* <ul>
|
||||
* <li>A successful {@code lock} operation has the same memory
|
||||
* synchronization effects as a successful <em>Lock</em> action.
|
||||
* <li>A successful {@code unlock} operation has the same
|
||||
* memory synchronization effects as a successful <em>Unlock</em> action.
|
||||
* </ul>
|
||||
*
|
||||
* Unsuccessful locking and unlocking operations, and reentrant
|
||||
* locking/unlocking operations, do not require any memory
|
||||
* synchronization effects.
|
||||
*
|
||||
* <h3>Implementation Considerations</h3>
|
||||
*
|
||||
* <p>The three forms of lock acquisition (interruptible,
|
||||
* non-interruptible, and timed) may differ in their performance
|
||||
* characteristics, ordering guarantees, or other implementation
|
||||
* qualities. Further, the ability to interrupt the <em>ongoing</em>
|
||||
* acquisition of a lock may not be available in a given {@code Lock}
|
||||
* class. Consequently, an implementation is not required to define
|
||||
* exactly the same guarantees or semantics for all three forms of
|
||||
* lock acquisition, nor is it required to support interruption of an
|
||||
* ongoing lock acquisition. An implementation is required to clearly
|
||||
* document the semantics and guarantees provided by each of the
|
||||
* locking methods. It must also obey the interruption semantics as
|
||||
* defined in this interface, to the extent that interruption of lock
|
||||
* acquisition is supported: which is either totally, or only on
|
||||
* method entry.
|
||||
*
|
||||
* <p>As interruption generally implies cancellation, and checks for
|
||||
* interruption are often infrequent, an implementation can favor responding
|
||||
* to an interrupt over normal method return. This is true even if it can be
|
||||
* shown that the interrupt occurred after another action may have unblocked
|
||||
* the thread. An implementation should document this behavior.
|
||||
*
|
||||
* @see ReentrantLock
|
||||
* @see Condition
|
||||
* @see ReadWriteLock
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface Lock {
|
||||
|
||||
/**
|
||||
* Acquires the lock.
|
||||
*
|
||||
* <p>If the lock is not available then the current thread becomes
|
||||
* disabled for thread scheduling purposes and lies dormant until the
|
||||
* lock has been acquired.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>A {@code Lock} implementation may be able to detect erroneous use
|
||||
* of the lock, such as an invocation that would cause deadlock, and
|
||||
* may throw an (unchecked) exception in such circumstances. The
|
||||
* circumstances and the exception type must be documented by that
|
||||
* {@code Lock} implementation.
|
||||
*/
|
||||
void lock();
|
||||
|
||||
/**
|
||||
* Acquires the lock unless the current thread is
|
||||
* {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>Acquires the lock if it is available and returns immediately.
|
||||
*
|
||||
* <p>If the lock is not available then the current thread becomes
|
||||
* disabled for thread scheduling purposes and lies dormant until
|
||||
* one of two things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>The lock is acquired by the current thread; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread, and interruption of lock acquisition is supported.
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while acquiring the
|
||||
* lock, and interruption of lock acquisition is supported,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The ability to interrupt a lock acquisition in some
|
||||
* implementations may not be possible, and if possible may be an
|
||||
* expensive operation. The programmer should be aware that this
|
||||
* may be the case. An implementation should document when this is
|
||||
* the case.
|
||||
*
|
||||
* <p>An implementation can favor responding to an interrupt over
|
||||
* normal method return.
|
||||
*
|
||||
* <p>A {@code Lock} implementation may be able to detect
|
||||
* erroneous use of the lock, such as an invocation that would
|
||||
* cause deadlock, and may throw an (unchecked) exception in such
|
||||
* circumstances. The circumstances and the exception type must
|
||||
* be documented by that {@code Lock} implementation.
|
||||
*
|
||||
* @throws InterruptedException if the current thread is
|
||||
* interrupted while acquiring the lock (and interruption
|
||||
* of lock acquisition is supported)
|
||||
*/
|
||||
void lockInterruptibly() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Acquires the lock only if it is free at the time of invocation.
|
||||
*
|
||||
* <p>Acquires the lock if it is available and returns immediately
|
||||
* with the value {@code true}.
|
||||
* If the lock is not available then this method will return
|
||||
* immediately with the value {@code false}.
|
||||
*
|
||||
* <p>A typical usage idiom for this method would be:
|
||||
* <pre> {@code
|
||||
* Lock lock = ...;
|
||||
* if (lock.tryLock()) {
|
||||
* try {
|
||||
* // manipulate protected state
|
||||
* } finally {
|
||||
* lock.unlock();
|
||||
* }
|
||||
* } else {
|
||||
* // perform alternative actions
|
||||
* }}</pre>
|
||||
*
|
||||
* This usage ensures that the lock is unlocked if it was acquired, and
|
||||
* doesn't try to unlock if the lock was not acquired.
|
||||
*
|
||||
* @return {@code true} if the lock was acquired and
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
boolean tryLock();
|
||||
|
||||
/**
|
||||
* Acquires the lock if it is free within the given waiting time and the
|
||||
* current thread has not been {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>If the lock is available this method returns immediately
|
||||
* with the value {@code true}.
|
||||
* If the lock is not available then
|
||||
* the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until one of three things happens:
|
||||
* <ul>
|
||||
* <li>The lock is acquired by the current thread; or
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread, and interruption of lock acquisition is supported; or
|
||||
* <li>The specified waiting time elapses
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the lock is acquired then the value {@code true} is returned.
|
||||
*
|
||||
* <p>If the current thread:
|
||||
* <ul>
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while acquiring
|
||||
* the lock, and interruption of lock acquisition is supported,
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* <p>If the specified waiting time elapses then the value {@code false}
|
||||
* is returned.
|
||||
* If the time is
|
||||
* less than or equal to zero, the method will not wait at all.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The ability to interrupt a lock acquisition in some implementations
|
||||
* may not be possible, and if possible may
|
||||
* be an expensive operation.
|
||||
* The programmer should be aware that this may be the case. An
|
||||
* implementation should document when this is the case.
|
||||
*
|
||||
* <p>An implementation can favor responding to an interrupt over normal
|
||||
* method return, or reporting a timeout.
|
||||
*
|
||||
* <p>A {@code Lock} implementation may be able to detect
|
||||
* erroneous use of the lock, such as an invocation that would cause
|
||||
* deadlock, and may throw an (unchecked) exception in such circumstances.
|
||||
* The circumstances and the exception type must be documented by that
|
||||
* {@code Lock} implementation.
|
||||
*
|
||||
* @param time the maximum time to wait for the lock
|
||||
* @param unit the time unit of the {@code time} argument
|
||||
* @return {@code true} if the lock was acquired and {@code false}
|
||||
* if the waiting time elapsed before the lock was acquired
|
||||
*
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* while acquiring the lock (and interruption of lock
|
||||
* acquisition is supported)
|
||||
*/
|
||||
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Releases the lock.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>A {@code Lock} implementation will usually impose
|
||||
* restrictions on which thread can release a lock (typically only the
|
||||
* holder of the lock can release it) and may throw
|
||||
* an (unchecked) exception if the restriction is violated.
|
||||
* Any restrictions and the exception
|
||||
* type must be documented by that {@code Lock} implementation.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
/**
|
||||
* Returns a new {@link Condition} instance that is bound to this
|
||||
* {@code Lock} instance.
|
||||
*
|
||||
* <p>Before waiting on the condition the lock must be held by the
|
||||
* current thread.
|
||||
* A call to {@link Condition#await()} will atomically release the lock
|
||||
* before waiting and re-acquire the lock before the wait returns.
|
||||
*
|
||||
* <p><b>Implementation Considerations</b>
|
||||
*
|
||||
* <p>The exact operation of the {@link Condition} instance depends on
|
||||
* the {@code Lock} implementation and must be documented by that
|
||||
* implementation.
|
||||
*
|
||||
* @return A new {@link Condition} instance for this {@code Lock} instance
|
||||
* @throws UnsupportedOperationException if this {@code Lock}
|
||||
* implementation does not support conditions
|
||||
*/
|
||||
Condition newCondition();
|
||||
}
|
||||
414
jdkSrc/jdk8/java/util/concurrent/locks/LockSupport.java
Normal file
414
jdkSrc/jdk8/java/util/concurrent/locks/LockSupport.java
Normal file
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* Basic thread blocking primitives for creating locks and other
|
||||
* synchronization classes.
|
||||
*
|
||||
* <p>This class associates, with each thread that uses it, a permit
|
||||
* (in the sense of the {@link java.util.concurrent.Semaphore
|
||||
* Semaphore} class). A call to {@code park} will return immediately
|
||||
* if the permit is available, consuming it in the process; otherwise
|
||||
* it <em>may</em> block. A call to {@code unpark} makes the permit
|
||||
* available, if it was not already available. (Unlike with Semaphores
|
||||
* though, permits do not accumulate. There is at most one.)
|
||||
*
|
||||
* <p>Methods {@code park} and {@code unpark} provide efficient
|
||||
* means of blocking and unblocking threads that do not encounter the
|
||||
* problems that cause the deprecated methods {@code Thread.suspend}
|
||||
* and {@code Thread.resume} to be unusable for such purposes: Races
|
||||
* between one thread invoking {@code park} and another thread trying
|
||||
* to {@code unpark} it will preserve liveness, due to the
|
||||
* permit. Additionally, {@code park} will return if the caller's
|
||||
* thread was interrupted, and timeout versions are supported. The
|
||||
* {@code park} method may also return at any other time, for "no
|
||||
* reason", so in general must be invoked within a loop that rechecks
|
||||
* conditions upon return. In this sense {@code park} serves as an
|
||||
* optimization of a "busy wait" that does not waste as much time
|
||||
* spinning, but must be paired with an {@code unpark} to be
|
||||
* effective.
|
||||
*
|
||||
* <p>The three forms of {@code park} each also support a
|
||||
* {@code blocker} object parameter. This object is recorded while
|
||||
* the thread is blocked to permit monitoring and diagnostic tools to
|
||||
* identify the reasons that threads are blocked. (Such tools may
|
||||
* access blockers using method {@link #getBlocker(Thread)}.)
|
||||
* The use of these forms rather than the original forms without this
|
||||
* parameter is strongly encouraged. The normal argument to supply as
|
||||
* a {@code blocker} within a lock implementation is {@code this}.
|
||||
*
|
||||
* <p>These methods are designed to be used as tools for creating
|
||||
* higher-level synchronization utilities, and are not in themselves
|
||||
* useful for most concurrency control applications. The {@code park}
|
||||
* method is designed for use only in constructions of the form:
|
||||
*
|
||||
* <pre> {@code
|
||||
* while (!canProceed()) { ... LockSupport.park(this); }}</pre>
|
||||
*
|
||||
* where neither {@code canProceed} nor any other actions prior to the
|
||||
* call to {@code park} entail locking or blocking. Because only one
|
||||
* permit is associated with each thread, any intermediary uses of
|
||||
* {@code park} could interfere with its intended effects.
|
||||
*
|
||||
* <p><b>Sample Usage.</b> Here is a sketch of a first-in-first-out
|
||||
* non-reentrant lock class:
|
||||
* <pre> {@code
|
||||
* class FIFOMutex {
|
||||
* private final AtomicBoolean locked = new AtomicBoolean(false);
|
||||
* private final Queue<Thread> waiters
|
||||
* = new ConcurrentLinkedQueue<Thread>();
|
||||
*
|
||||
* public void lock() {
|
||||
* boolean wasInterrupted = false;
|
||||
* Thread current = Thread.currentThread();
|
||||
* waiters.add(current);
|
||||
*
|
||||
* // Block while not first in queue or cannot acquire lock
|
||||
* while (waiters.peek() != current ||
|
||||
* !locked.compareAndSet(false, true)) {
|
||||
* LockSupport.park(this);
|
||||
* if (Thread.interrupted()) // ignore interrupts while waiting
|
||||
* wasInterrupted = true;
|
||||
* }
|
||||
*
|
||||
* waiters.remove();
|
||||
* if (wasInterrupted) // reassert interrupt status on exit
|
||||
* current.interrupt();
|
||||
* }
|
||||
*
|
||||
* public void unlock() {
|
||||
* locked.set(false);
|
||||
* LockSupport.unpark(waiters.peek());
|
||||
* }
|
||||
* }}</pre>
|
||||
*/
|
||||
public class LockSupport {
|
||||
private LockSupport() {} // Cannot be instantiated.
|
||||
|
||||
private static void setBlocker(Thread t, Object arg) {
|
||||
// Even though volatile, hotspot doesn't need a write barrier here.
|
||||
UNSAFE.putObject(t, parkBlockerOffset, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes available the permit for the given thread, if it
|
||||
* was not already available. If the thread was blocked on
|
||||
* {@code park} then it will unblock. Otherwise, its next call
|
||||
* to {@code park} is guaranteed not to block. This operation
|
||||
* is not guaranteed to have any effect at all if the given
|
||||
* thread has not been started.
|
||||
*
|
||||
* @param thread the thread to unpark, or {@code null}, in which case
|
||||
* this operation has no effect
|
||||
*/
|
||||
public static void unpark(Thread thread) {
|
||||
if (thread != null)
|
||||
UNSAFE.unpark(thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes unless the
|
||||
* permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call returns
|
||||
* immediately; otherwise
|
||||
* the current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until one of three things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread upon return.
|
||||
*
|
||||
* @param blocker the synchronization object responsible for this
|
||||
* thread parking
|
||||
* @since 1.6
|
||||
*/
|
||||
public static void park(Object blocker) {
|
||||
Thread t = Thread.currentThread();
|
||||
setBlocker(t, blocker);
|
||||
UNSAFE.park(false, 0L);
|
||||
setBlocker(t, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes, for up to
|
||||
* the specified waiting time, unless the permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call
|
||||
* returns immediately; otherwise the current thread becomes disabled
|
||||
* for thread scheduling purposes and lies dormant until one of four
|
||||
* things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The specified waiting time elapses; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread, or the elapsed time
|
||||
* upon return.
|
||||
*
|
||||
* @param blocker the synchronization object responsible for this
|
||||
* thread parking
|
||||
* @param nanos the maximum number of nanoseconds to wait
|
||||
* @since 1.6
|
||||
*/
|
||||
public static void parkNanos(Object blocker, long nanos) {
|
||||
if (nanos > 0) {
|
||||
Thread t = Thread.currentThread();
|
||||
setBlocker(t, blocker);
|
||||
UNSAFE.park(false, nanos);
|
||||
setBlocker(t, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes, until
|
||||
* the specified deadline, unless the permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call
|
||||
* returns immediately; otherwise the current thread becomes disabled
|
||||
* for thread scheduling purposes and lies dormant until one of four
|
||||
* things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread; or
|
||||
*
|
||||
* <li>The specified deadline passes; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread, or the current time
|
||||
* upon return.
|
||||
*
|
||||
* @param blocker the synchronization object responsible for this
|
||||
* thread parking
|
||||
* @param deadline the absolute time, in milliseconds from the Epoch,
|
||||
* to wait until
|
||||
* @since 1.6
|
||||
*/
|
||||
public static void parkUntil(Object blocker, long deadline) {
|
||||
Thread t = Thread.currentThread();
|
||||
setBlocker(t, blocker);
|
||||
UNSAFE.park(true, deadline);
|
||||
setBlocker(t, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blocker object supplied to the most recent
|
||||
* invocation of a park method that has not yet unblocked, or null
|
||||
* if not blocked. The value returned is just a momentary
|
||||
* snapshot -- the thread may have since unblocked or blocked on a
|
||||
* different blocker object.
|
||||
*
|
||||
* @param t the thread
|
||||
* @return the blocker
|
||||
* @throws NullPointerException if argument is null
|
||||
* @since 1.6
|
||||
*/
|
||||
public static Object getBlocker(Thread t) {
|
||||
if (t == null)
|
||||
throw new NullPointerException();
|
||||
return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes unless the
|
||||
* permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call
|
||||
* returns immediately; otherwise the current thread becomes disabled
|
||||
* for thread scheduling purposes and lies dormant until one of three
|
||||
* things happens:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread upon return.
|
||||
*/
|
||||
public static void park() {
|
||||
UNSAFE.park(false, 0L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes, for up to
|
||||
* the specified waiting time, unless the permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call
|
||||
* returns immediately; otherwise the current thread becomes disabled
|
||||
* for thread scheduling purposes and lies dormant until one of four
|
||||
* things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The specified waiting time elapses; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread, or the elapsed time
|
||||
* upon return.
|
||||
*
|
||||
* @param nanos the maximum number of nanoseconds to wait
|
||||
*/
|
||||
public static void parkNanos(long nanos) {
|
||||
if (nanos > 0)
|
||||
UNSAFE.park(false, nanos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the current thread for thread scheduling purposes, until
|
||||
* the specified deadline, unless the permit is available.
|
||||
*
|
||||
* <p>If the permit is available then it is consumed and the call
|
||||
* returns immediately; otherwise the current thread becomes disabled
|
||||
* for thread scheduling purposes and lies dormant until one of four
|
||||
* things happens:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Some other thread invokes {@link #unpark unpark} with the
|
||||
* current thread as the target; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The specified deadline passes; or
|
||||
*
|
||||
* <li>The call spuriously (that is, for no reason) returns.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This method does <em>not</em> report which of these caused the
|
||||
* method to return. Callers should re-check the conditions which caused
|
||||
* the thread to park in the first place. Callers may also determine,
|
||||
* for example, the interrupt status of the thread, or the current time
|
||||
* upon return.
|
||||
*
|
||||
* @param deadline the absolute time, in milliseconds from the Epoch,
|
||||
* to wait until
|
||||
*/
|
||||
public static void parkUntil(long deadline) {
|
||||
UNSAFE.park(true, deadline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pseudo-randomly initialized or updated secondary seed.
|
||||
* Copied from ThreadLocalRandom due to package access restrictions.
|
||||
*/
|
||||
static final int nextSecondarySeed() {
|
||||
int r;
|
||||
Thread t = Thread.currentThread();
|
||||
if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
|
||||
r ^= r << 13; // xorshift
|
||||
r ^= r >>> 17;
|
||||
r ^= r << 5;
|
||||
}
|
||||
else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
|
||||
r = 1; // avoid zero
|
||||
UNSAFE.putInt(t, SECONDARY, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// Hotspot implementation via intrinsics API
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long parkBlockerOffset;
|
||||
private static final long SEED;
|
||||
private static final long PROBE;
|
||||
private static final long SECONDARY;
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class<?> tk = Thread.class;
|
||||
parkBlockerOffset = UNSAFE.objectFieldOffset
|
||||
(tk.getDeclaredField("parkBlocker"));
|
||||
SEED = UNSAFE.objectFieldOffset
|
||||
(tk.getDeclaredField("threadLocalRandomSeed"));
|
||||
PROBE = UNSAFE.objectFieldOffset
|
||||
(tk.getDeclaredField("threadLocalRandomProbe"));
|
||||
SECONDARY = UNSAFE.objectFieldOffset
|
||||
(tk.getDeclaredField("threadLocalRandomSecondarySeed"));
|
||||
} catch (Exception ex) { throw new Error(ex); }
|
||||
}
|
||||
|
||||
}
|
||||
133
jdkSrc/jdk8/java/util/concurrent/locks/ReadWriteLock.java
Normal file
133
jdkSrc/jdk8/java/util/concurrent/locks/ReadWriteLock.java
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
|
||||
/**
|
||||
* A {@code ReadWriteLock} maintains a pair of associated {@link
|
||||
* Lock locks}, one for read-only operations and one for writing.
|
||||
* The {@link #readLock read lock} may be held simultaneously by
|
||||
* multiple reader threads, so long as there are no writers. The
|
||||
* {@link #writeLock write lock} is exclusive.
|
||||
*
|
||||
* <p>All {@code ReadWriteLock} implementations must guarantee that
|
||||
* the memory synchronization effects of {@code writeLock} operations
|
||||
* (as specified in the {@link Lock} interface) also hold with respect
|
||||
* to the associated {@code readLock}. That is, a thread successfully
|
||||
* acquiring the read lock will see all updates made upon previous
|
||||
* release of the write lock.
|
||||
*
|
||||
* <p>A read-write lock allows for a greater level of concurrency in
|
||||
* accessing shared data than that permitted by a mutual exclusion lock.
|
||||
* It exploits the fact that while only a single thread at a time (a
|
||||
* <em>writer</em> thread) can modify the shared data, in many cases any
|
||||
* number of threads can concurrently read the data (hence <em>reader</em>
|
||||
* threads).
|
||||
* In theory, the increase in concurrency permitted by the use of a read-write
|
||||
* lock will lead to performance improvements over the use of a mutual
|
||||
* exclusion lock. In practice this increase in concurrency will only be fully
|
||||
* realized on a multi-processor, and then only if the access patterns for
|
||||
* the shared data are suitable.
|
||||
*
|
||||
* <p>Whether or not a read-write lock will improve performance over the use
|
||||
* of a mutual exclusion lock depends on the frequency that the data is
|
||||
* read compared to being modified, the duration of the read and write
|
||||
* operations, and the contention for the data - that is, the number of
|
||||
* threads that will try to read or write the data at the same time.
|
||||
* For example, a collection that is initially populated with data and
|
||||
* thereafter infrequently modified, while being frequently searched
|
||||
* (such as a directory of some kind) is an ideal candidate for the use of
|
||||
* a read-write lock. However, if updates become frequent then the data
|
||||
* spends most of its time being exclusively locked and there is little, if any
|
||||
* increase in concurrency. Further, if the read operations are too short
|
||||
* the overhead of the read-write lock implementation (which is inherently
|
||||
* more complex than a mutual exclusion lock) can dominate the execution
|
||||
* cost, particularly as many read-write lock implementations still serialize
|
||||
* all threads through a small section of code. Ultimately, only profiling
|
||||
* and measurement will establish whether the use of a read-write lock is
|
||||
* suitable for your application.
|
||||
*
|
||||
*
|
||||
* <p>Although the basic operation of a read-write lock is straight-forward,
|
||||
* there are many policy decisions that an implementation must make, which
|
||||
* may affect the effectiveness of the read-write lock in a given application.
|
||||
* Examples of these policies include:
|
||||
* <ul>
|
||||
* <li>Determining whether to grant the read lock or the write lock, when
|
||||
* both readers and writers are waiting, at the time that a writer releases
|
||||
* the write lock. Writer preference is common, as writes are expected to be
|
||||
* short and infrequent. Reader preference is less common as it can lead to
|
||||
* lengthy delays for a write if the readers are frequent and long-lived as
|
||||
* expected. Fair, or "in-order" implementations are also possible.
|
||||
*
|
||||
* <li>Determining whether readers that request the read lock while a
|
||||
* reader is active and a writer is waiting, are granted the read lock.
|
||||
* Preference to the reader can delay the writer indefinitely, while
|
||||
* preference to the writer can reduce the potential for concurrency.
|
||||
*
|
||||
* <li>Determining whether the locks are reentrant: can a thread with the
|
||||
* write lock reacquire it? Can it acquire a read lock while holding the
|
||||
* write lock? Is the read lock itself reentrant?
|
||||
*
|
||||
* <li>Can the write lock be downgraded to a read lock without allowing
|
||||
* an intervening writer? Can a read lock be upgraded to a write lock,
|
||||
* in preference to other waiting readers or writers?
|
||||
*
|
||||
* </ul>
|
||||
* You should consider all of these things when evaluating the suitability
|
||||
* of a given implementation for your application.
|
||||
*
|
||||
* @see ReentrantReadWriteLock
|
||||
* @see Lock
|
||||
* @see ReentrantLock
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public interface ReadWriteLock {
|
||||
/**
|
||||
* Returns the lock used for reading.
|
||||
*
|
||||
* @return the lock used for reading
|
||||
*/
|
||||
Lock readLock();
|
||||
|
||||
/**
|
||||
* Returns the lock used for writing.
|
||||
*
|
||||
* @return the lock used for writing
|
||||
*/
|
||||
Lock writeLock();
|
||||
}
|
||||
762
jdkSrc/jdk8/java/util/concurrent/locks/ReentrantLock.java
Normal file
762
jdkSrc/jdk8/java/util/concurrent/locks/ReentrantLock.java
Normal file
@@ -0,0 +1,762 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
package java.util.concurrent.locks;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A reentrant mutual exclusion {@link Lock} with the same basic
|
||||
* behavior and semantics as the implicit monitor lock accessed using
|
||||
* {@code synchronized} methods and statements, but with extended
|
||||
* capabilities.
|
||||
*
|
||||
* <p>A {@code ReentrantLock} is <em>owned</em> by the thread last
|
||||
* successfully locking, but not yet unlocking it. A thread invoking
|
||||
* {@code lock} will return, successfully acquiring the lock, when
|
||||
* the lock is not owned by another thread. The method will return
|
||||
* immediately if the current thread already owns the lock. This can
|
||||
* be checked using methods {@link #isHeldByCurrentThread}, and {@link
|
||||
* #getHoldCount}.
|
||||
*
|
||||
* <p>The constructor for this class accepts an optional
|
||||
* <em>fairness</em> parameter. When set {@code true}, under
|
||||
* contention, locks favor granting access to the longest-waiting
|
||||
* thread. Otherwise this lock does not guarantee any particular
|
||||
* access order. Programs using fair locks accessed by many threads
|
||||
* may display lower overall throughput (i.e., are slower; often much
|
||||
* slower) than those using the default setting, but have smaller
|
||||
* variances in times to obtain locks and guarantee lack of
|
||||
* starvation. Note however, that fairness of locks does not guarantee
|
||||
* fairness of thread scheduling. Thus, one of many threads using a
|
||||
* fair lock may obtain it multiple times in succession while other
|
||||
* active threads are not progressing and not currently holding the
|
||||
* lock.
|
||||
* Also note that the untimed {@link #tryLock()} method does not
|
||||
* honor the fairness setting. It will succeed if the lock
|
||||
* is available even if other threads are waiting.
|
||||
*
|
||||
* <p>It is recommended practice to <em>always</em> immediately
|
||||
* follow a call to {@code lock} with a {@code try} block, most
|
||||
* typically in a before/after construction such as:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class X {
|
||||
* private final ReentrantLock lock = new ReentrantLock();
|
||||
* // ...
|
||||
*
|
||||
* public void m() {
|
||||
* lock.lock(); // block until condition holds
|
||||
* try {
|
||||
* // ... method body
|
||||
* } finally {
|
||||
* lock.unlock()
|
||||
* }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>In addition to implementing the {@link Lock} interface, this
|
||||
* class defines a number of {@code public} and {@code protected}
|
||||
* methods for inspecting the state of the lock. Some of these
|
||||
* methods are only useful for instrumentation and monitoring.
|
||||
*
|
||||
* <p>Serialization of this class behaves in the same way as built-in
|
||||
* locks: a deserialized lock is in the unlocked state, regardless of
|
||||
* its state when serialized.
|
||||
*
|
||||
* <p>This lock supports a maximum of 2147483647 recursive locks by
|
||||
* the same thread. Attempts to exceed this limit result in
|
||||
* {@link Error} throws from locking methods.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Doug Lea
|
||||
*/
|
||||
public class ReentrantLock implements Lock, java.io.Serializable {
|
||||
private static final long serialVersionUID = 7373984872572414699L;
|
||||
/** Synchronizer providing all implementation mechanics */
|
||||
private final Sync sync;
|
||||
|
||||
/**
|
||||
* Base of synchronization control for this lock. Subclassed
|
||||
* into fair and nonfair versions below. Uses AQS state to
|
||||
* represent the number of holds on the lock.
|
||||
*/
|
||||
abstract static class Sync extends AbstractQueuedSynchronizer {
|
||||
private static final long serialVersionUID = -5179523762034025860L;
|
||||
|
||||
/**
|
||||
* Performs {@link Lock#lock}. The main reason for subclassing
|
||||
* is to allow fast path for nonfair version.
|
||||
*/
|
||||
abstract void lock();
|
||||
|
||||
/**
|
||||
* Performs non-fair tryLock. tryAcquire is implemented in
|
||||
* subclasses, but both need nonfair try for trylock method.
|
||||
*/
|
||||
final boolean nonfairTryAcquire(int acquires) {
|
||||
final Thread current = Thread.currentThread();
|
||||
int c = getState();
|
||||
if (c == 0) {
|
||||
if (compareAndSetState(0, acquires)) {
|
||||
setExclusiveOwnerThread(current);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (current == getExclusiveOwnerThread()) {
|
||||
int nextc = c + acquires;
|
||||
if (nextc < 0) // overflow
|
||||
throw new Error("Maximum lock count exceeded");
|
||||
setState(nextc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected final boolean tryRelease(int releases) {
|
||||
int c = getState() - releases;
|
||||
if (Thread.currentThread() != getExclusiveOwnerThread())
|
||||
throw new IllegalMonitorStateException();
|
||||
boolean free = false;
|
||||
if (c == 0) {
|
||||
free = true;
|
||||
setExclusiveOwnerThread(null);
|
||||
}
|
||||
setState(c);
|
||||
return free;
|
||||
}
|
||||
|
||||
protected final boolean isHeldExclusively() {
|
||||
// While we must in general read state before owner,
|
||||
// we don't need to do so to check if current thread is owner
|
||||
return getExclusiveOwnerThread() == Thread.currentThread();
|
||||
}
|
||||
|
||||
final ConditionObject newCondition() {
|
||||
return new ConditionObject();
|
||||
}
|
||||
|
||||
// Methods relayed from outer class
|
||||
|
||||
final Thread getOwner() {
|
||||
return getState() == 0 ? null : getExclusiveOwnerThread();
|
||||
}
|
||||
|
||||
final int getHoldCount() {
|
||||
return isHeldExclusively() ? getState() : 0;
|
||||
}
|
||||
|
||||
final boolean isLocked() {
|
||||
return getState() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitutes the instance from a stream (that is, deserializes it).
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
s.defaultReadObject();
|
||||
setState(0); // reset to unlocked state
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync object for non-fair locks
|
||||
*/
|
||||
static final class NonfairSync extends Sync {
|
||||
private static final long serialVersionUID = 7316153563782823691L;
|
||||
|
||||
/**
|
||||
* Performs lock. Try immediate barge, backing up to normal
|
||||
* acquire on failure.
|
||||
*/
|
||||
final void lock() {
|
||||
if (compareAndSetState(0, 1))
|
||||
setExclusiveOwnerThread(Thread.currentThread());
|
||||
else
|
||||
acquire(1);
|
||||
}
|
||||
|
||||
protected final boolean tryAcquire(int acquires) {
|
||||
return nonfairTryAcquire(acquires);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync object for fair locks
|
||||
*/
|
||||
static final class FairSync extends Sync {
|
||||
private static final long serialVersionUID = -3000897897090466540L;
|
||||
|
||||
final void lock() {
|
||||
acquire(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fair version of tryAcquire. Don't grant access unless
|
||||
* recursive call or no waiters or is first.
|
||||
*/
|
||||
protected final boolean tryAcquire(int acquires) {
|
||||
final Thread current = Thread.currentThread();
|
||||
int c = getState();
|
||||
if (c == 0) {
|
||||
if (!hasQueuedPredecessors() &&
|
||||
compareAndSetState(0, acquires)) {
|
||||
setExclusiveOwnerThread(current);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (current == getExclusiveOwnerThread()) {
|
||||
int nextc = c + acquires;
|
||||
if (nextc < 0)
|
||||
throw new Error("Maximum lock count exceeded");
|
||||
setState(nextc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of {@code ReentrantLock}.
|
||||
* This is equivalent to using {@code ReentrantLock(false)}.
|
||||
*/
|
||||
public ReentrantLock() {
|
||||
sync = new NonfairSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of {@code ReentrantLock} with the
|
||||
* given fairness policy.
|
||||
*
|
||||
* @param fair {@code true} if this lock should use a fair ordering policy
|
||||
*/
|
||||
public ReentrantLock(boolean fair) {
|
||||
sync = fair ? new FairSync() : new NonfairSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the lock.
|
||||
*
|
||||
* <p>Acquires the lock if it is not held by another thread and returns
|
||||
* immediately, setting the lock hold count to one.
|
||||
*
|
||||
* <p>If the current thread already holds the lock then the hold
|
||||
* count is incremented by one and the method returns immediately.
|
||||
*
|
||||
* <p>If the lock is held by another thread then the
|
||||
* current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until the lock has been acquired,
|
||||
* at which time the lock hold count is set to one.
|
||||
*/
|
||||
public void lock() {
|
||||
sync.lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the lock unless the current thread is
|
||||
* {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>Acquires the lock if it is not held by another thread and returns
|
||||
* immediately, setting the lock hold count to one.
|
||||
*
|
||||
* <p>If the current thread already holds this lock then the hold count
|
||||
* is incremented by one and the method returns immediately.
|
||||
*
|
||||
* <p>If the lock is held by another thread then the
|
||||
* current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until one of two things happens:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>The lock is acquired by the current thread; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts} the
|
||||
* current thread.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the lock is acquired by the current thread then the lock hold
|
||||
* count is set to one.
|
||||
*
|
||||
* <p>If the current thread:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
*
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while acquiring
|
||||
* the lock,
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* <p>In this implementation, as this method is an explicit
|
||||
* interruption point, preference is given to responding to the
|
||||
* interrupt over normal or reentrant acquisition of the lock.
|
||||
*
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
*/
|
||||
public void lockInterruptibly() throws InterruptedException {
|
||||
sync.acquireInterruptibly(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the lock only if it is not held by another thread at the time
|
||||
* of invocation.
|
||||
*
|
||||
* <p>Acquires the lock if it is not held by another thread and
|
||||
* returns immediately with the value {@code true}, setting the
|
||||
* lock hold count to one. Even when this lock has been set to use a
|
||||
* fair ordering policy, a call to {@code tryLock()} <em>will</em>
|
||||
* immediately acquire the lock if it is available, whether or not
|
||||
* other threads are currently waiting for the lock.
|
||||
* This "barging" behavior can be useful in certain
|
||||
* circumstances, even though it breaks fairness. If you want to honor
|
||||
* the fairness setting for this lock, then use
|
||||
* {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
|
||||
* which is almost equivalent (it also detects interruption).
|
||||
*
|
||||
* <p>If the current thread already holds this lock then the hold
|
||||
* count is incremented by one and the method returns {@code true}.
|
||||
*
|
||||
* <p>If the lock is held by another thread then this method will return
|
||||
* immediately with the value {@code false}.
|
||||
*
|
||||
* @return {@code true} if the lock was free and was acquired by the
|
||||
* current thread, or the lock was already held by the current
|
||||
* thread; and {@code false} otherwise
|
||||
*/
|
||||
public boolean tryLock() {
|
||||
return sync.nonfairTryAcquire(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires the lock if it is not held by another thread within the given
|
||||
* waiting time and the current thread has not been
|
||||
* {@linkplain Thread#interrupt interrupted}.
|
||||
*
|
||||
* <p>Acquires the lock if it is not held by another thread and returns
|
||||
* immediately with the value {@code true}, setting the lock hold count
|
||||
* to one. If this lock has been set to use a fair ordering policy then
|
||||
* an available lock <em>will not</em> be acquired if any other threads
|
||||
* are waiting for the lock. This is in contrast to the {@link #tryLock()}
|
||||
* method. If you want a timed {@code tryLock} that does permit barging on
|
||||
* a fair lock then combine the timed and un-timed forms together:
|
||||
*
|
||||
* <pre> {@code
|
||||
* if (lock.tryLock() ||
|
||||
* lock.tryLock(timeout, unit)) {
|
||||
* ...
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>If the current thread
|
||||
* already holds this lock then the hold count is incremented by one and
|
||||
* the method returns {@code true}.
|
||||
*
|
||||
* <p>If the lock is held by another thread then the
|
||||
* current thread becomes disabled for thread scheduling
|
||||
* purposes and lies dormant until one of three things happens:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>The lock is acquired by the current thread; or
|
||||
*
|
||||
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
|
||||
* the current thread; or
|
||||
*
|
||||
* <li>The specified waiting time elapses
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the lock is acquired then the value {@code true} is returned and
|
||||
* the lock hold count is set to one.
|
||||
*
|
||||
* <p>If the current thread:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>has its interrupted status set on entry to this method; or
|
||||
*
|
||||
* <li>is {@linkplain Thread#interrupt interrupted} while
|
||||
* acquiring the lock,
|
||||
*
|
||||
* </ul>
|
||||
* then {@link InterruptedException} is thrown and the current thread's
|
||||
* interrupted status is cleared.
|
||||
*
|
||||
* <p>If the specified waiting time elapses then the value {@code false}
|
||||
* is returned. If the time is less than or equal to zero, the method
|
||||
* will not wait at all.
|
||||
*
|
||||
* <p>In this implementation, as this method is an explicit
|
||||
* interruption point, preference is given to responding to the
|
||||
* interrupt over normal or reentrant acquisition of the lock, and
|
||||
* over reporting the elapse of the waiting time.
|
||||
*
|
||||
* @param timeout the time to wait for the lock
|
||||
* @param unit the time unit of the timeout argument
|
||||
* @return {@code true} if the lock was free and was acquired by the
|
||||
* current thread, or the lock was already held by the current
|
||||
* thread; and {@code false} if the waiting time elapsed before
|
||||
* the lock could be acquired
|
||||
* @throws InterruptedException if the current thread is interrupted
|
||||
* @throws NullPointerException if the time unit is null
|
||||
*/
|
||||
public boolean tryLock(long timeout, TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to release this lock.
|
||||
*
|
||||
* <p>If the current thread is the holder of this lock then the hold
|
||||
* count is decremented. If the hold count is now zero then the lock
|
||||
* is released. If the current thread is not the holder of this
|
||||
* lock then {@link IllegalMonitorStateException} is thrown.
|
||||
*
|
||||
* @throws IllegalMonitorStateException if the current thread does not
|
||||
* hold this lock
|
||||
*/
|
||||
public void unlock() {
|
||||
sync.release(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Condition} instance for use with this
|
||||
* {@link Lock} instance.
|
||||
*
|
||||
* <p>The returned {@link Condition} instance supports the same
|
||||
* usages as do the {@link Object} monitor methods ({@link
|
||||
* Object#wait() wait}, {@link Object#notify notify}, and {@link
|
||||
* Object#notifyAll notifyAll}) when used with the built-in
|
||||
* monitor lock.
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>If this lock is not held when any of the {@link Condition}
|
||||
* {@linkplain Condition#await() waiting} or {@linkplain
|
||||
* Condition#signal signalling} methods are called, then an {@link
|
||||
* IllegalMonitorStateException} is thrown.
|
||||
*
|
||||
* <li>When the condition {@linkplain Condition#await() waiting}
|
||||
* methods are called the lock is released and, before they
|
||||
* return, the lock is reacquired and the lock hold count restored
|
||||
* to what it was when the method was called.
|
||||
*
|
||||
* <li>If a thread is {@linkplain Thread#interrupt interrupted}
|
||||
* while waiting then the wait will terminate, an {@link
|
||||
* InterruptedException} will be thrown, and the thread's
|
||||
* interrupted status will be cleared.
|
||||
*
|
||||
* <li> Waiting threads are signalled in FIFO order.
|
||||
*
|
||||
* <li>The ordering of lock reacquisition for threads returning
|
||||
* from waiting methods is the same as for threads initially
|
||||
* acquiring the lock, which is in the default case not specified,
|
||||
* but for <em>fair</em> locks favors those threads that have been
|
||||
* waiting the longest.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @return the Condition object
|
||||
*/
|
||||
public Condition newCondition() {
|
||||
return sync.newCondition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the number of holds on this lock by the current thread.
|
||||
*
|
||||
* <p>A thread has a hold on a lock for each lock action that is not
|
||||
* matched by an unlock action.
|
||||
*
|
||||
* <p>The hold count information is typically only used for testing and
|
||||
* debugging purposes. For example, if a certain section of code should
|
||||
* not be entered with the lock already held then we can assert that
|
||||
* fact:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class X {
|
||||
* ReentrantLock lock = new ReentrantLock();
|
||||
* // ...
|
||||
* public void m() {
|
||||
* assert lock.getHoldCount() == 0;
|
||||
* lock.lock();
|
||||
* try {
|
||||
* // ... method body
|
||||
* } finally {
|
||||
* lock.unlock();
|
||||
* }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* @return the number of holds on this lock by the current thread,
|
||||
* or zero if this lock is not held by the current thread
|
||||
*/
|
||||
public int getHoldCount() {
|
||||
return sync.getHoldCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries if this lock is held by the current thread.
|
||||
*
|
||||
* <p>Analogous to the {@link Thread#holdsLock(Object)} method for
|
||||
* built-in monitor locks, this method is typically used for
|
||||
* debugging and testing. For example, a method that should only be
|
||||
* called while a lock is held can assert that this is the case:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class X {
|
||||
* ReentrantLock lock = new ReentrantLock();
|
||||
* // ...
|
||||
*
|
||||
* public void m() {
|
||||
* assert lock.isHeldByCurrentThread();
|
||||
* // ... method body
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* <p>It can also be used to ensure that a reentrant lock is used
|
||||
* in a non-reentrant manner, for example:
|
||||
*
|
||||
* <pre> {@code
|
||||
* class X {
|
||||
* ReentrantLock lock = new ReentrantLock();
|
||||
* // ...
|
||||
*
|
||||
* public void m() {
|
||||
* assert !lock.isHeldByCurrentThread();
|
||||
* lock.lock();
|
||||
* try {
|
||||
* // ... method body
|
||||
* } finally {
|
||||
* lock.unlock();
|
||||
* }
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* @return {@code true} if current thread holds this lock and
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public boolean isHeldByCurrentThread() {
|
||||
return sync.isHeldExclusively();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries if this lock is held by any thread. This method is
|
||||
* designed for use in monitoring of the system state,
|
||||
* not for synchronization control.
|
||||
*
|
||||
* @return {@code true} if any thread holds this lock and
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public boolean isLocked() {
|
||||
return sync.isLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this lock has fairness set true.
|
||||
*
|
||||
* @return {@code true} if this lock has fairness set true
|
||||
*/
|
||||
public final boolean isFair() {
|
||||
return sync instanceof FairSync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thread that currently owns this lock, or
|
||||
* {@code null} if not owned. When this method is called by a
|
||||
* thread that is not the owner, the return value reflects a
|
||||
* best-effort approximation of current lock status. For example,
|
||||
* the owner may be momentarily {@code null} even if there are
|
||||
* threads trying to acquire the lock but have not yet done so.
|
||||
* This method is designed to facilitate construction of
|
||||
* subclasses that provide more extensive lock monitoring
|
||||
* facilities.
|
||||
*
|
||||
* @return the owner, or {@code null} if not owned
|
||||
*/
|
||||
protected Thread getOwner() {
|
||||
return sync.getOwner();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries whether any threads are waiting to acquire this lock. Note that
|
||||
* because cancellations may occur at any time, a {@code true}
|
||||
* return does not guarantee that any other thread will ever
|
||||
* acquire this lock. This method is designed primarily for use in
|
||||
* monitoring of the system state.
|
||||
*
|
||||
* @return {@code true} if there may be other threads waiting to
|
||||
* acquire the lock
|
||||
*/
|
||||
public final boolean hasQueuedThreads() {
|
||||
return sync.hasQueuedThreads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries whether the given thread is waiting to acquire this
|
||||
* lock. Note that because cancellations may occur at any time, a
|
||||
* {@code true} return does not guarantee that this thread
|
||||
* will ever acquire this lock. This method is designed primarily for use
|
||||
* in monitoring of the system state.
|
||||
*
|
||||
* @param thread the thread
|
||||
* @return {@code true} if the given thread is queued waiting for this lock
|
||||
* @throws NullPointerException if the thread is null
|
||||
*/
|
||||
public final boolean hasQueuedThread(Thread thread) {
|
||||
return sync.isQueued(thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of threads waiting to
|
||||
* acquire this lock. The value is only an estimate because the number of
|
||||
* threads may change dynamically while this method traverses
|
||||
* internal data structures. This method is designed for use in
|
||||
* monitoring of the system state, not for synchronization
|
||||
* control.
|
||||
*
|
||||
* @return the estimated number of threads waiting for this lock
|
||||
*/
|
||||
public final int getQueueLength() {
|
||||
return sync.getQueueLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection containing threads that may be waiting to
|
||||
* acquire this lock. Because the actual set of threads may change
|
||||
* dynamically while constructing this result, the returned
|
||||
* collection is only a best-effort estimate. The elements of the
|
||||
* returned collection are in no particular order. This method is
|
||||
* designed to facilitate construction of subclasses that provide
|
||||
* more extensive monitoring facilities.
|
||||
*
|
||||
* @return the collection of threads
|
||||
*/
|
||||
protected Collection<Thread> getQueuedThreads() {
|
||||
return sync.getQueuedThreads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries whether any threads are waiting on the given condition
|
||||
* associated with this lock. Note that because timeouts and
|
||||
* interrupts may occur at any time, a {@code true} return does
|
||||
* not guarantee that a future {@code signal} will awaken any
|
||||
* threads. This method is designed primarily for use in
|
||||
* monitoring of the system state.
|
||||
*
|
||||
* @param condition the condition
|
||||
* @return {@code true} if there are any waiting threads
|
||||
* @throws IllegalMonitorStateException if this lock is not held
|
||||
* @throws IllegalArgumentException if the given condition is
|
||||
* not associated with this lock
|
||||
* @throws NullPointerException if the condition is null
|
||||
*/
|
||||
public boolean hasWaiters(Condition condition) {
|
||||
if (condition == null)
|
||||
throw new NullPointerException();
|
||||
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
|
||||
throw new IllegalArgumentException("not owner");
|
||||
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of threads waiting on the
|
||||
* given condition associated with this lock. Note that because
|
||||
* timeouts and interrupts may occur at any time, the estimate
|
||||
* serves only as an upper bound on the actual number of waiters.
|
||||
* This method is designed for use in monitoring of the system
|
||||
* state, not for synchronization control.
|
||||
*
|
||||
* @param condition the condition
|
||||
* @return the estimated number of waiting threads
|
||||
* @throws IllegalMonitorStateException if this lock is not held
|
||||
* @throws IllegalArgumentException if the given condition is
|
||||
* not associated with this lock
|
||||
* @throws NullPointerException if the condition is null
|
||||
*/
|
||||
public int getWaitQueueLength(Condition condition) {
|
||||
if (condition == null)
|
||||
throw new NullPointerException();
|
||||
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
|
||||
throw new IllegalArgumentException("not owner");
|
||||
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection containing those threads that may be
|
||||
* waiting on the given condition associated with this lock.
|
||||
* Because the actual set of threads may change dynamically while
|
||||
* constructing this result, the returned collection is only a
|
||||
* best-effort estimate. The elements of the returned collection
|
||||
* are in no particular order. This method is designed to
|
||||
* facilitate construction of subclasses that provide more
|
||||
* extensive condition monitoring facilities.
|
||||
*
|
||||
* @param condition the condition
|
||||
* @return the collection of threads
|
||||
* @throws IllegalMonitorStateException if this lock is not held
|
||||
* @throws IllegalArgumentException if the given condition is
|
||||
* not associated with this lock
|
||||
* @throws NullPointerException if the condition is null
|
||||
*/
|
||||
protected Collection<Thread> getWaitingThreads(Condition condition) {
|
||||
if (condition == null)
|
||||
throw new NullPointerException();
|
||||
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
|
||||
throw new IllegalArgumentException("not owner");
|
||||
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string identifying this lock, as well as its lock state.
|
||||
* The state, in brackets, includes either the String {@code "Unlocked"}
|
||||
* or the String {@code "Locked by"} followed by the
|
||||
* {@linkplain Thread#getName name} of the owning thread.
|
||||
*
|
||||
* @return a string identifying this lock, as well as its lock state
|
||||
*/
|
||||
public String toString() {
|
||||
Thread o = sync.getOwner();
|
||||
return super.toString() + ((o == null) ?
|
||||
"[Unlocked]" :
|
||||
"[Locked by thread " + o.getName() + "]");
|
||||
}
|
||||
}
|
||||
1510
jdkSrc/jdk8/java/util/concurrent/locks/ReentrantReadWriteLock.java
Normal file
1510
jdkSrc/jdk8/java/util/concurrent/locks/ReentrantReadWriteLock.java
Normal file
File diff suppressed because it is too large
Load Diff
1414
jdkSrc/jdk8/java/util/concurrent/locks/StampedLock.java
Normal file
1414
jdkSrc/jdk8/java/util/concurrent/locks/StampedLock.java
Normal file
File diff suppressed because it is too large
Load Diff
79
jdkSrc/jdk8/java/util/concurrent/locks/package-info.java
Normal file
79
jdkSrc/jdk8/java/util/concurrent/locks/package-info.java
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interfaces and classes providing a framework for locking and waiting
|
||||
* for conditions that is distinct from built-in synchronization and
|
||||
* monitors. The framework permits much greater flexibility in the use of
|
||||
* locks and conditions, at the expense of more awkward syntax.
|
||||
*
|
||||
* <p>The {@link java.util.concurrent.locks.Lock} interface supports
|
||||
* locking disciplines that differ in semantics (reentrant, fair, etc),
|
||||
* and that can be used in non-block-structured contexts including
|
||||
* hand-over-hand and lock reordering algorithms. The main implementation
|
||||
* is {@link java.util.concurrent.locks.ReentrantLock}.
|
||||
*
|
||||
* <p>The {@link java.util.concurrent.locks.ReadWriteLock} interface
|
||||
* similarly defines locks that may be shared among readers but are
|
||||
* exclusive to writers. Only a single implementation, {@link
|
||||
* java.util.concurrent.locks.ReentrantReadWriteLock}, is provided, since
|
||||
* it covers most standard usage contexts. But programmers may create
|
||||
* their own implementations to cover nonstandard requirements.
|
||||
*
|
||||
* <p>The {@link java.util.concurrent.locks.Condition} interface
|
||||
* describes condition variables that may be associated with Locks.
|
||||
* These are similar in usage to the implicit monitors accessed using
|
||||
* {@code Object.wait}, but offer extended capabilities.
|
||||
* In particular, multiple {@code Condition} objects may be associated
|
||||
* with a single {@code Lock}. To avoid compatibility issues, the
|
||||
* names of {@code Condition} methods are different from the
|
||||
* corresponding {@code Object} versions.
|
||||
*
|
||||
* <p>The {@link java.util.concurrent.locks.AbstractQueuedSynchronizer}
|
||||
* class serves as a useful superclass for defining locks and other
|
||||
* synchronizers that rely on queuing blocked threads. The {@link
|
||||
* java.util.concurrent.locks.AbstractQueuedLongSynchronizer} class
|
||||
* provides the same functionality but extends support to 64 bits of
|
||||
* synchronization state. Both extend class {@link
|
||||
* java.util.concurrent.locks.AbstractOwnableSynchronizer}, a simple
|
||||
* class that helps record the thread currently holding exclusive
|
||||
* synchronization. The {@link java.util.concurrent.locks.LockSupport}
|
||||
* class provides lower-level blocking and unblocking support that is
|
||||
* useful for those developers implementing their own customized lock
|
||||
* classes.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
package java.util.concurrent.locks;
|
||||
307
jdkSrc/jdk8/java/util/concurrent/package-info.java
Normal file
307
jdkSrc/jdk8/java/util/concurrent/package-info.java
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Utility classes commonly useful in concurrent programming. This
|
||||
* package includes a few small standardized extensible frameworks, as
|
||||
* well as some classes that provide useful functionality and are
|
||||
* otherwise tedious or difficult to implement. Here are brief
|
||||
* descriptions of the main components. See also the
|
||||
* {@link java.util.concurrent.locks} and
|
||||
* {@link java.util.concurrent.atomic} packages.
|
||||
*
|
||||
* <h2>Executors</h2>
|
||||
*
|
||||
* <b>Interfaces.</b>
|
||||
*
|
||||
* {@link java.util.concurrent.Executor} is a simple standardized
|
||||
* interface for defining custom thread-like subsystems, including
|
||||
* thread pools, asynchronous I/O, and lightweight task frameworks.
|
||||
* Depending on which concrete Executor class is being used, tasks may
|
||||
* execute in a newly created thread, an existing task-execution thread,
|
||||
* or the thread calling {@link java.util.concurrent.Executor#execute
|
||||
* execute}, and may execute sequentially or concurrently.
|
||||
*
|
||||
* {@link java.util.concurrent.ExecutorService} provides a more
|
||||
* complete asynchronous task execution framework. An
|
||||
* ExecutorService manages queuing and scheduling of tasks,
|
||||
* and allows controlled shutdown.
|
||||
*
|
||||
* The {@link java.util.concurrent.ScheduledExecutorService}
|
||||
* subinterface and associated interfaces add support for
|
||||
* delayed and periodic task execution. ExecutorServices
|
||||
* provide methods arranging asynchronous execution of any
|
||||
* function expressed as {@link java.util.concurrent.Callable},
|
||||
* the result-bearing analog of {@link java.lang.Runnable}.
|
||||
*
|
||||
* A {@link java.util.concurrent.Future} returns the results of
|
||||
* a function, allows determination of whether execution has
|
||||
* completed, and provides a means to cancel execution.
|
||||
*
|
||||
* A {@link java.util.concurrent.RunnableFuture} is a {@code Future}
|
||||
* that possesses a {@code run} method that upon execution,
|
||||
* sets its results.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* <b>Implementations.</b>
|
||||
*
|
||||
* Classes {@link java.util.concurrent.ThreadPoolExecutor} and
|
||||
* {@link java.util.concurrent.ScheduledThreadPoolExecutor}
|
||||
* provide tunable, flexible thread pools.
|
||||
*
|
||||
* The {@link java.util.concurrent.Executors} class provides
|
||||
* factory methods for the most common kinds and configurations
|
||||
* of Executors, as well as a few utility methods for using
|
||||
* them. Other utilities based on {@code Executors} include the
|
||||
* concrete class {@link java.util.concurrent.FutureTask}
|
||||
* providing a common extensible implementation of Futures, and
|
||||
* {@link java.util.concurrent.ExecutorCompletionService}, that
|
||||
* assists in coordinating the processing of groups of
|
||||
* asynchronous tasks.
|
||||
*
|
||||
* <p>Class {@link java.util.concurrent.ForkJoinPool} provides an
|
||||
* Executor primarily designed for processing instances of {@link
|
||||
* java.util.concurrent.ForkJoinTask} and its subclasses. These
|
||||
* classes employ a work-stealing scheduler that attains high
|
||||
* throughput for tasks conforming to restrictions that often hold in
|
||||
* computation-intensive parallel processing.
|
||||
*
|
||||
* <h2>Queues</h2>
|
||||
*
|
||||
* The {@link java.util.concurrent.ConcurrentLinkedQueue} class
|
||||
* supplies an efficient scalable thread-safe non-blocking FIFO queue.
|
||||
* The {@link java.util.concurrent.ConcurrentLinkedDeque} class is
|
||||
* similar, but additionally supports the {@link java.util.Deque}
|
||||
* interface.
|
||||
*
|
||||
* <p>Five implementations in {@code java.util.concurrent} support
|
||||
* the extended {@link java.util.concurrent.BlockingQueue}
|
||||
* interface, that defines blocking versions of put and take:
|
||||
* {@link java.util.concurrent.LinkedBlockingQueue},
|
||||
* {@link java.util.concurrent.ArrayBlockingQueue},
|
||||
* {@link java.util.concurrent.SynchronousQueue},
|
||||
* {@link java.util.concurrent.PriorityBlockingQueue}, and
|
||||
* {@link java.util.concurrent.DelayQueue}.
|
||||
* The different classes cover the most common usage contexts
|
||||
* for producer-consumer, messaging, parallel tasking, and
|
||||
* related concurrent designs.
|
||||
*
|
||||
* <p>Extended interface {@link java.util.concurrent.TransferQueue},
|
||||
* and implementation {@link java.util.concurrent.LinkedTransferQueue}
|
||||
* introduce a synchronous {@code transfer} method (along with related
|
||||
* features) in which a producer may optionally block awaiting its
|
||||
* consumer.
|
||||
*
|
||||
* <p>The {@link java.util.concurrent.BlockingDeque} interface
|
||||
* extends {@code BlockingQueue} to support both FIFO and LIFO
|
||||
* (stack-based) operations.
|
||||
* Class {@link java.util.concurrent.LinkedBlockingDeque}
|
||||
* provides an implementation.
|
||||
*
|
||||
* <h2>Timing</h2>
|
||||
*
|
||||
* The {@link java.util.concurrent.TimeUnit} class provides
|
||||
* multiple granularities (including nanoseconds) for
|
||||
* specifying and controlling time-out based operations. Most
|
||||
* classes in the package contain operations based on time-outs
|
||||
* in addition to indefinite waits. In all cases that
|
||||
* time-outs are used, the time-out specifies the minimum time
|
||||
* that the method should wait before indicating that it
|
||||
* timed-out. Implementations make a "best effort"
|
||||
* to detect time-outs as soon as possible after they occur.
|
||||
* However, an indefinite amount of time may elapse between a
|
||||
* time-out being detected and a thread actually executing
|
||||
* again after that time-out. All methods that accept timeout
|
||||
* parameters treat values less than or equal to zero to mean
|
||||
* not to wait at all. To wait "forever", you can use a value
|
||||
* of {@code Long.MAX_VALUE}.
|
||||
*
|
||||
* <h2>Synchronizers</h2>
|
||||
*
|
||||
* Five classes aid common special-purpose synchronization idioms.
|
||||
* <ul>
|
||||
*
|
||||
* <li>{@link java.util.concurrent.Semaphore} is a classic concurrency tool.
|
||||
*
|
||||
* <li>{@link java.util.concurrent.CountDownLatch} is a very simple yet
|
||||
* very common utility for blocking until a given number of signals,
|
||||
* events, or conditions hold.
|
||||
*
|
||||
* <li>A {@link java.util.concurrent.CyclicBarrier} is a resettable
|
||||
* multiway synchronization point useful in some styles of parallel
|
||||
* programming.
|
||||
*
|
||||
* <li>A {@link java.util.concurrent.Phaser} provides
|
||||
* a more flexible form of barrier that may be used to control phased
|
||||
* computation among multiple threads.
|
||||
*
|
||||
* <li>An {@link java.util.concurrent.Exchanger} allows two threads to
|
||||
* exchange objects at a rendezvous point, and is useful in several
|
||||
* pipeline designs.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Concurrent Collections</h2>
|
||||
*
|
||||
* Besides Queues, this package supplies Collection implementations
|
||||
* designed for use in multithreaded contexts:
|
||||
* {@link java.util.concurrent.ConcurrentHashMap},
|
||||
* {@link java.util.concurrent.ConcurrentSkipListMap},
|
||||
* {@link java.util.concurrent.ConcurrentSkipListSet},
|
||||
* {@link java.util.concurrent.CopyOnWriteArrayList}, and
|
||||
* {@link java.util.concurrent.CopyOnWriteArraySet}.
|
||||
* When many threads are expected to access a given collection, a
|
||||
* {@code ConcurrentHashMap} is normally preferable to a synchronized
|
||||
* {@code HashMap}, and a {@code ConcurrentSkipListMap} is normally
|
||||
* preferable to a synchronized {@code TreeMap}.
|
||||
* A {@code CopyOnWriteArrayList} is preferable to a synchronized
|
||||
* {@code ArrayList} when the expected number of reads and traversals
|
||||
* greatly outnumber the number of updates to a list.
|
||||
*
|
||||
* <p>The "Concurrent" prefix used with some classes in this package
|
||||
* is a shorthand indicating several differences from similar
|
||||
* "synchronized" classes. For example {@code java.util.Hashtable} and
|
||||
* {@code Collections.synchronizedMap(new HashMap())} are
|
||||
* synchronized. But {@link
|
||||
* java.util.concurrent.ConcurrentHashMap} is "concurrent". A
|
||||
* concurrent collection is thread-safe, but not governed by a
|
||||
* single exclusion lock. In the particular case of
|
||||
* ConcurrentHashMap, it safely permits any number of
|
||||
* concurrent reads as well as a tunable number of concurrent
|
||||
* writes. "Synchronized" classes can be useful when you need
|
||||
* to prevent all access to a collection via a single lock, at
|
||||
* the expense of poorer scalability. In other cases in which
|
||||
* multiple threads are expected to access a common collection,
|
||||
* "concurrent" versions are normally preferable. And
|
||||
* unsynchronized collections are preferable when either
|
||||
* collections are unshared, or are accessible only when
|
||||
* holding other locks.
|
||||
*
|
||||
* <p id="Weakly">Most concurrent Collection implementations
|
||||
* (including most Queues) also differ from the usual {@code java.util}
|
||||
* conventions in that their {@linkplain java.util.Iterator Iterators}
|
||||
* and {@linkplain java.util.Spliterator Spliterators} provide
|
||||
* <em>weakly consistent</em> rather than fast-fail traversal:
|
||||
* <ul>
|
||||
* <li>they may proceed concurrently with other operations
|
||||
* <li>they will never throw {@link java.util.ConcurrentModificationException
|
||||
* ConcurrentModificationException}
|
||||
* <li>they are guaranteed to traverse elements as they existed upon
|
||||
* construction exactly once, and may (but are not guaranteed to)
|
||||
* reflect any modifications subsequent to construction.
|
||||
* </ul>
|
||||
*
|
||||
* <h2 id="MemoryVisibility">Memory Consistency Properties</h2>
|
||||
*
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5">
|
||||
* Chapter 17 of the Java Language Specification</a> defines the
|
||||
* <i>happens-before</i> relation on memory operations such as reads and
|
||||
* writes of shared variables. The results of a write by one thread are
|
||||
* guaranteed to be visible to a read by another thread only if the write
|
||||
* operation <i>happens-before</i> the read operation. The
|
||||
* {@code synchronized} and {@code volatile} constructs, as well as the
|
||||
* {@code Thread.start()} and {@code Thread.join()} methods, can form
|
||||
* <i>happens-before</i> relationships. In particular:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Each action in a thread <i>happens-before</i> every action in that
|
||||
* thread that comes later in the program's order.
|
||||
*
|
||||
* <li>An unlock ({@code synchronized} block or method exit) of a
|
||||
* monitor <i>happens-before</i> every subsequent lock ({@code synchronized}
|
||||
* block or method entry) of that same monitor. And because
|
||||
* the <i>happens-before</i> relation is transitive, all actions
|
||||
* of a thread prior to unlocking <i>happen-before</i> all actions
|
||||
* subsequent to any thread locking that monitor.
|
||||
*
|
||||
* <li>A write to a {@code volatile} field <i>happens-before</i> every
|
||||
* subsequent read of that same field. Writes and reads of
|
||||
* {@code volatile} fields have similar memory consistency effects
|
||||
* as entering and exiting monitors, but do <em>not</em> entail
|
||||
* mutual exclusion locking.
|
||||
*
|
||||
* <li>A call to {@code start} on a thread <i>happens-before</i> any
|
||||
* action in the started thread.
|
||||
*
|
||||
* <li>All actions in a thread <i>happen-before</i> any other thread
|
||||
* successfully returns from a {@code join} on that thread.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* The methods of all classes in {@code java.util.concurrent} and its
|
||||
* subpackages extend these guarantees to higher-level
|
||||
* synchronization. In particular:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>Actions in a thread prior to placing an object into any concurrent
|
||||
* collection <i>happen-before</i> actions subsequent to the access or
|
||||
* removal of that element from the collection in another thread.
|
||||
*
|
||||
* <li>Actions in a thread prior to the submission of a {@code Runnable}
|
||||
* to an {@code Executor} <i>happen-before</i> its execution begins.
|
||||
* Similarly for {@code Callables} submitted to an {@code ExecutorService}.
|
||||
*
|
||||
* <li>Actions taken by the asynchronous computation represented by a
|
||||
* {@code Future} <i>happen-before</i> actions subsequent to the
|
||||
* retrieval of the result via {@code Future.get()} in another thread.
|
||||
*
|
||||
* <li>Actions prior to "releasing" synchronizer methods such as
|
||||
* {@code Lock.unlock}, {@code Semaphore.release}, and
|
||||
* {@code CountDownLatch.countDown} <i>happen-before</i> actions
|
||||
* subsequent to a successful "acquiring" method such as
|
||||
* {@code Lock.lock}, {@code Semaphore.acquire},
|
||||
* {@code Condition.await}, and {@code CountDownLatch.await} on the
|
||||
* same synchronizer object in another thread.
|
||||
*
|
||||
* <li>For each pair of threads that successfully exchange objects via
|
||||
* an {@code Exchanger}, actions prior to the {@code exchange()}
|
||||
* in each thread <i>happen-before</i> those subsequent to the
|
||||
* corresponding {@code exchange()} in another thread.
|
||||
*
|
||||
* <li>Actions prior to calling {@code CyclicBarrier.await} and
|
||||
* {@code Phaser.awaitAdvance} (as well as its variants)
|
||||
* <i>happen-before</i> actions performed by the barrier action, and
|
||||
* actions performed by the barrier action <i>happen-before</i> actions
|
||||
* subsequent to a successful return from the corresponding {@code await}
|
||||
* in other threads.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
package java.util.concurrent;
|
||||
Reference in New Issue
Block a user