summaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/util
diff options
context:
space:
mode:
authorYohann Roussel <yroussel@google.com>2014-03-19 16:25:37 +0100
committerYohann Roussel <yroussel@google.com>2014-03-20 15:13:33 +0100
commit4eceb95409e844fdc33c9c706e1dc307bfd40303 (patch)
treeee9f4f3fc79f757c79081c336bce4f1782c6ccd8 /guava/src/com/google/common/util
parent3d2402901b1a6462e2cf47a6fd09711f327961c3 (diff)
downloadtoolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.zip
toolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.tar.gz
toolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.tar.bz2
Initial Jack import.
Change-Id: I953cf0a520195a7187d791b2885848ad0d5a9b43
Diffstat (limited to 'guava/src/com/google/common/util')
-rw-r--r--guava/src/com/google/common/util/concurrent/AbstractCheckedFuture.java117
-rw-r--r--guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java188
-rw-r--r--guava/src/com/google/common/util/concurrent/AbstractFuture.java371
-rw-r--r--guava/src/com/google/common/util/concurrent/AbstractIdleService.java132
-rw-r--r--guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java163
-rw-r--r--guava/src/com/google/common/util/concurrent/AbstractScheduledService.java446
-rw-r--r--guava/src/com/google/common/util/concurrent/AbstractService.java536
-rw-r--r--guava/src/com/google/common/util/concurrent/AsyncFunction.java41
-rw-r--r--guava/src/com/google/common/util/concurrent/AtomicDouble.java257
-rw-r--r--guava/src/com/google/common/util/concurrent/AtomicDoubleArray.java271
-rw-r--r--guava/src/com/google/common/util/concurrent/AtomicLongMap.java434
-rw-r--r--guava/src/com/google/common/util/concurrent/Atomics.java76
-rw-r--r--guava/src/com/google/common/util/concurrent/Callables.java43
-rw-r--r--guava/src/com/google/common/util/concurrent/CheckedFuture.java76
-rw-r--r--guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java1034
-rw-r--r--guava/src/com/google/common/util/concurrent/ExecutionError.java64
-rw-r--r--guava/src/com/google/common/util/concurrent/ExecutionList.java159
-rw-r--r--guava/src/com/google/common/util/concurrent/FakeTimeLimiter.java47
-rw-r--r--guava/src/com/google/common/util/concurrent/ForwardingBlockingQueue.java74
-rw-r--r--guava/src/com/google/common/util/concurrent/ForwardingCheckedFuture.java78
-rw-r--r--guava/src/com/google/common/util/concurrent/ForwardingExecutorService.java117
-rw-r--r--guava/src/com/google/common/util/concurrent/ForwardingFuture.java96
-rw-r--r--guava/src/com/google/common/util/concurrent/ForwardingListenableFuture.java74
-rw-r--r--guava/src/com/google/common/util/concurrent/ForwardingListeningExecutorService.java52
-rw-r--r--guava/src/com/google/common/util/concurrent/ForwardingService.java86
-rw-r--r--guava/src/com/google/common/util/concurrent/FutureCallback.java49
-rw-r--r--guava/src/com/google/common/util/concurrent/Futures.java1249
-rw-r--r--guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java182
-rw-r--r--guava/src/com/google/common/util/concurrent/ListenableFuture.java135
-rw-r--r--guava/src/com/google/common/util/concurrent/ListenableFutureTask.java90
-rw-r--r--guava/src/com/google/common/util/concurrent/ListeningExecutorService.java88
-rw-r--r--guava/src/com/google/common/util/concurrent/ListeningScheduledExecutorService.java40
-rw-r--r--guava/src/com/google/common/util/concurrent/Monitor.java942
-rw-r--r--guava/src/com/google/common/util/concurrent/MoreExecutors.java587
-rw-r--r--guava/src/com/google/common/util/concurrent/RateLimiter.java658
-rw-r--r--guava/src/com/google/common/util/concurrent/Service.java234
-rw-r--r--guava/src/com/google/common/util/concurrent/SettableFuture.java70
-rw-r--r--guava/src/com/google/common/util/concurrent/SimpleTimeLimiter.java195
-rw-r--r--guava/src/com/google/common/util/concurrent/Striped.java376
-rw-r--r--guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java176
-rw-r--r--guava/src/com/google/common/util/concurrent/TimeLimiter.java106
-rw-r--r--guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java65
-rw-r--r--guava/src/com/google/common/util/concurrent/UncheckedExecutionException.java69
-rw-r--r--guava/src/com/google/common/util/concurrent/UncheckedTimeoutException.java41
-rw-r--r--guava/src/com/google/common/util/concurrent/Uninterruptibles.java278
-rw-r--r--guava/src/com/google/common/util/concurrent/package-info.java36
46 files changed, 10698 insertions, 0 deletions
diff --git a/guava/src/com/google/common/util/concurrent/AbstractCheckedFuture.java b/guava/src/com/google/common/util/concurrent/AbstractCheckedFuture.java
new file mode 100644
index 0000000..dfaf343
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AbstractCheckedFuture.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A delegating wrapper around a {@link ListenableFuture} that adds support for
+ * the {@link #checkedGet()} and {@link #checkedGet(long, TimeUnit)} methods.
+ *
+ * @author Sven Mawson
+ * @since 1.0
+ */
+@Beta
+public abstract class AbstractCheckedFuture<V, X extends Exception>
+ extends ForwardingListenableFuture.SimpleForwardingListenableFuture<V>
+ implements CheckedFuture<V, X> {
+ /**
+ * Constructs an {@code AbstractCheckedFuture} that wraps a delegate.
+ */
+ protected AbstractCheckedFuture(ListenableFuture<V> delegate) {
+ super(delegate);
+ }
+
+ /**
+ * Translates from an {@link InterruptedException},
+ * {@link CancellationException} or {@link ExecutionException} thrown by
+ * {@code get} to an exception of type {@code X} to be thrown by
+ * {@code checkedGet}. Subclasses must implement this method.
+ *
+ * <p>If {@code e} is an {@code InterruptedException}, the calling
+ * {@code checkedGet} method has already restored the interrupt after catching
+ * the exception. If an implementation of {@link #mapException(Exception)}
+ * wishes to swallow the interrupt, it can do so by calling
+ * {@link Thread#interrupted()}.
+ *
+ * <p>Subclasses may choose to throw, rather than return, a subclass of
+ * {@code RuntimeException} to allow creating a CheckedFuture that throws
+ * both checked and unchecked exceptions.
+ */
+ protected abstract X mapException(Exception e);
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>This implementation calls {@link #get()} and maps that method's standard
+ * exceptions to instances of type {@code X} using {@link #mapException}.
+ *
+ * <p>In addition, if {@code get} throws an {@link InterruptedException}, this
+ * implementation will set the current thread's interrupt status before
+ * calling {@code mapException}.
+ *
+ * @throws X if {@link #get()} throws an {@link InterruptedException},
+ * {@link CancellationException}, or {@link ExecutionException}
+ */
+ @Override
+ public V checkedGet() throws X {
+ try {
+ return get();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw mapException(e);
+ } catch (CancellationException e) {
+ throw mapException(e);
+ } catch (ExecutionException e) {
+ throw mapException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>This implementation calls {@link #get(long, TimeUnit)} and maps that
+ * method's standard exceptions (excluding {@link TimeoutException}, which is
+ * propagated) to instances of type {@code X} using {@link #mapException}.
+ *
+ * <p>In addition, if {@code get} throws an {@link InterruptedException}, this
+ * implementation will set the current thread's interrupt status before
+ * calling {@code mapException}.
+ *
+ * @throws X if {@link #get()} throws an {@link InterruptedException},
+ * {@link CancellationException}, or {@link ExecutionException}
+ * @throws TimeoutException {@inheritDoc}
+ */
+ @Override
+ public V checkedGet(long timeout, TimeUnit unit) throws TimeoutException, X {
+ try {
+ return get(timeout, unit);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw mapException(e);
+ } catch (CancellationException e) {
+ throw mapException(e);
+ } catch (ExecutionException e) {
+ throw mapException(e);
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java b/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java
new file mode 100644
index 0000000..6926c85
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AbstractExecutionThreadService.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2009 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Throwables;
+
+import java.util.concurrent.Executor;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Base class for services that can implement {@link #startUp}, {@link #run} and
+ * {@link #shutDown} methods. This class uses a single thread to execute the
+ * service; consider {@link AbstractService} if you would like to manage any
+ * threading manually.
+ *
+ * @author Jesse Wilson
+ * @since 1.0
+ */
+@Beta
+public abstract class AbstractExecutionThreadService implements Service {
+ private static final Logger logger = Logger.getLogger(
+ AbstractExecutionThreadService.class.getName());
+
+ /* use AbstractService for state management */
+ private final Service delegate = new AbstractService() {
+ @Override protected final void doStart() {
+ executor().execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ startUp();
+ notifyStarted();
+
+ if (isRunning()) {
+ try {
+ AbstractExecutionThreadService.this.run();
+ } catch (Throwable t) {
+ try {
+ shutDown();
+ } catch (Exception ignored) {
+ logger.log(Level.WARNING,
+ "Error while attempting to shut down the service"
+ + " after failure.", ignored);
+ }
+ throw t;
+ }
+ }
+
+ shutDown();
+ notifyStopped();
+ } catch (Throwable t) {
+ notifyFailed(t);
+ throw Throwables.propagate(t);
+ }
+ }
+ });
+ }
+
+ @Override protected void doStop() {
+ triggerShutdown();
+ }
+ };
+
+ /**
+ * Constructor for use by subclasses.
+ */
+ protected AbstractExecutionThreadService() {}
+
+ /**
+ * Start the service. This method is invoked on the execution thread.
+ *
+ * <p>By default this method does nothing.
+ */
+ protected void startUp() throws Exception {}
+
+ /**
+ * Run the service. This method is invoked on the execution thread.
+ * Implementations must respond to stop requests. You could poll for lifecycle
+ * changes in a work loop:
+ * <pre>
+ * public void run() {
+ * while ({@link #isRunning()}) {
+ * // perform a unit of work
+ * }
+ * }
+ * </pre>
+ * ...or you could respond to stop requests by implementing {@link
+ * #triggerShutdown()}, which should cause {@link #run()} to return.
+ */
+ protected abstract void run() throws Exception;
+
+ /**
+ * Stop the service. This method is invoked on the execution thread.
+ *
+ * <p>By default this method does nothing.
+ */
+ // TODO: consider supporting a TearDownTestCase-like API
+ protected void shutDown() throws Exception {}
+
+ /**
+ * Invoked to request the service to stop.
+ *
+ * <p>By default this method does nothing.
+ */
+ protected void triggerShutdown() {}
+
+ /**
+ * Returns the {@link Executor} that will be used to run this service.
+ * Subclasses may override this method to use a custom {@link Executor}, which
+ * may configure its worker thread with a specific name, thread group or
+ * priority. The returned executor's {@link Executor#execute(Runnable)
+ * execute()} method is called when this service is started, and should return
+ * promptly.
+ *
+ * <p>The default implementation returns a new {@link Executor} that sets the
+ * name of its threads to the string returned by {@link #getServiceName}
+ */
+ protected Executor executor() {
+ return new Executor() {
+ @Override
+ public void execute(Runnable command) {
+ new Thread(command, getServiceName()).start();
+ }
+ };
+ }
+
+ @Override public String toString() {
+ return getServiceName() + " [" + state() + "]";
+ }
+
+ // We override instead of using ForwardingService so that these can be final.
+
+ @Override public final ListenableFuture<State> start() {
+ return delegate.start();
+ }
+
+ @Override public final State startAndWait() {
+ return delegate.startAndWait();
+ }
+
+ @Override public final boolean isRunning() {
+ return delegate.isRunning();
+ }
+
+ @Override public final State state() {
+ return delegate.state();
+ }
+
+ @Override public final ListenableFuture<State> stop() {
+ return delegate.stop();
+ }
+
+ @Override public final State stopAndWait() {
+ return delegate.stopAndWait();
+ }
+
+ @Override public final void addListener(Listener listener, Executor executor) {
+ delegate.addListener(listener, executor);
+ }
+
+ /**
+ * Returns the name of this service. {@link AbstractExecutionThreadService}
+ * may include the name in debugging output.
+ *
+ * <p>Subclasses may override this method.
+ *
+ * @since 10.0
+ */
+ protected String getServiceName() {
+ return getClass().getSimpleName();
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AbstractFuture.java b/guava/src/com/google/common/util/concurrent/AbstractFuture.java
new file mode 100644
index 0000000..28b2cc0
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AbstractFuture.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+
+import javax.annotation.Nullable;
+
+/**
+ * An abstract implementation of the {@link ListenableFuture} interface. This
+ * class is preferable to {@link java.util.concurrent.FutureTask} for two
+ * reasons: It implements {@code ListenableFuture}, and it does not implement
+ * {@code Runnable}. (If you want a {@code Runnable} implementation of {@code
+ * ListenableFuture}, create a {@link ListenableFutureTask}, or submit your
+ * tasks to a {@link ListeningExecutorService}.)
+ *
+ * <p>This class implements all methods in {@code ListenableFuture}.
+ * Subclasses should provide a way to set the result of the computation through
+ * the protected methods {@link #set(Object)} and
+ * {@link #setException(Throwable)}. Subclasses may also override {@link
+ * #interruptTask()}, which will be invoked automatically if a call to {@link
+ * #cancel(boolean) cancel(true)} succeeds in canceling the future.
+ *
+ * <p>{@code AbstractFuture} uses an {@link AbstractQueuedSynchronizer} to deal
+ * with concurrency issues and guarantee thread safety.
+ *
+ * <p>The state changing methods all return a boolean indicating success or
+ * failure in changing the future's state. Valid states are running,
+ * completed, failed, or cancelled.
+ *
+ * <p>This class uses an {@link ExecutionList} to guarantee that all registered
+ * listeners will be executed, either when the future finishes or, for listeners
+ * that are added after the future completes, immediately.
+ * {@code Runnable}-{@code Executor} pairs are stored in the execution list but
+ * are not necessarily executed in the order in which they were added. (If a
+ * listener is added after the Future is complete, it will be executed
+ * immediately, even if earlier listeners have not been executed. Additionally,
+ * executors need not guarantee FIFO execution, or different listeners may run
+ * in different executors.)
+ *
+ * @author Sven Mawson
+ * @since 1.0
+ */
+public abstract class AbstractFuture<V> implements ListenableFuture<V> {
+
+ /** Synchronization control for AbstractFutures. */
+ private final Sync<V> sync = new Sync<V>();
+
+ // The execution list to hold our executors.
+ private final ExecutionList executionList = new ExecutionList();
+
+ /**
+ * Constructor for use by subclasses.
+ */
+ protected AbstractFuture() {}
+
+ /*
+ * Improve the documentation of when InterruptedException is thrown. Our
+ * behavior matches the JDK's, but the JDK's documentation is misleading.
+ */
+ /**
+ * {@inheritDoc}
+ *
+ * <p>The default {@link AbstractFuture} implementation throws {@code
+ * InterruptedException} if the current thread is interrupted before or during
+ * the call, even if the value is already available.
+ *
+ * @throws InterruptedException if the current thread was interrupted before
+ * or during the call (optional but recommended).
+ * @throws CancellationException {@inheritDoc}
+ */
+ @Override
+ public V get(long timeout, TimeUnit unit) throws InterruptedException,
+ TimeoutException, ExecutionException {
+ return sync.get(unit.toNanos(timeout));
+ }
+
+ /*
+ * Improve the documentation of when InterruptedException is thrown. Our
+ * behavior matches the JDK's, but the JDK's documentation is misleading.
+ */
+ /**
+ * {@inheritDoc}
+ *
+ * <p>The default {@link AbstractFuture} implementation throws {@code
+ * InterruptedException} if the current thread is interrupted before or during
+ * the call, even if the value is already available.
+ *
+ * @throws InterruptedException if the current thread was interrupted before
+ * or during the call (optional but recommended).
+ * @throws CancellationException {@inheritDoc}
+ */
+ @Override
+ public V get() throws InterruptedException, ExecutionException {
+ return sync.get();
+ }
+
+ @Override
+ public boolean isDone() {
+ return sync.isDone();
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return sync.isCancelled();
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ if (!sync.cancel()) {
+ return false;
+ }
+ executionList.execute();
+ if (mayInterruptIfRunning) {
+ interruptTask();
+ }
+ return true;
+ }
+
+ /**
+ * Subclasses can override this method to implement interruption of the
+ * future's computation. The method is invoked automatically by a successful
+ * call to {@link #cancel(boolean) cancel(true)}.
+ *
+ * <p>The default implementation does nothing.
+ *
+ * @since 10.0
+ */
+ protected void interruptTask() {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 10.0
+ */
+ @Override
+ public void addListener(Runnable listener, Executor exec) {
+ executionList.add(listener, exec);
+ }
+
+ /**
+ * Subclasses should invoke this method to set the result of the computation
+ * to {@code value}. This will set the state of the future to
+ * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the
+ * state was successfully changed.
+ *
+ * @param value the value that was the result of the task.
+ * @return true if the state was successfully changed.
+ */
+ protected boolean set(@Nullable V value) {
+ boolean result = sync.set(value);
+ if (result) {
+ executionList.execute();
+ }
+ return result;
+ }
+
+ /**
+ * Subclasses should invoke this method to set the result of the computation
+ * to an error, {@code throwable}. This will set the state of the future to
+ * {@link AbstractFuture.Sync#COMPLETED} and invoke the listeners if the
+ * state was successfully changed.
+ *
+ * @param throwable the exception that the task failed with.
+ * @return true if the state was successfully changed.
+ * @throws Error if the throwable was an {@link Error}.
+ */
+ protected boolean setException(Throwable throwable) {
+ boolean result = sync.setException(checkNotNull(throwable));
+ if (result) {
+ executionList.execute();
+ }
+
+ // If it's an Error, we want to make sure it reaches the top of the
+ // call stack, so we rethrow it.
+ if (throwable instanceof Error) {
+ throw (Error) throwable;
+ }
+ return result;
+ }
+
+ /**
+ * <p>Following the contract of {@link AbstractQueuedSynchronizer} we create a
+ * private subclass to hold the synchronizer. This synchronizer is used to
+ * implement the blocking and waiting calls as well as to handle state changes
+ * in a thread-safe manner. The current state of the future is held in the
+ * Sync state, and the lock is released whenever the state changes to either
+ * {@link #COMPLETED} or {@link #CANCELLED}.
+ *
+ * <p>To avoid races between threads doing release and acquire, we transition
+ * to the final state in two steps. One thread will successfully CAS from
+ * RUNNING to COMPLETING, that thread will then set the result of the
+ * computation, and only then transition to COMPLETED or CANCELLED.
+ *
+ * <p>We don't use the integer argument passed between acquire methods so we
+ * pass around a -1 everywhere.
+ */
+ static final class Sync<V> extends AbstractQueuedSynchronizer {
+
+ private static final long serialVersionUID = 0L;
+
+ /* Valid states. */
+ static final int RUNNING = 0;
+ static final int COMPLETING = 1;
+ static final int COMPLETED = 2;
+ static final int CANCELLED = 4;
+
+ private V value;
+ private Throwable exception;
+
+ /*
+ * Acquisition succeeds if the future is done, otherwise it fails.
+ */
+ @Override
+ protected int tryAcquireShared(int ignored) {
+ if (isDone()) {
+ return 1;
+ }
+ return -1;
+ }
+
+ /*
+ * We always allow a release to go through, this means the state has been
+ * successfully changed and the result is available.
+ */
+ @Override
+ protected boolean tryReleaseShared(int finalState) {
+ setState(finalState);
+ return true;
+ }
+
+ /**
+ * Blocks until the task is complete or the timeout expires. Throws a
+ * {@link TimeoutException} if the timer expires, otherwise behaves like
+ * {@link #get()}.
+ */
+ V get(long nanos) throws TimeoutException, CancellationException,
+ ExecutionException, InterruptedException {
+
+ // Attempt to acquire the shared lock with a timeout.
+ if (!tryAcquireSharedNanos(-1, nanos)) {
+ throw new TimeoutException("Timeout waiting for task.");
+ }
+
+ return getValue();
+ }
+
+ /**
+ * Blocks until {@link #complete(Object, Throwable, int)} has been
+ * successfully called. Throws a {@link CancellationException} if the task
+ * was cancelled, or a {@link ExecutionException} if the task completed with
+ * an error.
+ */
+ V get() throws CancellationException, ExecutionException,
+ InterruptedException {
+
+ // Acquire the shared lock allowing interruption.
+ acquireSharedInterruptibly(-1);
+ return getValue();
+ }
+
+ /**
+ * Implementation of the actual value retrieval. Will return the value
+ * on success, an exception on failure, a cancellation on cancellation, or
+ * an illegal state if the synchronizer is in an invalid state.
+ */
+ private V getValue() throws CancellationException, ExecutionException {
+ int state = getState();
+ switch (state) {
+ case COMPLETED:
+ if (exception != null) {
+ throw new ExecutionException(exception);
+ } else {
+ return value;
+ }
+
+ case CANCELLED:
+ throw new CancellationException("Task was cancelled.");
+
+ default:
+ throw new IllegalStateException(
+ "Error, synchronizer in invalid state: " + state);
+ }
+ }
+
+ /**
+ * Checks if the state is {@link #COMPLETED} or {@link #CANCELLED}.
+ */
+ boolean isDone() {
+ return (getState() & (COMPLETED | CANCELLED)) != 0;
+ }
+
+ /**
+ * Checks if the state is {@link #CANCELLED}.
+ */
+ boolean isCancelled() {
+ return getState() == CANCELLED;
+ }
+
+ /**
+ * Transition to the COMPLETED state and set the value.
+ */
+ boolean set(@Nullable V v) {
+ return complete(v, null, COMPLETED);
+ }
+
+ /**
+ * Transition to the COMPLETED state and set the exception.
+ */
+ boolean setException(Throwable t) {
+ return complete(null, t, COMPLETED);
+ }
+
+ /**
+ * Transition to the CANCELLED state.
+ */
+ boolean cancel() {
+ return complete(null, null, CANCELLED);
+ }
+
+ /**
+ * Implementation of completing a task. Either {@code v} or {@code t} will
+ * be set but not both. The {@code finalState} is the state to change to
+ * from {@link #RUNNING}. If the state is not in the RUNNING state we
+ * return {@code false} after waiting for the state to be set to a valid
+ * final state ({@link #COMPLETED} or {@link #CANCELLED}).
+ *
+ * @param v the value to set as the result of the computation.
+ * @param t the exception to set as the result of the computation.
+ * @param finalState the state to transition to.
+ */
+ private boolean complete(@Nullable V v, @Nullable Throwable t,
+ int finalState) {
+ boolean doCompletion = compareAndSetState(RUNNING, COMPLETING);
+ if (doCompletion) {
+ // If this thread successfully transitioned to COMPLETING, set the value
+ // and exception and then release to the final state.
+ this.value = v;
+ this.exception = t;
+ releaseShared(finalState);
+ } else if (getState() == COMPLETING) {
+ // If some other thread is currently completing the future, block until
+ // they are done so we can guarantee completion.
+ acquireShared(-1);
+ }
+ return doCompletion;
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AbstractIdleService.java b/guava/src/com/google/common/util/concurrent/AbstractIdleService.java
new file mode 100644
index 0000000..6d49ddd
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AbstractIdleService.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2009 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Throwables;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Base class for services that do not need a thread while "running"
+ * but may need one during startup and shutdown. Subclasses can
+ * implement {@link #startUp} and {@link #shutDown} methods, each
+ * which run in a executor which by default uses a separate thread
+ * for each method.
+ *
+ * @author Chris Nokleberg
+ * @since 1.0
+ */
+@Beta
+public abstract class AbstractIdleService implements Service {
+
+ /* use AbstractService for state management */
+ private final Service delegate = new AbstractService() {
+ @Override protected final void doStart() {
+ executor(State.STARTING).execute(new Runnable() {
+ @Override public void run() {
+ try {
+ startUp();
+ notifyStarted();
+ } catch (Throwable t) {
+ notifyFailed(t);
+ throw Throwables.propagate(t);
+ }
+ }
+ });
+ }
+
+ @Override protected final void doStop() {
+ executor(State.STOPPING).execute(new Runnable() {
+ @Override public void run() {
+ try {
+ shutDown();
+ notifyStopped();
+ } catch (Throwable t) {
+ notifyFailed(t);
+ throw Throwables.propagate(t);
+ }
+ }
+ });
+ }
+ };
+
+ /** Start the service. */
+ protected abstract void startUp() throws Exception;
+
+ /** Stop the service. */
+ protected abstract void shutDown() throws Exception;
+
+ /**
+ * Returns the {@link Executor} that will be used to run this service.
+ * Subclasses may override this method to use a custom {@link Executor}, which
+ * may configure its worker thread with a specific name, thread group or
+ * priority. The returned executor's {@link Executor#execute(Runnable)
+ * execute()} method is called when this service is started and stopped,
+ * and should return promptly.
+ *
+ * @param state {@link Service.State#STARTING} or
+ * {@link Service.State#STOPPING}, used by the default implementation for
+ * naming the thread
+ */
+ protected Executor executor(final State state) {
+ return new Executor() {
+ @Override
+ public void execute(Runnable command) {
+ new Thread(command, getServiceName() + " " + state).start();
+ }
+ };
+ }
+
+ @Override public String toString() {
+ return getServiceName() + " [" + state() + "]";
+ }
+
+ // We override instead of using ForwardingService so that these can be final.
+
+ @Override public final ListenableFuture<State> start() {
+ return delegate.start();
+ }
+
+ @Override public final State startAndWait() {
+ return delegate.startAndWait();
+ }
+
+ @Override public final boolean isRunning() {
+ return delegate.isRunning();
+ }
+
+ @Override public final State state() {
+ return delegate.state();
+ }
+
+ @Override public final ListenableFuture<State> stop() {
+ return delegate.stop();
+ }
+
+ @Override public final State stopAndWait() {
+ return delegate.stopAndWait();
+ }
+
+ @Override public final void addListener(Listener listener, Executor executor) {
+ delegate.addListener(listener, executor);
+ }
+
+ private String getServiceName() {
+ return getClass().getSimpleName();
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java b/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java
new file mode 100644
index 0000000..4e867a6
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AbstractListeningExecutorService.java
@@ -0,0 +1,163 @@
+/*
+ * This file is a modified version of
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/AbstractExecutorService.java?revision=1.35
+ * which contained the following notice:
+ *
+ * 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/
+ *
+ * Rationale for copying:
+ * Guava targets JDK5, whose AbstractExecutorService class lacks the newTaskFor protected
+ * customization methods needed by MoreExecutors.listeningDecorator. This class is a copy of
+ * AbstractExecutorService from the JSR166 CVS repository. It contains the desired methods.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.util.concurrent.MoreExecutors.invokeAnyImpl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Implements {@link ListeningExecutorService} execution methods atop the abstract {@link #execute}
+ * method. More concretely, the {@code submit}, {@code invokeAny} and {@code invokeAll} methods
+ * create {@link ListenableFutureTask} instances and pass them to {@link #execute}.
+ *
+ * <p>In addition to {@link #execute}, subclasses must implement all methods related to shutdown and
+ * termination.
+ *
+ * @author Doug Lea
+ */
+abstract class AbstractListeningExecutorService implements ListeningExecutorService {
+ @Override public ListenableFuture<?> submit(Runnable task) {
+ ListenableFutureTask<Void> ftask = ListenableFutureTask.create(task, null);
+ execute(ftask);
+ return ftask;
+ }
+
+ @Override public <T> ListenableFuture<T> submit(Runnable task, T result) {
+ ListenableFutureTask<T> ftask = ListenableFutureTask.create(task, result);
+ execute(ftask);
+ return ftask;
+ }
+
+ @Override public <T> ListenableFuture<T> submit(Callable<T> task) {
+ ListenableFutureTask<T> ftask = ListenableFutureTask.create(task);
+ execute(ftask);
+ return ftask;
+ }
+
+ @Override public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ try {
+ return invokeAnyImpl(this, tasks, false, 0);
+ } catch (TimeoutException cannotHappen) {
+ throw new AssertionError();
+ }
+ }
+
+ @Override public <T> T invokeAny(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return invokeAnyImpl(this, tasks, true, unit.toNanos(timeout));
+ }
+
+ @Override public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ if (tasks == null) {
+ throw new NullPointerException();
+ }
+ List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+ boolean done = false;
+ try {
+ for (Callable<T> t : tasks) {
+ ListenableFutureTask<T> f = ListenableFutureTask.create(t);
+ futures.add(f);
+ execute(f);
+ }
+ for (Future<T> f : futures) {
+ if (!f.isDone()) {
+ try {
+ f.get();
+ } catch (CancellationException ignore) {
+ } catch (ExecutionException ignore) {
+ }
+ }
+ }
+ done = true;
+ return futures;
+ } finally {
+ if (!done) {
+ for (Future<T> f : futures) {
+ f.cancel(true);
+ }
+ }
+ }
+ }
+
+ @Override public <T> List<Future<T>> invokeAll(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (tasks == null || unit == null) {
+ throw new NullPointerException();
+ }
+ long nanos = unit.toNanos(timeout);
+ List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+ boolean done = false;
+ try {
+ for (Callable<T> t : tasks) {
+ futures.add(ListenableFutureTask.create(t));
+ }
+
+ long lastTime = System.nanoTime();
+
+ // Interleave time checks and calls to execute in case
+ // executor doesn't have any/much parallelism.
+ Iterator<Future<T>> it = futures.iterator();
+ while (it.hasNext()) {
+ execute((Runnable) (it.next()));
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ if (nanos <= 0) {
+ return futures;
+ }
+ }
+
+ for (Future<T> f : futures) {
+ if (!f.isDone()) {
+ if (nanos <= 0) {
+ return futures;
+ }
+ try {
+ f.get(nanos, TimeUnit.NANOSECONDS);
+ } catch (CancellationException ignore) {
+ } catch (ExecutionException ignore) {
+ } catch (TimeoutException toe) {
+ return futures;
+ }
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ }
+ }
+ done = true;
+ return futures;
+ } finally {
+ if (!done) {
+ for (Future<T> f : futures) {
+ f.cancel(true);
+ }
+ }
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java b/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
new file mode 100644
index 0000000..cfc7475
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AbstractScheduledService.java
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.concurrent.GuardedBy;
+
+/**
+ * Base class for services that can implement {@link #startUp} and {@link #shutDown} but while in
+ * the "running" state need to perform a periodic task. Subclasses can implement {@link #startUp},
+ * {@link #shutDown} and also a {@link #runOneIteration} method that will be executed periodically.
+ *
+ * <p>This class uses the {@link ScheduledExecutorService} returned from {@link #executor} to run
+ * the {@link #startUp} and {@link #shutDown} methods and also uses that service to schedule the
+ * {@link #runOneIteration} that will be executed periodically as specified by its
+ * {@link Scheduler}. When this service is asked to stop via {@link #stop} or {@link #stopAndWait},
+ * it will cancel the periodic task (but not interrupt it) and wait for it to stop before running
+ * the {@link #shutDown} method.
+ *
+ * <p>Subclasses are guaranteed that the life cycle methods ({@link #runOneIteration}, {@link
+ * #startUp} and {@link #shutDown}) will never run concurrently. Notably, if any execution of {@link
+ * #runOneIteration} takes longer than its schedule defines, then subsequent executions may start
+ * late. Also, all life cycle methods are executed with a lock held, so subclasses can safely
+ * modify shared state without additional synchronization necessary for visibility to later
+ * executions of the life cycle methods.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * Here is a sketch of a service which crawls a website and uses the scheduling capabilities to
+ * rate limit itself. <pre> {@code
+ * class CrawlingService extends AbstractScheduledService {
+ * private Set<Uri> visited;
+ * private Queue<Uri> toCrawl;
+ * protected void startUp() throws Exception {
+ * toCrawl = readStartingUris();
+ * }
+ *
+ * protected void runOneIteration() throws Exception {
+ * Uri uri = toCrawl.remove();
+ * Collection<Uri> newUris = crawl(uri);
+ * visited.add(uri);
+ * for (Uri newUri : newUris) {
+ * if (!visited.contains(newUri)) { toCrawl.add(newUri); }
+ * }
+ * }
+ *
+ * protected void shutDown() throws Exception {
+ * saveUris(toCrawl);
+ * }
+ *
+ * protected Scheduler scheduler() {
+ * return Scheduler.newFixedRateSchedule(0, 1, TimeUnit.SECONDS);
+ * }
+ * }}</pre>
+ *
+ * This class uses the life cycle methods to read in a list of starting URIs and save the set of
+ * outstanding URIs when shutting down. Also, it takes advantage of the scheduling functionality to
+ * rate limit the number of queries we perform.
+ *
+ * @author Luke Sandberg
+ * @since 11.0
+ */
+@Beta
+public abstract class AbstractScheduledService implements Service {
+ private static final Logger logger = Logger.getLogger(AbstractScheduledService.class.getName());
+
+ /**
+ * A scheduler defines the policy for how the {@link AbstractScheduledService} should run its
+ * task.
+ *
+ * <p>Consider using the {@link #newFixedDelaySchedule} and {@link #newFixedRateSchedule} factory
+ * methods, these provide {@link Scheduler} instances for the common use case of running the
+ * service with a fixed schedule. If more flexibility is needed then consider subclassing the
+ * {@link CustomScheduler} abstract class in preference to creating your own {@link Scheduler}
+ * implementation.
+ *
+ * @author Luke Sandberg
+ * @since 11.0
+ */
+ public abstract static class Scheduler {
+ /**
+ * Returns a {@link Scheduler} that schedules the task using the
+ * {@link ScheduledExecutorService#scheduleWithFixedDelay} method.
+ *
+ * @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
+ */
+ public static Scheduler newFixedDelaySchedule(final long initialDelay, final long delay,
+ final TimeUnit unit) {
+ return new Scheduler() {
+ @Override
+ public Future<?> schedule(AbstractService service, ScheduledExecutorService executor,
+ Runnable task) {
+ return executor.scheduleWithFixedDelay(task, initialDelay, delay, unit);
+ }
+ };
+ }
+
+ /**
+ * Returns a {@link Scheduler} that schedules the task using the
+ * {@link ScheduledExecutorService#scheduleAtFixedRate} method.
+ *
+ * @param initialDelay the time to delay first execution
+ * @param period the period between successive executions of the task
+ * @param unit the time unit of the initialDelay and period parameters
+ */
+ public static Scheduler newFixedRateSchedule(final long initialDelay, final long period,
+ final TimeUnit unit) {
+ return new Scheduler() {
+ @Override
+ public Future<?> schedule(AbstractService service, ScheduledExecutorService executor,
+ Runnable task) {
+ return executor.scheduleAtFixedRate(task, initialDelay, period, unit);
+ }
+ };
+ }
+
+ /** Schedules the task to run on the provided executor on behalf of the service. */
+ abstract Future<?> schedule(AbstractService service, ScheduledExecutorService executor,
+ Runnable runnable);
+
+ private Scheduler() {}
+ }
+
+ /* use AbstractService for state management */
+ private final AbstractService delegate = new AbstractService() {
+
+ // A handle to the running task so that we can stop it when a shutdown has been requested.
+ // These two fields are volatile because their values will be accessed from multiple threads.
+ private volatile Future<?> runningTask;
+ private volatile ScheduledExecutorService executorService;
+
+ // This lock protects the task so we can ensure that none of the template methods (startUp,
+ // shutDown or runOneIteration) run concurrently with one another.
+ private final ReentrantLock lock = new ReentrantLock();
+
+ private final Runnable task = new Runnable() {
+ @Override public void run() {
+ lock.lock();
+ try {
+ AbstractScheduledService.this.runOneIteration();
+ } catch (Throwable t) {
+ try {
+ shutDown();
+ } catch (Exception ignored) {
+ logger.log(Level.WARNING,
+ "Error while attempting to shut down the service after failure.", ignored);
+ }
+ notifyFailed(t);
+ throw Throwables.propagate(t);
+ } finally {
+ lock.unlock();
+ }
+ }
+ };
+
+ @Override protected final void doStart() {
+ executorService = executor();
+ executorService.execute(new Runnable() {
+ @Override public void run() {
+ lock.lock();
+ try {
+ startUp();
+ runningTask = scheduler().schedule(delegate, executorService, task);
+ notifyStarted();
+ } catch (Throwable t) {
+ notifyFailed(t);
+ throw Throwables.propagate(t);
+ } finally {
+ lock.unlock();
+ }
+ }
+ });
+ }
+
+ @Override protected final void doStop() {
+ runningTask.cancel(false);
+ executorService.execute(new Runnable() {
+ @Override public void run() {
+ try {
+ lock.lock();
+ try {
+ if (state() != State.STOPPING) {
+ // This means that the state has changed since we were scheduled. This implies that
+ // an execution of runOneIteration has thrown an exception and we have transitioned
+ // to a failed state, also this means that shutDown has already been called, so we
+ // do not want to call it again.
+ return;
+ }
+ shutDown();
+ } finally {
+ lock.unlock();
+ }
+ notifyStopped();
+ } catch (Throwable t) {
+ notifyFailed(t);
+ throw Throwables.propagate(t);
+ }
+ }
+ });
+ }
+ };
+
+ /**
+ * Run one iteration of the scheduled task. If any invocation of this method throws an exception,
+ * the service will transition to the {@link Service.State#FAILED} state and this method will no
+ * longer be called.
+ */
+ protected abstract void runOneIteration() throws Exception;
+
+ /**
+ * Start the service.
+ *
+ * <p>By default this method does nothing.
+ */
+ protected void startUp() throws Exception {}
+
+ /**
+ * Stop the service. This is guaranteed not to run concurrently with {@link #runOneIteration}.
+ *
+ * <p>By default this method does nothing.
+ */
+ protected void shutDown() throws Exception {}
+
+ /**
+ * Returns the {@link Scheduler} object used to configure this service. This method will only be
+ * called once.
+ */
+ protected abstract Scheduler scheduler();
+
+ /**
+ * Returns the {@link ScheduledExecutorService} that will be used to execute the {@link #startUp},
+ * {@link #runOneIteration} and {@link #shutDown} methods. The executor will not be
+ * {@link ScheduledExecutorService#shutdown} when this service stops. Subclasses may override this
+ * method to use a custom {@link ScheduledExecutorService} instance.
+ *
+ * <p>By default this returns a new {@link ScheduledExecutorService} with a single thread thread
+ * pool. This method will only be called once.
+ */
+ protected ScheduledExecutorService executor() {
+ return Executors.newSingleThreadScheduledExecutor();
+ }
+
+ @Override public String toString() {
+ return getClass().getSimpleName() + " [" + state() + "]";
+ }
+
+ // We override instead of using ForwardingService so that these can be final.
+
+ @Override public final ListenableFuture<State> start() {
+ return delegate.start();
+ }
+
+ @Override public final State startAndWait() {
+ return delegate.startAndWait();
+ }
+
+ @Override public final boolean isRunning() {
+ return delegate.isRunning();
+ }
+
+ @Override public final State state() {
+ return delegate.state();
+ }
+
+ @Override public final ListenableFuture<State> stop() {
+ return delegate.stop();
+ }
+
+ @Override public final State stopAndWait() {
+ return delegate.stopAndWait();
+ }
+
+ @Override public final void addListener(Listener listener, Executor executor) {
+ delegate.addListener(listener, executor);
+ }
+
+ /**
+ * A {@link Scheduler} that provides a convenient way for the {@link AbstractScheduledService} to
+ * use a dynamically changing schedule. After every execution of the task, assuming it hasn't
+ * been cancelled, the {@link #getNextSchedule} method will be called.
+ *
+ * @author Luke Sandberg
+ * @since 11.0
+ */
+ @Beta
+ public abstract static class CustomScheduler extends Scheduler {
+
+ /**
+ * A callable class that can reschedule itself using a {@link CustomScheduler}.
+ */
+ private class ReschedulableCallable extends ForwardingFuture<Void> implements Callable<Void> {
+
+ /** The underlying task. */
+ private final Runnable wrappedRunnable;
+
+ /** The executor on which this Callable will be scheduled. */
+ private final ScheduledExecutorService executor;
+
+ /**
+ * The service that is managing this callable. This is used so that failure can be
+ * reported properly.
+ */
+ private final AbstractService service;
+
+ /**
+ * This lock is used to ensure safe and correct cancellation, it ensures that a new task is
+ * not scheduled while a cancel is ongoing. Also it protects the currentFuture variable to
+ * ensure that it is assigned atomically with being scheduled.
+ */
+ private final ReentrantLock lock = new ReentrantLock();
+
+ /** The future that represents the next execution of this task.*/
+ @GuardedBy("lock")
+ private Future<Void> currentFuture;
+
+ ReschedulableCallable(AbstractService service, ScheduledExecutorService executor,
+ Runnable runnable) {
+ this.wrappedRunnable = runnable;
+ this.executor = executor;
+ this.service = service;
+ }
+
+ @Override
+ public Void call() throws Exception {
+ wrappedRunnable.run();
+ reschedule();
+ return null;
+ }
+
+ /**
+ * Atomically reschedules this task and assigns the new future to {@link #currentFuture}.
+ */
+ public void reschedule() {
+ // We reschedule ourselves with a lock held for two reasons. 1. we want to make sure that
+ // cancel calls cancel on the correct future. 2. we want to make sure that the assignment
+ // to currentFuture doesn't race with itself so that currentFuture is assigned in the
+ // correct order.
+ lock.lock();
+ try {
+ if (currentFuture == null || !currentFuture.isCancelled()) {
+ final Schedule schedule = CustomScheduler.this.getNextSchedule();
+ currentFuture = executor.schedule(this, schedule.delay, schedule.unit);
+ }
+ } catch (Throwable e) {
+ // If an exception is thrown by the subclass then we need to make sure that the service
+ // notices and transitions to the FAILED state. We do it by calling notifyFailed directly
+ // because the service does not monitor the state of the future so if the exception is not
+ // caught and forwarded to the service the task would stop executing but the service would
+ // have no idea.
+ service.notifyFailed(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ // N.B. Only protect cancel and isCancelled because those are the only methods that are
+ // invoked by the AbstractScheduledService.
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ // Ensure that a task cannot be rescheduled while a cancel is ongoing.
+ lock.lock();
+ try {
+ return currentFuture.cancel(mayInterruptIfRunning);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ protected Future<Void> delegate() {
+ throw new UnsupportedOperationException("Only cancel is supported by this future");
+ }
+ }
+
+ @Override
+ final Future<?> schedule(AbstractService service, ScheduledExecutorService executor,
+ Runnable runnable) {
+ ReschedulableCallable task = new ReschedulableCallable(service, executor, runnable);
+ task.reschedule();
+ return task;
+ }
+
+ /**
+ * A value object that represents an absolute delay until a task should be invoked.
+ *
+ * @author Luke Sandberg
+ * @since 11.0
+ */
+ @Beta
+ protected static final class Schedule {
+
+ private final long delay;
+ private final TimeUnit unit;
+
+ /**
+ * @param delay the time from now to delay execution
+ * @param unit the time unit of the delay parameter
+ */
+ public Schedule(long delay, TimeUnit unit) {
+ this.delay = delay;
+ this.unit = Preconditions.checkNotNull(unit);
+ }
+ }
+
+ /**
+ * Calculates the time at which to next invoke the task.
+ *
+ * <p>This is guaranteed to be called immediately after the task has completed an iteration and
+ * on the same thread as the previous execution of {@link
+ * AbstractScheduledService#runOneIteration}.
+ *
+ * @return a schedule that defines the delay before the next execution.
+ */
+ protected abstract Schedule getNextSchedule() throws Exception;
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AbstractService.java b/guava/src/com/google/common/util/concurrent/AbstractService.java
new file mode 100644
index 0000000..a2e14fe
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AbstractService.java
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2009 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Queues;
+import com.google.common.util.concurrent.Service.State; // javadoc needs this
+
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Base class for implementing services that can handle {@link #doStart} and {@link #doStop}
+ * requests, responding to them with {@link #notifyStarted()} and {@link #notifyStopped()}
+ * callbacks. Its subclasses must manage threads manually; consider
+ * {@link AbstractExecutionThreadService} if you need only a single execution thread.
+ *
+ * @author Jesse Wilson
+ * @author Luke Sandberg
+ * @since 1.0
+ */
+@Beta
+public abstract class AbstractService implements Service {
+ private static final Logger logger = Logger.getLogger(AbstractService.class.getName());
+ private final ReentrantLock lock = new ReentrantLock();
+
+ private final Transition startup = new Transition();
+ private final Transition shutdown = new Transition();
+
+ /**
+ * The listeners to notify during a state transition.
+ */
+ @GuardedBy("lock")
+ private final List<ListenerExecutorPair> listeners = Lists.newArrayList();
+
+ /**
+ * The queue of listeners that are waiting to be executed.
+ *
+ * <p>Enqueue operations should be protected by {@link #lock} while dequeue operations should be
+ * protected by the implicit lock on this object. Dequeue operations should be executed atomically
+ * with the execution of the {@link Runnable} and additionally the {@link #lock} should not be
+ * held when the listeners are being executed. Use {@link #executeListeners} for this operation.
+ * This is necessary to ensure that elements on the queue are executed in the correct order.
+ * Enqueue operations should be protected so that listeners are added in the correct order. We use
+ * a concurrent queue implementation so that enqueues can be executed concurrently with dequeues.
+ */
+ @GuardedBy("queuedListeners")
+ private final Queue<Runnable> queuedListeners = Queues.newConcurrentLinkedQueue();
+
+ /**
+ * The current state of the service. This should be written with the lock held but can be read
+ * without it because it is an immutable object in a volatile field. This is desirable so that
+ * methods like {@link #state}, {@link #failureCause} and notably {@link #toString} can be run
+ * without grabbing the lock.
+ *
+ * <p>To update this field correctly the lock must be held to guarantee that the state is
+ * consistent.
+ */
+ @GuardedBy("lock")
+ private volatile StateSnapshot snapshot = new StateSnapshot(State.NEW);
+
+ protected AbstractService() {
+ // Add a listener to update the futures. This needs to be added first so that it is executed
+ // before the other listeners. This way the other listeners can access the completed futures.
+ addListener(
+ new Listener() {
+ @Override public void starting() {}
+
+ @Override public void running() {
+ startup.set(State.RUNNING);
+ }
+
+ @Override public void stopping(State from) {
+ if (from == State.STARTING) {
+ startup.set(State.STOPPING);
+ }
+ }
+
+ @Override public void terminated(State from) {
+ if (from == State.NEW) {
+ startup.set(State.TERMINATED);
+ }
+ shutdown.set(State.TERMINATED);
+ }
+
+ @Override public void failed(State from, Throwable failure) {
+ switch (from) {
+ case STARTING:
+ startup.setException(failure);
+ shutdown.setException(new Exception("Service failed to start.", failure));
+ break;
+ case RUNNING:
+ shutdown.setException(new Exception("Service failed while running", failure));
+ break;
+ case STOPPING:
+ shutdown.setException(failure);
+ break;
+ case TERMINATED: /* fall-through */
+ case FAILED: /* fall-through */
+ case NEW: /* fall-through */
+ default:
+ throw new AssertionError("Unexpected from state: " + from);
+ }
+ }
+ },
+ MoreExecutors.sameThreadExecutor());
+ }
+
+ /**
+ * This method is called by {@link #start} to initiate service startup. The invocation of this
+ * method should cause a call to {@link #notifyStarted()}, either during this method's run, or
+ * after it has returned. If startup fails, the invocation should cause a call to
+ * {@link #notifyFailed(Throwable)} instead.
+ *
+ * <p>This method should return promptly; prefer to do work on a different thread where it is
+ * convenient. It is invoked exactly once on service startup, even when {@link #start} is called
+ * multiple times.
+ */
+ protected abstract void doStart();
+
+ /**
+ * This method should be used to initiate service shutdown. The invocation of this method should
+ * cause a call to {@link #notifyStopped()}, either during this method's run, or after it has
+ * returned. If shutdown fails, the invocation should cause a call to
+ * {@link #notifyFailed(Throwable)} instead.
+ *
+ * <p> This method should return promptly; prefer to do work on a different thread where it is
+ * convenient. It is invoked exactly once on service shutdown, even when {@link #stop} is called
+ * multiple times.
+ */
+ protected abstract void doStop();
+
+ @Override
+ public final ListenableFuture<State> start() {
+ lock.lock();
+ try {
+ if (snapshot.state == State.NEW) {
+ snapshot = new StateSnapshot(State.STARTING);
+ starting();
+ doStart();
+ }
+ } catch (Throwable startupFailure) {
+ notifyFailed(startupFailure);
+ } finally {
+ lock.unlock();
+ executeListeners();
+ }
+
+ return startup;
+ }
+
+ @Override
+ public final ListenableFuture<State> stop() {
+ lock.lock();
+ try {
+ switch (snapshot.state) {
+ case NEW:
+ snapshot = new StateSnapshot(State.TERMINATED);
+ terminated(State.NEW);
+ break;
+ case STARTING:
+ snapshot = new StateSnapshot(State.STARTING, true, null);
+ stopping(State.STARTING);
+ break;
+ case RUNNING:
+ snapshot = new StateSnapshot(State.STOPPING);
+ stopping(State.RUNNING);
+ doStop();
+ break;
+ case STOPPING:
+ case TERMINATED:
+ case FAILED:
+ // do nothing
+ break;
+ default:
+ throw new AssertionError("Unexpected state: " + snapshot.state);
+ }
+ } catch (Throwable shutdownFailure) {
+ notifyFailed(shutdownFailure);
+ } finally {
+ lock.unlock();
+ executeListeners();
+ }
+
+ return shutdown;
+ }
+
+ @Override
+ public State startAndWait() {
+ return Futures.getUnchecked(start());
+ }
+
+ @Override
+ public State stopAndWait() {
+ return Futures.getUnchecked(stop());
+ }
+
+ /**
+ * Implementing classes should invoke this method once their service has started. It will cause
+ * the service to transition from {@link State#STARTING} to {@link State#RUNNING}.
+ *
+ * @throws IllegalStateException if the service is not {@link State#STARTING}.
+ */
+ protected final void notifyStarted() {
+ lock.lock();
+ try {
+ if (snapshot.state != State.STARTING) {
+ IllegalStateException failure = new IllegalStateException(
+ "Cannot notifyStarted() when the service is " + snapshot.state);
+ notifyFailed(failure);
+ throw failure;
+ }
+
+ if (snapshot.shutdownWhenStartupFinishes) {
+ snapshot = new StateSnapshot(State.STOPPING);
+ // We don't call listeners here because we already did that when we set the
+ // shutdownWhenStartupFinishes flag.
+ doStop();
+ } else {
+ snapshot = new StateSnapshot(State.RUNNING);
+ running();
+ }
+ } finally {
+ lock.unlock();
+ executeListeners();
+ }
+ }
+
+ /**
+ * Implementing classes should invoke this method once their service has stopped. It will cause
+ * the service to transition from {@link State#STOPPING} to {@link State#TERMINATED}.
+ *
+ * @throws IllegalStateException if the service is neither {@link State#STOPPING} nor
+ * {@link State#RUNNING}.
+ */
+ protected final void notifyStopped() {
+ lock.lock();
+ try {
+ if (snapshot.state != State.STOPPING && snapshot.state != State.RUNNING) {
+ IllegalStateException failure = new IllegalStateException(
+ "Cannot notifyStopped() when the service is " + snapshot.state);
+ notifyFailed(failure);
+ throw failure;
+ }
+ State previous = snapshot.state;
+ snapshot = new StateSnapshot(State.TERMINATED);
+ terminated(previous);
+ } finally {
+ lock.unlock();
+ executeListeners();
+ }
+ }
+
+ /**
+ * Invoke this method to transition the service to the {@link State#FAILED}. The service will
+ * <b>not be stopped</b> if it is running. Invoke this method when a service has failed critically
+ * or otherwise cannot be started nor stopped.
+ */
+ protected final void notifyFailed(Throwable cause) {
+ checkNotNull(cause);
+
+ lock.lock();
+ try {
+ switch (snapshot.state) {
+ case NEW:
+ case TERMINATED:
+ throw new IllegalStateException("Failed while in state:" + snapshot.state, cause);
+ case RUNNING:
+ case STARTING:
+ case STOPPING:
+ State previous = snapshot.state;
+ snapshot = new StateSnapshot(State.FAILED, false, cause);
+ failed(previous, cause);
+ break;
+ case FAILED:
+ // Do nothing
+ break;
+ default:
+ throw new AssertionError("Unexpected state: " + snapshot.state);
+ }
+ } finally {
+ lock.unlock();
+ executeListeners();
+ }
+ }
+
+ @Override
+ public final boolean isRunning() {
+ return state() == State.RUNNING;
+ }
+
+ @Override
+ public final State state() {
+ return snapshot.externalState();
+ }
+
+ @Override
+ public final void addListener(Listener listener, Executor executor) {
+ checkNotNull(listener, "listener");
+ checkNotNull(executor, "executor");
+ lock.lock();
+ try {
+ if (snapshot.state != State.TERMINATED && snapshot.state != State.FAILED) {
+ listeners.add(new ListenerExecutorPair(listener, executor));
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override public String toString() {
+ return getClass().getSimpleName() + " [" + state() + "]";
+ }
+
+ /**
+ * A change from one service state to another, plus the result of the change.
+ */
+ private class Transition extends AbstractFuture<State> {
+ @Override
+ public State get(long timeout, TimeUnit unit)
+ throws InterruptedException, TimeoutException, ExecutionException {
+ try {
+ return super.get(timeout, unit);
+ } catch (TimeoutException e) {
+ throw new TimeoutException(AbstractService.this.toString());
+ }
+ }
+ }
+
+ /**
+ * Attempts to execute all the listeners in {@link #queuedListeners} while not holding the
+ * {@link #lock}.
+ */
+ private void executeListeners() {
+ if (!lock.isHeldByCurrentThread()) {
+ synchronized (queuedListeners) {
+ Runnable listener;
+ while ((listener = queuedListeners.poll()) != null) {
+ listener.run();
+ }
+ }
+ }
+ }
+
+ @GuardedBy("lock")
+ private void starting() {
+ for (final ListenerExecutorPair pair : listeners) {
+ queuedListeners.add(new Runnable() {
+ @Override public void run() {
+ pair.execute(new Runnable() {
+ @Override public void run() {
+ pair.listener.starting();
+ }
+ });
+ }
+ });
+ }
+ }
+
+ @GuardedBy("lock")
+ private void running() {
+ for (final ListenerExecutorPair pair : listeners) {
+ queuedListeners.add(new Runnable() {
+ @Override public void run() {
+ pair.execute(new Runnable() {
+ @Override public void run() {
+ pair.listener.running();
+ }
+ });
+ }
+ });
+ }
+ }
+
+ @GuardedBy("lock")
+ private void stopping(final State from) {
+ for (final ListenerExecutorPair pair : listeners) {
+ queuedListeners.add(new Runnable() {
+ @Override public void run() {
+ pair.execute(new Runnable() {
+ @Override public void run() {
+ pair.listener.stopping(from);
+ }
+ });
+ }
+ });
+ }
+ }
+
+ @GuardedBy("lock")
+ private void terminated(final State from) {
+ for (final ListenerExecutorPair pair : listeners) {
+ queuedListeners.add(new Runnable() {
+ @Override public void run() {
+ pair.execute(new Runnable() {
+ @Override public void run() {
+ pair.listener.terminated(from);
+ }
+ });
+ }
+ });
+ }
+ // There are no more state transitions so we can clear this out.
+ listeners.clear();
+ }
+
+ @GuardedBy("lock")
+ private void failed(final State from, final Throwable cause) {
+ for (final ListenerExecutorPair pair : listeners) {
+ queuedListeners.add(new Runnable() {
+ @Override public void run() {
+ pair.execute(new Runnable() {
+ @Override public void run() {
+ pair.listener.failed(from, cause);
+ }
+ });
+ }
+ });
+ }
+ // There are no more state transitions so we can clear this out.
+ listeners.clear();
+ }
+
+ /** A simple holder for a listener and its executor. */
+ private static class ListenerExecutorPair {
+ final Listener listener;
+ final Executor executor;
+
+ ListenerExecutorPair(Listener listener, Executor executor) {
+ this.listener = listener;
+ this.executor = executor;
+ }
+
+ /**
+ * Executes the given {@link Runnable} on {@link #executor} logging and swallowing all
+ * exceptions
+ */
+ void execute(Runnable runnable) {
+ try {
+ executor.execute(runnable);
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "Exception while executing listener " + listener
+ + " with executor " + executor, e);
+ }
+ }
+ }
+
+ /**
+ * An immutable snapshot of the current state of the service. This class represents a consistent
+ * snapshot of the state and therefore it can be used to answer simple queries without needing to
+ * grab a lock.
+ */
+ @Immutable
+ private static final class StateSnapshot {
+ /**
+ * The internal state, which equals external state unless
+ * shutdownWhenStartupFinishes is true.
+ */
+ final State state;
+
+ /**
+ * If true, the user requested a shutdown while the service was still starting
+ * up.
+ */
+ final boolean shutdownWhenStartupFinishes;
+
+ /**
+ * The exception that caused this service to fail. This will be {@code null}
+ * unless the service has failed.
+ */
+ @Nullable
+ final Throwable failure;
+
+ StateSnapshot(State internalState) {
+ this(internalState, false, null);
+ }
+
+ StateSnapshot(State internalState, boolean shutdownWhenStartupFinishes, Throwable failure) {
+ checkArgument(!shutdownWhenStartupFinishes || internalState == State.STARTING,
+ "shudownWhenStartupFinishes can only be set if state is STARTING. Got %s instead.",
+ internalState);
+ checkArgument(!(failure != null ^ internalState == State.FAILED),
+ "A failure cause should be set if and only if the state is failed. Got %s and %s "
+ + "instead.", internalState, failure);
+ this.state = internalState;
+ this.shutdownWhenStartupFinishes = shutdownWhenStartupFinishes;
+ this.failure = failure;
+ }
+
+ /** @see Service#state() */
+ State externalState() {
+ if (shutdownWhenStartupFinishes && state == State.STARTING) {
+ return State.STOPPING;
+ } else {
+ return state;
+ }
+ }
+
+ /** @see Service#failureCause() */
+ Throwable failureCause() {
+ checkState(state == State.FAILED,
+ "failureCause() is only valid if the service has failed, service is %s", state);
+ return failure;
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AsyncFunction.java b/guava/src/com/google/common/util/concurrent/AsyncFunction.java
new file mode 100644
index 0000000..441c029
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AsyncFunction.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.Future;
+
+/**
+ * Transforms a value, possibly asynchronously. For an example usage and more
+ * information, see {@link Futures#transform(ListenableFuture, AsyncFunction)}.
+ *
+ * @author Chris Povirk
+ * @since 11.0
+ */
+@Beta
+public interface AsyncFunction<I, O> {
+ /**
+ * Returns an output {@code Future} to use in place of the given {@code
+ * input}. The output {@code Future} need not be {@linkplain Future#isDone
+ * done}, making {@code AsyncFunction} suitable for asynchronous derivations.
+ *
+ * <p>Throwing an exception from this method is equivalent to returning a
+ * failing {@code Future}.
+ */
+ ListenableFuture<O> apply(I input) throws Exception;
+}
diff --git a/guava/src/com/google/common/util/concurrent/AtomicDouble.java b/guava/src/com/google/common/util/concurrent/AtomicDouble.java
new file mode 100644
index 0000000..615d7a9
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AtomicDouble.java
@@ -0,0 +1,257 @@
+/*
+ * 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/
+ */
+
+/*
+ * Source:
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/extra/AtomicDouble.java?revision=1.13
+ * (Modified to adapt to guava coding conventions and
+ * to use AtomicLongFieldUpdater instead of sun.misc.Unsafe)
+ */
+
+package com.google.common.util.concurrent;
+
+import static java.lang.Double.doubleToRawLongBits;
+import static java.lang.Double.longBitsToDouble;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.atomic.AtomicLongFieldUpdater;
+
+/**
+ * A {@code double} 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
+ * AtomicDouble} is used in applications such as atomic accumulation,
+ * and cannot be used as a replacement for a {@link Double}. However,
+ * this class does extend {@code Number} to allow uniform access by
+ * tools and utilities that deal with numerically-based classes.
+ *
+ * <p><a name="bitEquals">This class compares primitive {@code double}
+ * values in methods such as {@link #compareAndSet} by comparing their
+ * bitwise representation using {@link Double#doubleToRawLongBits},
+ * which differs from both the primitive double {@code ==} operator
+ * and from {@link Double#equals}, as if implemented by:
+ * <pre> {@code
+ * static boolean bitEquals(double x, double y) {
+ * long xBits = Double.doubleToRawLongBits(x);
+ * long yBits = Double.doubleToRawLongBits(y);
+ * return xBits == yBits;
+ * }}</pre>
+ *
+ * <p>It is possible to write a more scalable updater, at the cost of
+ * giving up strict atomicity. See for example
+ * <a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/DoubleAdder.html"
+ * DoubleAdder>
+ * and
+ * <a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/DoubleMaxUpdater.html"
+ * DoubleMaxUpdater>.
+ *
+ * @author Doug Lea
+ * @author Martin Buchholz
+ * @since 11.0
+ */
+@Beta
+public class AtomicDouble extends Number implements java.io.Serializable {
+ private static final long serialVersionUID = 0L;
+
+ private transient volatile long value;
+
+ private static final AtomicLongFieldUpdater<AtomicDouble> updater =
+ AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value");
+
+ /**
+ * Creates a new {@code AtomicDouble} with the given initial value.
+ *
+ * @param initialValue the initial value
+ */
+ public AtomicDouble(double initialValue) {
+ value = doubleToRawLongBits(initialValue);
+ }
+
+ /**
+ * Creates a new {@code AtomicDouble} with initial value {@code 0.0}.
+ */
+ public AtomicDouble() {
+ // assert doubleToRawLongBits(0.0) == 0L;
+ }
+
+ /**
+ * Gets the current value.
+ *
+ * @return the current value
+ */
+ public final double get() {
+ return longBitsToDouble(value);
+ }
+
+ /**
+ * Sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public final void set(double newValue) {
+ long next = doubleToRawLongBits(newValue);
+ value = next;
+ }
+
+ /**
+ * Eventually sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public final void lazySet(double newValue) {
+ set(newValue);
+ // TODO(user): replace with code below when jdk5 support is dropped.
+ // long next = doubleToRawLongBits(newValue);
+ // updater.lazySet(this, next);
+ }
+
+ /**
+ * Atomically sets to the given value and returns the old value.
+ *
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final double getAndSet(double newValue) {
+ long next = doubleToRawLongBits(newValue);
+ return longBitsToDouble(updater.getAndSet(this, next));
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value is <a href="#bitEquals">bitwise equal</a>
+ * to 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 bitwise equal to the expected value.
+ */
+ public final boolean compareAndSet(double expect, double update) {
+ return updater.compareAndSet(this,
+ doubleToRawLongBits(expect),
+ doubleToRawLongBits(update));
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value is <a href="#bitEquals">bitwise equal</a>
+ * to the expected value.
+ *
+ * <p>May <a
+ * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
+ * fail spuriously</a>
+ * and does not provide ordering guarantees, 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(double expect, double update) {
+ return updater.weakCompareAndSet(this,
+ doubleToRawLongBits(expect),
+ doubleToRawLongBits(update));
+ }
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public final double getAndAdd(double delta) {
+ while (true) {
+ long current = value;
+ double currentVal = longBitsToDouble(current);
+ double nextVal = currentVal + delta;
+ long next = doubleToRawLongBits(nextVal);
+ if (updater.compareAndSet(this, current, next)) {
+ return currentVal;
+ }
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public final double addAndGet(double delta) {
+ while (true) {
+ long current = value;
+ double currentVal = longBitsToDouble(current);
+ double nextVal = currentVal + delta;
+ long next = doubleToRawLongBits(nextVal);
+ if (updater.compareAndSet(this, current, next)) {
+ return nextVal;
+ }
+ }
+ }
+
+ /**
+ * Returns the String representation of the current value.
+ * @return the String representation of the current value
+ */
+ public String toString() {
+ return Double.toString(get());
+ }
+
+ /**
+ * Returns the value of this {@code AtomicDouble} as an {@code int}
+ * after a narrowing primitive conversion.
+ */
+ public int intValue() {
+ return (int) get();
+ }
+
+ /**
+ * Returns the value of this {@code AtomicDouble} as a {@code long}
+ * after a narrowing primitive conversion.
+ */
+ public long longValue() {
+ return (long) get();
+ }
+
+ /**
+ * Returns the value of this {@code AtomicDouble} as a {@code float}
+ * after a narrowing primitive conversion.
+ */
+ public float floatValue() {
+ return (float) get();
+ }
+
+ /**
+ * Returns the value of this {@code AtomicDouble} as a {@code double}.
+ */
+ public double doubleValue() {
+ return get();
+ }
+
+ /**
+ * Saves the state to a stream (that is, serializes it).
+ *
+ * @serialData The current value is emitted (a {@code double}).
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ s.defaultWriteObject();
+
+ s.writeDouble(get());
+ }
+
+ /**
+ * Reconstitutes the instance from a stream (that is, deserializes it).
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+
+ set(s.readDouble());
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AtomicDoubleArray.java b/guava/src/com/google/common/util/concurrent/AtomicDoubleArray.java
new file mode 100644
index 0000000..8da0195
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AtomicDoubleArray.java
@@ -0,0 +1,271 @@
+/*
+ * 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/
+ */
+
+/*
+ * Source:
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/extra/AtomicDoubleArray.java?revision=1.5
+ * (Modified to adapt to guava coding conventions and
+ * to use AtomicLongArray instead of sun.misc.Unsafe)
+ */
+
+package com.google.common.util.concurrent;
+
+import static java.lang.Double.doubleToRawLongBits;
+import static java.lang.Double.longBitsToDouble;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.atomic.AtomicLongArray;
+
+/**
+ * A {@code double} 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.
+ *
+ * <p><a name="bitEquals">This class compares primitive {@code double}
+ * values in methods such as {@link #compareAndSet} by comparing their
+ * bitwise representation using {@link Double#doubleToRawLongBits},
+ * which differs from both the primitive double {@code ==} operator
+ * and from {@link Double#equals}, as if implemented by:
+ * <pre> {@code
+ * static boolean bitEquals(double x, double y) {
+ * long xBits = Double.doubleToRawLongBits(x);
+ * long yBits = Double.doubleToRawLongBits(y);
+ * return xBits == yBits;
+ * }}</pre>
+ *
+ * @author Doug Lea
+ * @author Martin Buchholz
+ * @since 11.0
+ */
+@Beta
+public class AtomicDoubleArray implements java.io.Serializable {
+ private static final long serialVersionUID = 0L;
+
+ // Making this non-final is the lesser evil according to Effective
+ // Java 2nd Edition Item 76: Write readObject methods defensively.
+ private transient AtomicLongArray longs;
+
+ /**
+ * Creates a new {@code AtomicDoubleArray} of the given length,
+ * with all elements initially zero.
+ *
+ * @param length the length of the array
+ */
+ public AtomicDoubleArray(int length) {
+ this.longs = new AtomicLongArray(length);
+ }
+
+ /**
+ * Creates a new {@code AtomicDoubleArray} 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 AtomicDoubleArray(double[] array) {
+ final int len = array.length;
+ long[] longArray = new long[len];
+ for (int i = 0; i < len; i++) {
+ longArray[i] = doubleToRawLongBits(array[i]);
+ }
+ this.longs = new AtomicLongArray(longArray);
+ }
+
+ /**
+ * Returns the length of the array.
+ *
+ * @return the length of the array
+ */
+ public final int length() {
+ return longs.length();
+ }
+
+ /**
+ * Gets the current value at position {@code i}.
+ *
+ * @param i the index
+ * @return the current value
+ */
+ public final double get(int i) {
+ return longBitsToDouble(longs.get(i));
+ }
+
+ /**
+ * 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, double newValue) {
+ long next = doubleToRawLongBits(newValue);
+ longs.set(i, next);
+ }
+
+ /**
+ * Eventually sets the element at position {@code i} to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ */
+ public final void lazySet(int i, double newValue) {
+ set(i, newValue);
+ // TODO(user): replace with code below when jdk5 support is dropped.
+ // long next = doubleToRawLongBits(newValue);
+ // longs.lazySet(i, next);
+ }
+
+ /**
+ * 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 double getAndSet(int i, double newValue) {
+ long next = doubleToRawLongBits(newValue);
+ return longBitsToDouble(longs.getAndSet(i, next));
+ }
+
+ /**
+ * Atomically sets the element at position {@code i} to the given
+ * updated value
+ * if the current value is <a href="#bitEquals">bitwise equal</a>
+ * to the expected value.
+ *
+ * @param i the index
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that
+ * the actual value was not equal to the expected value.
+ */
+ public final boolean compareAndSet(int i, double expect, double update) {
+ return longs.compareAndSet(i,
+ doubleToRawLongBits(expect),
+ doubleToRawLongBits(update));
+ }
+
+ /**
+ * Atomically sets the element at position {@code i} to the given
+ * updated value
+ * if the current value is <a href="#bitEquals">bitwise equal</a>
+ * to the expected value.
+ *
+ * <p>May <a
+ * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
+ * fail spuriously</a>
+ * and does not provide ordering guarantees, 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 true if successful
+ */
+ public final boolean weakCompareAndSet(int i, double expect, double update) {
+ return longs.weakCompareAndSet(i,
+ doubleToRawLongBits(expect),
+ doubleToRawLongBits(update));
+ }
+
+ /**
+ * 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 double getAndAdd(int i, double delta) {
+ while (true) {
+ long current = longs.get(i);
+ double currentVal = longBitsToDouble(current);
+ double nextVal = currentVal + delta;
+ long next = doubleToRawLongBits(nextVal);
+ if (longs.compareAndSet(i, current, next)) {
+ return currentVal;
+ }
+ }
+ }
+
+ /**
+ * 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 double addAndGet(int i, double delta) {
+ while (true) {
+ long current = longs.get(i);
+ double currentVal = longBitsToDouble(current);
+ double nextVal = currentVal + delta;
+ long next = doubleToRawLongBits(nextVal);
+ if (longs.compareAndSet(i, current, next)) {
+ return nextVal;
+ }
+ }
+ }
+
+ /**
+ * 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 = length() - 1;
+ if (iMax == -1) {
+ return "[]";
+ }
+
+ // Double.toString(Math.PI).length() == 17
+ StringBuilder b = new StringBuilder((17 + 2) * (iMax + 1));
+ b.append('[');
+ for (int i = 0;; i++) {
+ b.append(longBitsToDouble(longs.get(i)));
+ if (i == iMax) {
+ return b.append(']').toString();
+ }
+ b.append(',').append(' ');
+ }
+ }
+
+ /**
+ * Saves the state to a stream (that is, serializes it).
+ *
+ * @serialData The length of the array is emitted (int), followed by all
+ * of its elements (each a {@code double}) in the proper order.
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ s.defaultWriteObject();
+
+ // Write out array length
+ int length = length();
+ s.writeInt(length);
+
+ // Write out all elements in the proper order.
+ for (int i = 0; i < length; i++) {
+ s.writeDouble(get(i));
+ }
+ }
+
+ /**
+ * Reconstitutes the instance from a stream (that is, deserializes it).
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+
+ // Read in array length and allocate array
+ int length = s.readInt();
+ this.longs = new AtomicLongArray(length);
+
+ // Read in all elements in the proper order.
+ for (int i = 0; i < length; i++) {
+ set(i, s.readDouble());
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/AtomicLongMap.java b/guava/src/com/google/common/util/concurrent/AtomicLongMap.java
new file mode 100644
index 0000000..f5aafd0
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/AtomicLongMap.java
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Function;
+import com.google.common.collect.Maps;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * A map containing {@code long} values that can be atomically updated. While writes to a
+ * traditional {@code Map} rely on {@code put(K, V)}, the typical mechanism for writing to this map
+ * is {@code addAndGet(K, long)}, which adds a {@code long} to the value currently associated with
+ * {@code K}. If a key has not yet been associated with a value, its implicit value is zero.
+ *
+ * <p>Most methods in this class treat absent values and zero values identically, as individually
+ * documented. Exceptions to this are {@link #containsKey}, {@link #size}, {@link #isEmpty},
+ * {@link #asMap}, and {@link #toString}.
+ *
+ * <p>Instances of this class may be used by multiple threads concurrently. All operations are
+ * atomic unless otherwise noted.
+ *
+ * <p><b>Note:</b> If your values are always positive and less than 2^31, you may wish to use a
+ * {@link com.google.common.collect.Multiset} such as
+ * {@link com.google.common.collect.ConcurrentHashMultiset} instead.
+ *
+ * <b>Warning:</b> Unlike {@code Multiset}, entries whose values are zero are not automatically
+ * removed from the map. Instead they must be removed manually with {@link #removeAllZeros}.
+ *
+ * @author Charles Fry
+ * @since 11.0
+ */
+@Beta
+@GwtCompatible
+public final class AtomicLongMap<K> {
+ private final ConcurrentHashMap<K, AtomicLong> map;
+
+ private AtomicLongMap(ConcurrentHashMap<K, AtomicLong> map) {
+ this.map = checkNotNull(map);
+ }
+
+ /**
+ * Creates an {@code AtomicLongMap}.
+ */
+ public static <K> AtomicLongMap<K> create() {
+ return new AtomicLongMap<K>(new ConcurrentHashMap<K, AtomicLong>());
+ }
+
+ /**
+ * Creates an {@code AtomicLongMap} with the same mappings as the specified {@code Map}.
+ */
+ public static <K> AtomicLongMap<K> create(Map<? extends K, ? extends Long> m) {
+ AtomicLongMap<K> result = create();
+ result.putAll(m);
+ return result;
+ }
+
+ /**
+ * Returns the value associated with {@code key}, or zero if there is no value associated with
+ * {@code key}.
+ */
+ public long get(K key) {
+ AtomicLong atomic = map.get(key);
+ return atomic == null ? 0L : atomic.get();
+ }
+
+ /**
+ * Increments by one the value currently associated with {@code key}, and returns the new value.
+ */
+ public long incrementAndGet(K key) {
+ return addAndGet(key, 1);
+ }
+
+ /**
+ * Decrements by one the value currently associated with {@code key}, and returns the new value.
+ */
+ public long decrementAndGet(K key) {
+ return addAndGet(key, -1);
+ }
+
+ /**
+ * Adds {@code delta} to the value currently associated with {@code key}, and returns the new
+ * value.
+ */
+ public long addAndGet(K key, long delta) {
+ outer: for (;;) {
+ AtomicLong atomic = map.get(key);
+ if (atomic == null) {
+ atomic = map.putIfAbsent(key, new AtomicLong(delta));
+ if (atomic == null) {
+ return delta;
+ }
+ // atomic is now non-null; fall through
+ }
+
+ for (;;) {
+ long oldValue = atomic.get();
+ if (oldValue == 0L) {
+ // don't compareAndSet a zero
+ if (map.replace(key, atomic, new AtomicLong(delta))) {
+ return delta;
+ }
+ // atomic replaced
+ continue outer;
+ }
+
+ long newValue = oldValue + delta;
+ if (atomic.compareAndSet(oldValue, newValue)) {
+ return newValue;
+ }
+ // value changed
+ }
+ }
+ }
+
+ /**
+ * Increments by one the value currently associated with {@code key}, and returns the old value.
+ */
+ public long getAndIncrement(K key) {
+ return getAndAdd(key, 1);
+ }
+
+ /**
+ * Decrements by one the value currently associated with {@code key}, and returns the old value.
+ */
+ public long getAndDecrement(K key) {
+ return getAndAdd(key, -1);
+ }
+
+ /**
+ * Adds {@code delta} to the value currently associated with {@code key}, and returns the old
+ * value.
+ */
+ public long getAndAdd(K key, long delta) {
+ outer: for (;;) {
+ AtomicLong atomic = map.get(key);
+ if (atomic == null) {
+ atomic = map.putIfAbsent(key, new AtomicLong(delta));
+ if (atomic == null) {
+ return 0L;
+ }
+ // atomic is now non-null; fall through
+ }
+
+ for (;;) {
+ long oldValue = atomic.get();
+ if (oldValue == 0L) {
+ // don't compareAndSet a zero
+ if (map.replace(key, atomic, new AtomicLong(delta))) {
+ return 0L;
+ }
+ // atomic replaced
+ continue outer;
+ }
+
+ long newValue = oldValue + delta;
+ if (atomic.compareAndSet(oldValue, newValue)) {
+ return oldValue;
+ }
+ // value changed
+ }
+ }
+ }
+
+ /**
+ * Associates {@code newValue} with {@code key} in this map, and returns the value previously
+ * associated with {@code key}, or zero if there was no such value.
+ */
+ public long put(K key, long newValue) {
+ outer: for (;;) {
+ AtomicLong atomic = map.get(key);
+ if (atomic == null) {
+ atomic = map.putIfAbsent(key, new AtomicLong(newValue));
+ if (atomic == null) {
+ return 0L;
+ }
+ // atomic is now non-null; fall through
+ }
+
+ for (;;) {
+ long oldValue = atomic.get();
+ if (oldValue == 0L) {
+ // don't compareAndSet a zero
+ if (map.replace(key, atomic, new AtomicLong(newValue))) {
+ return 0L;
+ }
+ // atomic replaced
+ continue outer;
+ }
+
+ if (atomic.compareAndSet(oldValue, newValue)) {
+ return oldValue;
+ }
+ // value changed
+ }
+ }
+ }
+
+ /**
+ * Copies all of the mappings from the specified map to this map. The effect of this call is
+ * equivalent to that of calling {@code put(k, v)} on this map once for each mapping from key
+ * {@code k} to value {@code v} in the specified map. The behavior of this operation is undefined
+ * if the specified map is modified while the operation is in progress.
+ */
+ public void putAll(Map<? extends K, ? extends Long> m) {
+ for (Map.Entry<? extends K, ? extends Long> entry : m.entrySet()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /**
+ * Removes and returns the value associated with {@code key}. If {@code key} is not
+ * in the map, this method has no effect and returns zero.
+ */
+ public long remove(K key) {
+ AtomicLong atomic = map.get(key);
+ if (atomic == null) {
+ return 0L;
+ }
+
+ for (;;) {
+ long oldValue = atomic.get();
+ if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {
+ // only remove after setting to zero, to avoid concurrent updates
+ map.remove(key, atomic);
+ // succeed even if the remove fails, since the value was already adjusted
+ return oldValue;
+ }
+ }
+ }
+
+ /**
+ * Removes all mappings from this map whose values are zero.
+ *
+ * <p>This method is not atomic: the map may be visible in intermediate states, where some
+ * of the zero values have been removed and others have not.
+ */
+ public void removeAllZeros() {
+ for (K key : map.keySet()) {
+ AtomicLong atomic = map.get(key);
+ if (atomic != null && atomic.get() == 0L) {
+ map.remove(key, atomic);
+ }
+ }
+ }
+
+ /**
+ * Returns the sum of all values in this map.
+ *
+ * <p>This method is not atomic: the sum may or may not include other concurrent operations.
+ */
+ public long sum() {
+ long sum = 0L;
+ for (AtomicLong value : map.values()) {
+ sum = sum + value.get();
+ }
+ return sum;
+ }
+
+ private transient Map<K, Long> asMap;
+
+ /**
+ * Returns a live, read-only view of the map backing this {@code AtomicLongMap}.
+ */
+ public Map<K, Long> asMap() {
+ Map<K, Long> result = asMap;
+ return (result == null) ? asMap = createAsMap() : result;
+ }
+
+ private Map<K, Long> createAsMap() {
+ return Collections.unmodifiableMap(
+ Maps.transformValues(map, new Function<AtomicLong, Long>() {
+ @Override
+ public Long apply(AtomicLong atomic) {
+ return atomic.get();
+ }
+ }));
+ }
+
+ /**
+ * Returns true if this map contains a mapping for the specified key.
+ */
+ public boolean containsKey(Object key) {
+ return map.containsKey(key);
+ }
+
+ /**
+ * Returns the number of key-value mappings in this map. If the map contains more than
+ * {@code Integer.MAX_VALUE} elements, returns {@code Integer.MAX_VALUE}.
+ */
+ public int size() {
+ return map.size();
+ }
+
+ /**
+ * Returns {@code true} if this map contains no key-value mappings.
+ */
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ /**
+ * Removes all of the mappings from this map. The map will be empty after this call returns.
+ *
+ * <p>This method is not atomic: the map may not be empty after returning if there were concurrent
+ * writes.
+ */
+ public void clear() {
+ map.clear();
+ }
+
+ @Override
+ public String toString() {
+ return map.toString();
+ }
+
+ /*
+ * ConcurrentMap operations which we may eventually add.
+ *
+ * The problem with these is that remove(K, long) has to be done in two phases by definition ---
+ * first decrementing to zero, and then removing. putIfAbsent or replace could observe the
+ * intermediate zero-state. Ways we could deal with this are:
+ *
+ * - Don't define any of the ConcurrentMap operations. This is the current state of affairs.
+ *
+ * - Define putIfAbsent and replace as treating zero and absent identically (as currently
+ * implemented below). This is a bit surprising with putIfAbsent, which really becomes
+ * putIfZero.
+ *
+ * - Allow putIfAbsent and replace to distinguish between zero and absent, but don't implement
+ * remove(K, long). Without any two-phase operations it becomes feasible for all remaining
+ * operations to distinguish between zero and absent. If we do this, then perhaps we should add
+ * replace(key, long).
+ *
+ * - Introduce a special-value private static final AtomicLong that would have the meaning of
+ * removal-in-progress, and rework all operations to properly distinguish between zero and
+ * absent.
+ */
+
+ /**
+ * If {@code key} is not already associated with a value or if {@code key} is associated with
+ * zero, associate it with {@code newValue}. Returns the previous value associated with
+ * {@code key}, or zero if there was no mapping for {@code key}.
+ */
+ long putIfAbsent(K key, long newValue) {
+ for (;;) {
+ AtomicLong atomic = map.get(key);
+ if (atomic == null) {
+ atomic = map.putIfAbsent(key, new AtomicLong(newValue));
+ if (atomic == null) {
+ return 0L;
+ }
+ // atomic is now non-null; fall through
+ }
+
+ long oldValue = atomic.get();
+ if (oldValue == 0L) {
+ // don't compareAndSet a zero
+ if (map.replace(key, atomic, new AtomicLong(newValue))) {
+ return 0L;
+ }
+ // atomic replaced
+ continue;
+ }
+
+ return oldValue;
+ }
+ }
+
+ /**
+ * If {@code (key, expectedOldValue)} is currently in the map, this method replaces
+ * {@code expectedOldValue} with {@code newValue} and returns true; otherwise, this method
+ * returns false.
+ *
+ * <p>If {@code expectedOldValue} is zero, this method will succeed if {@code (key, zero)}
+ * is currently in the map, or if {@code key} is not in the map at all.
+ */
+ boolean replace(K key, long expectedOldValue, long newValue) {
+ if (expectedOldValue == 0L) {
+ return putIfAbsent(key, newValue) == 0L;
+ } else {
+ AtomicLong atomic = map.get(key);
+ return (atomic == null) ? false : atomic.compareAndSet(expectedOldValue, newValue);
+ }
+ }
+
+ /**
+ * If {@code (key, value)} is currently in the map, this method removes it and returns
+ * true; otherwise, this method returns false.
+ */
+ boolean remove(K key, long value) {
+ AtomicLong atomic = map.get(key);
+ if (atomic == null) {
+ return false;
+ }
+
+ long oldValue = atomic.get();
+ if (oldValue != value) {
+ return false;
+ }
+
+ if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {
+ // only remove after setting to zero, to avoid concurrent updates
+ map.remove(key, atomic);
+ // succeed even if the remove fails, since the value was already adjusted
+ return true;
+ }
+
+ // value changed
+ return false;
+ }
+
+}
diff --git a/guava/src/com/google/common/util/concurrent/Atomics.java b/guava/src/com/google/common/util/concurrent/Atomics.java
new file mode 100644
index 0000000..fece83d
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/Atomics.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+
+import javax.annotation.Nullable;
+
+/**
+ * Static utility methods pertaining to classes in the
+ * {@code java.util.concurrent.atomic} package.
+ *
+ * @author Kurt Alfred Kluever
+ * @since 10.0
+ */
+@Beta
+public final class Atomics {
+ private Atomics() {}
+
+ /**
+ * Creates an {@code AtomicReference} instance with no initial value.
+ *
+ * @return a new {@code AtomicReference} with no initial value
+ */
+ public static <V> AtomicReference<V> newReference() {
+ return new AtomicReference<V>();
+ }
+
+ /**
+ * Creates an {@code AtomicReference} instance with the given initial value.
+ *
+ * @param initialValue the initial value
+ * @return a new {@code AtomicReference} with the given initial value
+ */
+ public static <V> AtomicReference<V> newReference(@Nullable V initialValue) {
+ return new AtomicReference<V>(initialValue);
+ }
+
+ /**
+ * Creates an {@code AtomicReferenceArray} instance of given length.
+ *
+ * @param length the length of the array
+ * @return a new {@code AtomicReferenceArray} with the given length
+ */
+ public static <E> AtomicReferenceArray<E> newReferenceArray(int length) {
+ return new AtomicReferenceArray<E>(length);
+ }
+
+ /**
+ * Creates an {@code AtomicReferenceArray} instance with the same length as,
+ * and all elements copied from, the given array.
+ *
+ * @param array the array to copy elements from
+ * @return a new {@code AtomicReferenceArray} copied from the given array
+ */
+ public static <E> AtomicReferenceArray<E> newReferenceArray(E[] array) {
+ return new AtomicReferenceArray<E>(array);
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/Callables.java b/guava/src/com/google/common/util/concurrent/Callables.java
new file mode 100644
index 0000000..f970f42
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/Callables.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import java.util.concurrent.Callable;
+
+import javax.annotation.Nullable;
+
+/**
+ * Static utility methods pertaining to the {@link Callable} interface.
+ *
+ * @author Isaac Shum
+ * @since 1.0
+ */
+public final class Callables {
+ private Callables() {}
+
+ /**
+ * Creates a {@code Callable} which immediately returns a preset value each
+ * time it is called.
+ */
+ public static <T> Callable<T> returning(final @Nullable T value) {
+ return new Callable<T>() {
+ @Override public T call() {
+ return value;
+ }
+ };
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/CheckedFuture.java b/guava/src/com/google/common/util/concurrent/CheckedFuture.java
new file mode 100644
index 0000000..31504e2
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/CheckedFuture.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A {@code CheckedFuture} is a {@link ListenableFuture} that includes versions
+ * of the {@code get} methods that can throw a checked exception. This makes it
+ * easier to create a future that executes logic which can throw an exception.
+ *
+ * <p>A common implementation is {@link Futures#immediateCheckedFuture}.
+ *
+ * <p>Implementations of this interface must adapt the exceptions thrown by
+ * {@code Future#get()}: {@link CancellationException},
+ * {@link ExecutionException} and {@link InterruptedException} into the type
+ * specified by the {@code E} type parameter.
+ *
+ * <p>This interface also extends the ListenableFuture interface to allow
+ * listeners to be added. This allows the future to be used as a normal
+ * {@link Future} or as an asynchronous callback mechanism as needed. This
+ * allows multiple callbacks to be registered for a particular task, and the
+ * future will guarantee execution of all listeners when the task completes.
+ *
+ * <p>For a simpler alternative to CheckedFuture, consider accessing Future
+ * values with {@link Futures#get(Future, Class) Futures.get()}.
+ *
+ * @author Sven Mawson
+ * @since 1.0
+ */
+@Beta
+public interface CheckedFuture<V, X extends Exception>
+ extends ListenableFuture<V> {
+
+ /**
+ * Exception checking version of {@link Future#get()} that will translate
+ * {@link InterruptedException}, {@link CancellationException} and
+ * {@link ExecutionException} into application-specific exceptions.
+ *
+ * @return the result of executing the future.
+ * @throws X on interruption, cancellation or execution exceptions.
+ */
+ V checkedGet() throws X;
+
+ /**
+ * Exception checking version of {@link Future#get(long, TimeUnit)} that will
+ * translate {@link InterruptedException}, {@link CancellationException} and
+ * {@link ExecutionException} into application-specific exceptions. On
+ * timeout this method throws a normal {@link TimeoutException}.
+ *
+ * @return the result of executing the future.
+ * @throws TimeoutException if retrieving the result timed out.
+ * @throws X on interruption, cancellation or execution exceptions.
+ */
+ V checkedGet(long timeout, TimeUnit unit) throws TimeoutException, X;
+}
diff --git a/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java b/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java
new file mode 100644
index 0000000..53d19d0
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/CycleDetectingLockFactory.java
@@ -0,0 +1,1034 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.MapMaker;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * The {@code CycleDetectingLockFactory} creates {@link ReentrantLock}s and
+ * {@link ReentrantReadWriteLock}s that detect potential deadlock by checking
+ * for cycles in lock acquisition order.
+ * <p>
+ * Potential deadlocks detected when calling the {@code lock()},
+ * {@code lockInterruptibly()}, or {@code tryLock()} methods will result in the
+ * execution of the {@link Policy} specified when creating the factory. The
+ * currently available policies are:
+ * <ul>
+ * <li>DISABLED
+ * <li>WARN
+ * <li>THROW
+ * </ul>
+ * The locks created by a factory instance will detect lock acquisition cycles
+ * with locks created by other {@code CycleDetectingLockFactory} instances
+ * (except those with {@code Policy.DISABLED}). A lock's behavior when a cycle
+ * is detected, however, is defined by the {@code Policy} of the factory that
+ * created it. This allows detection of cycles across components while
+ * delegating control over lock behavior to individual components.
+ * <p>
+ * Applications are encouraged to use a {@code CycleDetectingLockFactory} to
+ * create any locks for which external/unmanaged code is executed while the lock
+ * is held. (See caveats under <strong>Performance</strong>).
+ * <p>
+ * <strong>Cycle Detection</strong>
+ * <p>
+ * Deadlocks can arise when locks are acquired in an order that forms a cycle.
+ * In a simple example involving two locks and two threads, deadlock occurs
+ * when one thread acquires Lock A, and then Lock B, while another thread
+ * acquires Lock B, and then Lock A:
+ * <pre>
+ * Thread1: acquire(LockA) --X acquire(LockB)
+ * Thread2: acquire(LockB) --X acquire(LockA)
+ * </pre>
+ * Neither thread will progress because each is waiting for the other. In more
+ * complex applications, cycles can arise from interactions among more than 2
+ * locks:
+ * <pre>
+ * Thread1: acquire(LockA) --X acquire(LockB)
+ * Thread2: acquire(LockB) --X acquire(LockC)
+ * ...
+ * ThreadN: acquire(LockN) --X acquire(LockA)
+ * </pre>
+ * The implementation detects cycles by constructing a directed graph in which
+ * each lock represents a node and each edge represents an acquisition ordering
+ * between two locks.
+ * <ul>
+ * <li>Each lock adds (and removes) itself to/from a ThreadLocal Set of acquired
+ * locks when the Thread acquires its first hold (and releases its last
+ * remaining hold).
+ * <li>Before the lock is acquired, the lock is checked against the current set
+ * of acquired locks---to each of the acquired locks, an edge from the
+ * soon-to-be-acquired lock is either verified or created.
+ * <li>If a new edge needs to be created, the outgoing edges of the acquired
+ * locks are traversed to check for a cycle that reaches the lock to be
+ * acquired. If no cycle is detected, a new "safe" edge is created.
+ * <li>If a cycle is detected, an "unsafe" (cyclic) edge is created to represent
+ * a potential deadlock situation, and the appropriate Policy is executed.
+ * </ul>
+ * Note that detection of potential deadlock does not necessarily indicate that
+ * deadlock will happen, as it is possible that higher level application logic
+ * prevents the cyclic lock acquisition from occurring. One example of a false
+ * positive is:
+ * <pre>
+ * LockA -&gt; LockB -&gt; LockC
+ * LockA -&gt; LockC -&gt; LockB
+ * </pre>
+ *
+ * <strong>ReadWriteLocks</strong>
+ * <p>
+ * While {@code ReadWriteLock}s have different properties and can form cycles
+ * without potential deadlock, this class treats {@code ReadWriteLock}s as
+ * equivalent to traditional exclusive locks. Although this increases the false
+ * positives that the locks detect (i.e. cycles that will not actually result in
+ * deadlock), it simplifies the algorithm and implementation considerably. The
+ * assumption is that a user of this factory wishes to eliminate any cyclic
+ * acquisition ordering.
+ * <p>
+ * <strong>Explicit Lock Acquisition Ordering</strong>
+ * <p>
+ * The {@link CycleDetectingLockFactory.WithExplicitOrdering} class can be used
+ * to enforce an application-specific ordering in addition to performing general
+ * cycle detection.
+ * <p>
+ * <strong>Garbage Collection</strong>
+ * <p>
+ * In order to allow proper garbage collection of unused locks, the edges of
+ * the lock graph are weak references.
+ * <p>
+ * <strong>Performance</strong>
+ * <p>
+ * The extra bookkeeping done by cycle detecting locks comes at some cost to
+ * performance. Benchmarks (as of December 2011) show that:
+ *
+ * <ul>
+ * <li>for an unnested {@code lock()} and {@code unlock()}, a cycle detecting
+ * lock takes 38ns as opposed to the 24ns taken by a plain lock.
+ * <li>for nested locking, the cost increases with the depth of the nesting:
+ * <ul>
+ * <li> 2 levels: average of 64ns per lock()/unlock()
+ * <li> 3 levels: average of 77ns per lock()/unlock()
+ * <li> 4 levels: average of 99ns per lock()/unlock()
+ * <li> 5 levels: average of 103ns per lock()/unlock()
+ * <li>10 levels: average of 184ns per lock()/unlock()
+ * <li>20 levels: average of 393ns per lock()/unlock()
+ * </ul>
+ * </ul>
+ *
+ * As such, the CycleDetectingLockFactory may not be suitable for
+ * performance-critical applications which involve tightly-looped or
+ * deeply-nested locking algorithms.
+ *
+ * @author Darick Tong
+ * @since 13.0
+ */
+@Beta
+@ThreadSafe
+public class CycleDetectingLockFactory {
+
+ /**
+ * Encapsulates the action to be taken when a potential deadlock is
+ * encountered. Clients can use one of the predefined {@link Policies} or
+ * specify a custom implementation. Implementations must be thread-safe.
+ *
+ * @since 13.0
+ */
+ @Beta
+ @ThreadSafe
+ public interface Policy {
+
+ /**
+ * Called when a potential deadlock is encountered. Implementations can
+ * throw the given {@code exception} and/or execute other desired logic.
+ * <p>
+ * Note that the method will be called even upon an invocation of
+ * {@code tryLock()}. Although {@code tryLock()} technically recovers from
+ * deadlock by eventually timing out, this behavior is chosen based on the
+ * assumption that it is the application's wish to prohibit any cyclical
+ * lock acquisitions.
+ */
+ void handlePotentialDeadlock(PotentialDeadlockException exception);
+ }
+
+ /**
+ * Pre-defined {@link Policy} implementations.
+ *
+ * @since 13.0
+ */
+ @Beta
+ public enum Policies implements Policy {
+ /**
+ * When potential deadlock is detected, this policy results in the throwing
+ * of the {@code PotentialDeadlockException} indicating the potential
+ * deadlock, which includes stack traces illustrating the cycle in lock
+ * acquisition order.
+ */
+ THROW {
+ @Override
+ public void handlePotentialDeadlock(PotentialDeadlockException e) {
+ throw e;
+ }
+ },
+
+ /**
+ * When potential deadlock is detected, this policy results in the logging
+ * of a {@link Level#SEVERE} message indicating the potential deadlock,
+ * which includes stack traces illustrating the cycle in lock acquisition
+ * order.
+ */
+ WARN {
+ @Override
+ public void handlePotentialDeadlock(PotentialDeadlockException e) {
+ logger.log(Level.SEVERE, "Detected potential deadlock", e);
+ }
+ },
+
+ /**
+ * Disables cycle detection. This option causes the factory to return
+ * unmodified lock implementations provided by the JDK, and is provided to
+ * allow applications to easily parameterize when cycle detection is
+ * enabled.
+ * <p>
+ * Note that locks created by a factory with this policy will <em>not</em>
+ * participate the cycle detection performed by locks created by other
+ * factories.
+ */
+ DISABLED {
+ @Override
+ public void handlePotentialDeadlock(PotentialDeadlockException e) {
+ }
+ };
+ }
+
+ /**
+ * Creates a new factory with the specified policy.
+ */
+ public static CycleDetectingLockFactory newInstance(Policy policy) {
+ return new CycleDetectingLockFactory(policy);
+ }
+
+ /**
+ * Equivalent to {@code newReentrantLock(lockName, false)}.
+ */
+ public ReentrantLock newReentrantLock(String lockName) {
+ return newReentrantLock(lockName, false);
+ }
+
+ /**
+ * Creates a {@link ReentrantLock} with the given fairness policy. The
+ * {@code lockName} is used in the warning or exception output to help
+ * identify the locks involved in the detected deadlock.
+ */
+ public ReentrantLock newReentrantLock(String lockName, boolean fair) {
+ return policy == Policies.DISABLED ? new ReentrantLock(fair)
+ : new CycleDetectingReentrantLock(
+ new LockGraphNode(lockName), fair);
+ }
+
+ /**
+ * Equivalent to {@code newReentrantReadWriteLock(lockName, false)}.
+ */
+ public ReentrantReadWriteLock newReentrantReadWriteLock(String lockName) {
+ return newReentrantReadWriteLock(lockName, false);
+ }
+
+ /**
+ * Creates a {@link ReentrantReadWriteLock} with the given fairness policy.
+ * The {@code lockName} is used in the warning or exception output to help
+ * identify the locks involved in the detected deadlock.
+ */
+ public ReentrantReadWriteLock newReentrantReadWriteLock(
+ String lockName, boolean fair) {
+ return policy == Policies.DISABLED ? new ReentrantReadWriteLock(fair)
+ : new CycleDetectingReentrantReadWriteLock(
+ new LockGraphNode(lockName), fair);
+ }
+
+ // A static mapping from an Enum type to its set of LockGraphNodes.
+ private static final Map<Class<? extends Enum>,
+ Map<? extends Enum, LockGraphNode>> lockGraphNodesPerType =
+ new MapMaker().weakKeys().makeComputingMap(
+ new OrderedLockGraphNodesCreator());
+
+ /**
+ * Creates a {@code CycleDetectingLockFactory.WithExplicitOrdering<E>}.
+ */
+ public static <E extends Enum<E>> WithExplicitOrdering<E>
+ newInstanceWithExplicitOrdering(Class<E> enumClass, Policy policy) {
+ // OrderedLockGraphNodesCreator maps each enumClass to a Map with the
+ // corresponding enum key type.
+ @SuppressWarnings("unchecked")
+ Map<E, LockGraphNode> lockGraphNodes =
+ (Map<E, LockGraphNode>) lockGraphNodesPerType.get(enumClass);
+ return new WithExplicitOrdering<E>(policy, lockGraphNodes);
+ }
+
+ /**
+ * A {@code CycleDetectingLockFactory.WithExplicitOrdering} provides the
+ * additional enforcement of an application-specified ordering of lock
+ * acquisitions. The application defines the allowed ordering with an
+ * {@code Enum} whose values each correspond to a lock type. The order in
+ * which the values are declared dictates the allowed order of lock
+ * acquisition. In other words, locks corresponding to smaller values of
+ * {@link Enum#ordinal()} should only be acquired before locks with larger
+ * ordinals. Example:
+ *
+ * <pre> {@code
+ * enum MyLockOrder {
+ * FIRST, SECOND, THIRD;
+ * }
+ *
+ * CycleDetectingLockFactory.WithExplicitOrdering<MyLockOrder> factory =
+ * CycleDetectingLockFactory.newInstanceWithExplicitOrdering(Policies.THROW);
+ *
+ * Lock lock1 = factory.newReentrantLock(MyLockOrder.FIRST);
+ * Lock lock2 = factory.newReentrantLock(MyLockOrder.SECOND);
+ * Lock lock3 = factory.newReentrantLock(MyLockOrder.THIRD);
+ *
+ * lock1.lock();
+ * lock3.lock();
+ * lock2.lock(); // will throw an IllegalStateException
+ * }</pre>
+ *
+ * As with all locks created by instances of {@code CycleDetectingLockFactory}
+ * explicitly ordered locks participate in general cycle detection with all
+ * other cycle detecting locks, and a lock's behavior when detecting a cyclic
+ * lock acquisition is defined by the {@code Policy} of the factory that
+ * created it.
+ * <p>
+ * Note, however, that although multiple locks can be created for a given Enum
+ * value, whether it be through separate factory instances or through multiple
+ * calls to the same factory, attempting to acquire multiple locks with the
+ * same Enum value (within the same thread) will result in an
+ * IllegalStateException regardless of the factory's policy. For example:
+ *
+ * <pre> {@code
+ * CycleDetectingLockFactory.WithExplicitOrdering<MyLockOrder> factory1 =
+ * CycleDetectingLockFactory.newInstanceWithExplicitOrdering(...);
+ * CycleDetectingLockFactory.WithExplicitOrdering<MyLockOrder> factory2 =
+ * CycleDetectingLockFactory.newInstanceWithExplicitOrdering(...);
+ *
+ * Lock lockA = factory1.newReentrantLock(MyLockOrder.FIRST);
+ * Lock lockB = factory1.newReentrantLock(MyLockOrder.FIRST);
+ * Lock lockC = factory2.newReentrantLock(MyLockOrder.FIRST);
+ *
+ * lockA.lock();
+ *
+ * lockB.lock(); // will throw an IllegalStateException
+ * lockC.lock(); // will throw an IllegalStateException
+ *
+ * lockA.lock(); // reentrant acquisition is okay
+ * }</pre>
+ *
+ * It is the responsibility of the application to ensure that multiple lock
+ * instances with the same rank are never acquired in the same thread.
+ *
+ * @param <E> The Enum type representing the explicit lock ordering.
+ * @since 13.0
+ */
+ @Beta
+ public static final class WithExplicitOrdering<E extends Enum<E>>
+ extends CycleDetectingLockFactory {
+
+ private final Map<E, LockGraphNode> lockGraphNodes;
+
+ @VisibleForTesting
+ WithExplicitOrdering(
+ Policy policy, Map<E, LockGraphNode> lockGraphNodes) {
+ super(policy);
+ this.lockGraphNodes = lockGraphNodes;
+ }
+
+ /**
+ * Equivalent to {@code newReentrantLock(rank, false)}.
+ */
+ public ReentrantLock newReentrantLock(E rank) {
+ return newReentrantLock(rank, false);
+ }
+
+ /**
+ * Creates a {@link ReentrantLock} with the given fairness policy and rank.
+ * The values returned by {@link Enum#getDeclaringClass()} and
+ * {@link Enum#name()} are used to describe the lock in warning or
+ * exception output.
+ *
+ * @throws IllegalStateException If the factory has already created a
+ * {@code Lock} with the specified rank.
+ */
+ public ReentrantLock newReentrantLock(E rank, boolean fair) {
+ return policy == Policies.DISABLED ? new ReentrantLock(fair)
+ : new CycleDetectingReentrantLock(lockGraphNodes.get(rank), fair);
+ }
+
+ /**
+ * Equivalent to {@code newReentrantReadWriteLock(rank, false)}.
+ */
+ public ReentrantReadWriteLock newReentrantReadWriteLock(E rank) {
+ return newReentrantReadWriteLock(rank, false);
+ }
+
+ /**
+ * Creates a {@link ReentrantReadWriteLock} with the given fairness policy
+ * and rank. The values returned by {@link Enum#getDeclaringClass()} and
+ * {@link Enum#name()} are used to describe the lock in warning or exception
+ * output.
+ *
+ * @throws IllegalStateException If the factory has already created a
+ * {@code Lock} with the specified rank.
+ */
+ public ReentrantReadWriteLock newReentrantReadWriteLock(
+ E rank, boolean fair) {
+ return policy == Policies.DISABLED ? new ReentrantReadWriteLock(fair)
+ : new CycleDetectingReentrantReadWriteLock(
+ lockGraphNodes.get(rank), fair);
+ }
+ }
+
+ /**
+ * For a given Enum type, creates an immutable map from each of the Enum's
+ * values to a corresponding LockGraphNode, with the
+ * {@code allowedPriorLocks} and {@code disallowedPriorLocks} prepopulated
+ * with nodes according to the natural ordering of the associated Enum values.
+ */
+ @VisibleForTesting
+ static class OrderedLockGraphNodesCreator
+ implements Function<Class<? extends Enum>,
+ Map<? extends Enum, LockGraphNode>> {
+
+ @Override
+ @SuppressWarnings("unchecked") // There's no way to properly express with
+ // wildcards the recursive Enum type required by createNodesFor(), and the
+ // Map/Function types must use wildcards since they accept any Enum class.
+ public Map<? extends Enum, LockGraphNode> apply(
+ Class<? extends Enum> clazz) {
+ return createNodesFor(clazz);
+ }
+
+ <E extends Enum<E>> Map<E, LockGraphNode> createNodesFor(Class<E> clazz) {
+ EnumMap<E, LockGraphNode> map = Maps.newEnumMap(clazz);
+ E[] keys = clazz.getEnumConstants();
+ final int numKeys = keys.length;
+ ArrayList<LockGraphNode> nodes =
+ Lists.newArrayListWithCapacity(numKeys);
+ // Create a LockGraphNode for each enum value.
+ for (E key : keys) {
+ LockGraphNode node = new LockGraphNode(getLockName(key));
+ nodes.add(node);
+ map.put(key, node);
+ }
+ // Pre-populate all allowedPriorLocks with nodes of smaller ordinal.
+ for (int i = 1; i < numKeys; i++) {
+ nodes.get(i).checkAcquiredLocks(Policies.THROW, nodes.subList(0, i));
+ }
+ // Pre-populate all disallowedPriorLocks with nodes of larger ordinal.
+ for (int i = 0; i < numKeys - 1; i++) {
+ nodes.get(i).checkAcquiredLocks(
+ Policies.DISABLED, nodes.subList(i + 1, numKeys));
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * For the given Enum value {@code rank}, returns the value's
+ * {@code "EnumClass.name"}, which is used in exception and warning
+ * output.
+ */
+ private String getLockName(Enum<?> rank) {
+ return rank.getDeclaringClass().getSimpleName() + "." + rank.name();
+ }
+ }
+
+ //////// Implementation /////////
+
+ private static final Logger logger = Logger.getLogger(
+ CycleDetectingLockFactory.class.getName());
+
+ final Policy policy;
+
+ private CycleDetectingLockFactory(Policy policy) {
+ this.policy = policy;
+ }
+
+ /**
+ * Tracks the currently acquired locks for each Thread, kept up to date by
+ * calls to {@link #aboutToAcquire(CycleDetectingLock)} and
+ * {@link #lockStateChanged(CycleDetectingLock)}.
+ */
+ // This is logically a Set, but an ArrayList is used to minimize the amount
+ // of allocation done on lock()/unlock().
+ private static final ThreadLocal<ArrayList<LockGraphNode>>
+ acquiredLocks = new ThreadLocal<ArrayList<LockGraphNode>>() {
+ @Override
+ protected ArrayList<LockGraphNode> initialValue() {
+ return Lists.<LockGraphNode>newArrayListWithCapacity(3);
+ }
+ };
+
+ /**
+ * A Throwable used to record a stack trace that illustrates an example of
+ * a specific lock acquisition ordering. The top of the stack trace is
+ * truncated such that it starts with the acquisition of the lock in
+ * question, e.g.
+ *
+ * <pre>
+ * com...ExampleStackTrace: LockB -&gt; LockC
+ * at com...CycleDetectingReentrantLock.lock(CycleDetectingLockFactory.java:443)
+ * at ...
+ * at ...
+ * at com...MyClass.someMethodThatAcquiresLockB(MyClass.java:123)
+ * </pre>
+ */
+ private static class ExampleStackTrace extends IllegalStateException {
+
+ static final StackTraceElement[] EMPTY_STACK_TRACE =
+ new StackTraceElement[0];
+
+ static Set<String> EXCLUDED_CLASS_NAMES = ImmutableSet.of(
+ CycleDetectingLockFactory.class.getName(),
+ ExampleStackTrace.class.getName(),
+ LockGraphNode.class.getName());
+
+ ExampleStackTrace(LockGraphNode node1, LockGraphNode node2) {
+ super(node1.getLockName() + " -> " + node2.getLockName());
+ StackTraceElement[] origStackTrace = getStackTrace();
+ for (int i = 0, n = origStackTrace.length; i < n; i++) {
+ if (WithExplicitOrdering.class.getName().equals(
+ origStackTrace[i].getClassName())) {
+ // For pre-populated disallowedPriorLocks edges, omit the stack trace.
+ setStackTrace(EMPTY_STACK_TRACE);
+ break;
+ }
+ if (!EXCLUDED_CLASS_NAMES.contains(origStackTrace[i].getClassName())) {
+ setStackTrace(Arrays.copyOfRange(origStackTrace, i, n));
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Represents a detected cycle in lock acquisition ordering. The exception
+ * includes a causal chain of {@code ExampleStackTrace}s to illustrate the
+ * cycle, e.g.
+ *
+ * <pre>
+ * com....PotentialDeadlockException: Potential Deadlock from LockC -&gt; ReadWriteA
+ * at ...
+ * at ...
+ * Caused by: com...ExampleStackTrace: LockB -&gt; LockC
+ * at ...
+ * at ...
+ * Caused by: com...ExampleStackTrace: ReadWriteA -&gt; LockB
+ * at ...
+ * at ...
+ * </pre>
+ *
+ * Instances are logged for the {@code Policies.WARN}, and thrown for
+ * {@code Policies.THROW}.
+ *
+ * @since 13.0
+ */
+ @Beta
+ public static final class PotentialDeadlockException
+ extends ExampleStackTrace {
+
+ private final ExampleStackTrace conflictingStackTrace;
+
+ private PotentialDeadlockException(
+ LockGraphNode node1,
+ LockGraphNode node2,
+ ExampleStackTrace conflictingStackTrace) {
+ super(node1, node2);
+ this.conflictingStackTrace = conflictingStackTrace;
+ initCause(conflictingStackTrace);
+ }
+
+ public ExampleStackTrace getConflictingStackTrace() {
+ return conflictingStackTrace;
+ }
+
+ /**
+ * Appends the chain of messages from the {@code conflictingStackTrace} to
+ * the original {@code message}.
+ */
+ @Override
+ public String getMessage() {
+ StringBuilder message = new StringBuilder(super.getMessage());
+ for (Throwable t = conflictingStackTrace; t != null; t = t.getCause()) {
+ message.append(", ").append(t.getMessage());
+ }
+ return message.toString();
+ }
+ }
+
+ /**
+ * Internal Lock implementations implement the {@code CycleDetectingLock}
+ * interface, allowing the detection logic to treat all locks in the same
+ * manner.
+ */
+ private interface CycleDetectingLock {
+
+ /** @return the {@link LockGraphNode} associated with this lock. */
+ LockGraphNode getLockGraphNode();
+
+ /** @return {@code true} if the current thread has acquired this lock. */
+ boolean isAcquiredByCurrentThread();
+ }
+
+ /**
+ * A {@code LockGraphNode} associated with each lock instance keeps track of
+ * the directed edges in the lock acquisition graph.
+ */
+ private static class LockGraphNode {
+
+ /**
+ * The map tracking the locks that are known to be acquired before this
+ * lock, each associated with an example stack trace. Locks are weakly keyed
+ * to allow proper garbage collection when they are no longer referenced.
+ */
+ final Map<LockGraphNode, ExampleStackTrace> allowedPriorLocks =
+ new MapMaker().weakKeys().makeMap();
+
+ /**
+ * The map tracking lock nodes that can cause a lock acquisition cycle if
+ * acquired before this node.
+ */
+ final Map<LockGraphNode, PotentialDeadlockException>
+ disallowedPriorLocks = new MapMaker().weakKeys().makeMap();
+
+ final String lockName;
+
+ LockGraphNode(String lockName) {
+ this.lockName = Preconditions.checkNotNull(lockName);
+ }
+
+ String getLockName() {
+ return lockName;
+ }
+
+ void checkAcquiredLocks(
+ Policy policy, List<LockGraphNode> acquiredLocks) {
+ for (int i = 0, size = acquiredLocks.size(); i < size; i++) {
+ checkAcquiredLock(policy, acquiredLocks.get(i));
+ }
+ }
+
+ /**
+ * Checks the acquisition-ordering between {@code this}, which is about to
+ * be acquired, and the specified {@code acquiredLock}.
+ * <p>
+ * When this method returns, the {@code acquiredLock} should be in either
+ * the {@code preAcquireLocks} map, for the case in which it is safe to
+ * acquire {@code this} after the {@code acquiredLock}, or in the
+ * {@code disallowedPriorLocks} map, in which case it is not safe.
+ */
+ void checkAcquiredLock(Policy policy, LockGraphNode acquiredLock) {
+ // checkAcquiredLock() should never be invoked by a lock that has already
+ // been acquired. For unordered locks, aboutToAcquire() ensures this by
+ // checking isAcquiredByCurrentThread(). For ordered locks, however, this
+ // can happen because multiple locks may share the same LockGraphNode. In
+ // this situation, throw an IllegalStateException as defined by contract
+ // described in the documentation of WithExplicitOrdering.
+ Preconditions.checkState(
+ this != acquiredLock,
+ "Attempted to acquire multiple locks with the same rank " +
+ acquiredLock.getLockName());
+
+ if (allowedPriorLocks.containsKey(acquiredLock)) {
+ // The acquisition ordering from "acquiredLock" to "this" has already
+ // been verified as safe. In a properly written application, this is
+ // the common case.
+ return;
+ }
+ PotentialDeadlockException previousDeadlockException =
+ disallowedPriorLocks.get(acquiredLock);
+ if (previousDeadlockException != null) {
+ // Previously determined to be an unsafe lock acquisition.
+ // Create a new PotentialDeadlockException with the same causal chain
+ // (the example cycle) as that of the cached exception.
+ PotentialDeadlockException exception = new PotentialDeadlockException(
+ acquiredLock, this,
+ previousDeadlockException.getConflictingStackTrace());
+ policy.handlePotentialDeadlock(exception);
+ return;
+ }
+ // Otherwise, it's the first time seeing this lock relationship. Look for
+ // a path from the acquiredLock to this.
+ Set<LockGraphNode> seen = Sets.newIdentityHashSet();
+ ExampleStackTrace path = acquiredLock.findPathTo(this, seen);
+
+ if (path == null) {
+ // this can be safely acquired after the acquiredLock.
+ //
+ // Note that there is a race condition here which can result in missing
+ // a cyclic edge: it's possible for two threads to simultaneous find
+ // "safe" edges which together form a cycle. Preventing this race
+ // condition efficiently without _introducing_ deadlock is probably
+ // tricky. For now, just accept the race condition---missing a warning
+ // now and then is still better than having no deadlock detection.
+ allowedPriorLocks.put(
+ acquiredLock, new ExampleStackTrace(acquiredLock, this));
+ } else {
+ // Unsafe acquisition order detected. Create and cache a
+ // PotentialDeadlockException.
+ PotentialDeadlockException exception =
+ new PotentialDeadlockException(acquiredLock, this, path);
+ disallowedPriorLocks.put(acquiredLock, exception);
+ policy.handlePotentialDeadlock(exception);
+ }
+ }
+
+ /**
+ * Performs a depth-first traversal of the graph edges defined by each
+ * node's {@code allowedPriorLocks} to find a path between {@code this} and
+ * the specified {@code lock}.
+ *
+ * @return If a path was found, a chained {@link ExampleStackTrace}
+ * illustrating the path to the {@code lock}, or {@code null} if no path
+ * was found.
+ */
+ @Nullable
+ private ExampleStackTrace findPathTo(
+ LockGraphNode node, Set<LockGraphNode> seen) {
+ if (!seen.add(this)) {
+ return null; // Already traversed this node.
+ }
+ ExampleStackTrace found = allowedPriorLocks.get(node);
+ if (found != null) {
+ return found; // Found a path ending at the node!
+ }
+ // Recurse the edges.
+ for (Map.Entry<LockGraphNode, ExampleStackTrace> entry :
+ allowedPriorLocks.entrySet()) {
+ LockGraphNode preAcquiredLock = entry.getKey();
+ found = preAcquiredLock.findPathTo(node, seen);
+ if (found != null) {
+ // One of this node's allowedPriorLocks found a path. Prepend an
+ // ExampleStackTrace(preAcquiredLock, this) to the returned chain of
+ // ExampleStackTraces.
+ ExampleStackTrace path =
+ new ExampleStackTrace(preAcquiredLock, this);
+ path.setStackTrace(entry.getValue().getStackTrace());
+ path.initCause(found);
+ return path;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * CycleDetectingLock implementations must call this method before attempting
+ * to acquire the lock.
+ */
+ private void aboutToAcquire(CycleDetectingLock lock) {
+ if (!lock.isAcquiredByCurrentThread()) {
+ ArrayList<LockGraphNode> acquiredLockList = acquiredLocks.get();
+ LockGraphNode node = lock.getLockGraphNode();
+ node.checkAcquiredLocks(policy, acquiredLockList);
+ acquiredLockList.add(node);
+ }
+ }
+
+ /**
+ * CycleDetectingLock implementations must call this method in a
+ * {@code finally} clause after any attempt to change the lock state,
+ * including both lock and unlock attempts. Failure to do so can result in
+ * corrupting the acquireLocks set.
+ */
+ private void lockStateChanged(CycleDetectingLock lock) {
+ if (!lock.isAcquiredByCurrentThread()) {
+ ArrayList<LockGraphNode> acquiredLockList = acquiredLocks.get();
+ LockGraphNode node = lock.getLockGraphNode();
+ // Iterate in reverse because locks are usually locked/unlocked in a
+ // LIFO order.
+ for (int i = acquiredLockList.size() - 1; i >=0; i--) {
+ if (acquiredLockList.get(i) == node) {
+ acquiredLockList.remove(i);
+ break;
+ }
+ }
+ }
+ }
+
+ final class CycleDetectingReentrantLock
+ extends ReentrantLock implements CycleDetectingLock {
+
+ private final LockGraphNode lockGraphNode;
+
+ private CycleDetectingReentrantLock(
+ LockGraphNode lockGraphNode, boolean fair) {
+ super(fair);
+ this.lockGraphNode = Preconditions.checkNotNull(lockGraphNode);
+ }
+
+ ///// CycleDetectingLock methods. /////
+
+ @Override
+ public LockGraphNode getLockGraphNode() {
+ return lockGraphNode;
+ }
+
+ @Override
+ public boolean isAcquiredByCurrentThread() {
+ return isHeldByCurrentThread();
+ }
+
+ ///// Overridden ReentrantLock methods. /////
+
+ @Override
+ public void lock() {
+ aboutToAcquire(this);
+ try {
+ super.lock();
+ } finally {
+ lockStateChanged(this);
+ }
+ }
+
+ @Override
+ public void lockInterruptibly() throws InterruptedException {
+ aboutToAcquire(this);
+ try {
+ super.lockInterruptibly();
+ } finally {
+ lockStateChanged(this);
+ }
+ }
+
+ @Override
+ public boolean tryLock() {
+ aboutToAcquire(this);
+ try {
+ return super.tryLock();
+ } finally {
+ lockStateChanged(this);
+ }
+ }
+
+ @Override
+ public boolean tryLock(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ aboutToAcquire(this);
+ try {
+ return super.tryLock(timeout, unit);
+ } finally {
+ lockStateChanged(this);
+ }
+ }
+
+ @Override
+ public void unlock() {
+ try {
+ super.unlock();
+ } finally {
+ lockStateChanged(this);
+ }
+ }
+ }
+
+ final class CycleDetectingReentrantReadWriteLock
+ extends ReentrantReadWriteLock implements CycleDetectingLock {
+
+ // These ReadLock/WriteLock implementations shadow those in the
+ // ReentrantReadWriteLock superclass. They are simply wrappers around the
+ // internal Sync object, so this is safe since the shadowed locks are never
+ // exposed or used.
+ private final CycleDetectingReentrantReadLock readLock;
+ private final CycleDetectingReentrantWriteLock writeLock;
+
+ private final LockGraphNode lockGraphNode;
+
+ private CycleDetectingReentrantReadWriteLock(
+ LockGraphNode lockGraphNode, boolean fair) {
+ super(fair);
+ this.readLock = new CycleDetectingReentrantReadLock(this);
+ this.writeLock = new CycleDetectingReentrantWriteLock(this);
+ this.lockGraphNode = Preconditions.checkNotNull(lockGraphNode);
+ }
+
+ ///// Overridden ReentrantReadWriteLock methods. /////
+
+ @Override
+ public ReadLock readLock() {
+ return readLock;
+ }
+
+ @Override
+ public WriteLock writeLock() {
+ return writeLock;
+ }
+
+ ///// CycleDetectingLock methods. /////
+
+ @Override
+ public LockGraphNode getLockGraphNode() {
+ return lockGraphNode;
+ }
+
+ @Override
+ public boolean isAcquiredByCurrentThread() {
+ return isWriteLockedByCurrentThread() || getReadHoldCount() > 0;
+ }
+ }
+
+ private class CycleDetectingReentrantReadLock
+ extends ReentrantReadWriteLock.ReadLock {
+
+ final CycleDetectingReentrantReadWriteLock readWriteLock;
+
+ CycleDetectingReentrantReadLock(
+ CycleDetectingReentrantReadWriteLock readWriteLock) {
+ super(readWriteLock);
+ this.readWriteLock = readWriteLock;
+ }
+
+ @Override
+ public void lock() {
+ aboutToAcquire(readWriteLock);
+ try {
+ super.lock();
+ } finally {
+ lockStateChanged(readWriteLock);
+ }
+ }
+
+ @Override
+ public void lockInterruptibly() throws InterruptedException {
+ aboutToAcquire(readWriteLock);
+ try {
+ super.lockInterruptibly();
+ } finally {
+ lockStateChanged(readWriteLock);
+ }
+ }
+
+ @Override
+ public boolean tryLock() {
+ aboutToAcquire(readWriteLock);
+ try {
+ return super.tryLock();
+ } finally {
+ lockStateChanged(readWriteLock);
+ }
+ }
+
+ @Override
+ public boolean tryLock(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ aboutToAcquire(readWriteLock);
+ try {
+ return super.tryLock(timeout, unit);
+ } finally {
+ lockStateChanged(readWriteLock);
+ }
+ }
+
+ @Override
+ public void unlock() {
+ try {
+ super.unlock();
+ } finally {
+ lockStateChanged(readWriteLock);
+ }
+ }
+ }
+
+ private class CycleDetectingReentrantWriteLock
+ extends ReentrantReadWriteLock.WriteLock {
+
+ final CycleDetectingReentrantReadWriteLock readWriteLock;
+
+ CycleDetectingReentrantWriteLock(
+ CycleDetectingReentrantReadWriteLock readWriteLock) {
+ super(readWriteLock);
+ this.readWriteLock = readWriteLock;
+ }
+
+ @Override
+ public void lock() {
+ aboutToAcquire(readWriteLock);
+ try {
+ super.lock();
+ } finally {
+ lockStateChanged(readWriteLock);
+ }
+ }
+
+ @Override
+ public void lockInterruptibly() throws InterruptedException {
+ aboutToAcquire(readWriteLock);
+ try {
+ super.lockInterruptibly();
+ } finally {
+ lockStateChanged(readWriteLock);
+ }
+ }
+
+ @Override
+ public boolean tryLock() {
+ aboutToAcquire(readWriteLock);
+ try {
+ return super.tryLock();
+ } finally {
+ lockStateChanged(readWriteLock);
+ }
+ }
+
+ @Override
+ public boolean tryLock(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ aboutToAcquire(readWriteLock);
+ try {
+ return super.tryLock(timeout, unit);
+ } finally {
+ lockStateChanged(readWriteLock);
+ }
+ }
+
+ @Override
+ public void unlock() {
+ try {
+ super.unlock();
+ } finally {
+ lockStateChanged(readWriteLock);
+ }
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/ExecutionError.java b/guava/src/com/google/common/util/concurrent/ExecutionError.java
new file mode 100644
index 0000000..1a2edac
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ExecutionError.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * {@link Error} variant of {@link java.util.concurrent.ExecutionException}. As
+ * with {@code ExecutionException}, the error's {@linkplain #getCause() cause}
+ * comes from a failed task, possibly run in another thread. That cause should
+ * itself be an {@code Error}; if not, use {@code ExecutionException} or {@link
+ * UncheckedExecutionException}. This allows the client code to continue to
+ * distinguish between exceptions and errors, even when they come from other
+ * threads.
+ *
+ * @author Chris Povirk
+ * @since 10.0
+ */
+@Beta
+@GwtCompatible
+public class ExecutionError extends Error {
+ /**
+ * Creates a new instance with {@code null} as its detail message.
+ */
+ protected ExecutionError() {}
+
+ /**
+ * Creates a new instance with the given detail message.
+ */
+ protected ExecutionError(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new instance with the given detail message and cause.
+ */
+ public ExecutionError(String message, Error cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a new instance with the given cause.
+ */
+ public ExecutionError(Error cause) {
+ super(cause);
+ }
+
+ private static final long serialVersionUID = 0;
+}
diff --git a/guava/src/com/google/common/util/concurrent/ExecutionList.java b/guava/src/com/google/common/util/concurrent/ExecutionList.java
new file mode 100644
index 0000000..d1b78f5
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ExecutionList.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+
+import java.util.Queue;
+import java.util.concurrent.Executor;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * <p>A list of listeners, each with an associated {@code Executor}, that
+ * guarantees that every {@code Runnable} that is {@linkplain #add added} will
+ * be executed after {@link #execute()} is called. Any {@code Runnable} added
+ * after the call to {@code execute} is still guaranteed to execute. There is no
+ * guarantee, however, that listeners will be executed in the order that they
+ * are added.
+ *
+ * <p>Exceptions thrown by a listener will be propagated up to the executor.
+ * Any exception thrown during {@code Executor.execute} (e.g., a {@code
+ * RejectedExecutionException} or an exception thrown by {@linkplain
+ * MoreExecutors#sameThreadExecutor inline execution}) will be caught and
+ * logged.
+ *
+ * @author Nishant Thakkar
+ * @author Sven Mawson
+ * @since 1.0
+ */
+public final class ExecutionList {
+
+ // Logger to log exceptions caught when running runnables.
+ private static final Logger log =
+ Logger.getLogger(ExecutionList.class.getName());
+
+ // The runnable,executor pairs to execute.
+ private final Queue<RunnableExecutorPair> runnables = Lists.newLinkedList();
+
+ // Boolean we use mark when execution has started. Only accessed from within
+ // synchronized blocks.
+ private boolean executed = false;
+
+ /** Creates a new, empty {@link ExecutionList}. */
+ public ExecutionList() {
+ }
+
+ /**
+ * Adds the {@code Runnable} and accompanying {@code Executor} to the list of
+ * listeners to execute. If execution has already begun, the listener is
+ * executed immediately.
+ *
+ * <p>Note: For fast, lightweight listeners that would be safe to execute in
+ * any thread, consider {@link MoreExecutors#sameThreadExecutor}. For heavier
+ * listeners, {@code sameThreadExecutor()} carries some caveats: First, the
+ * thread that the listener runs in depends on whether the {@code
+ * ExecutionList} has been executed at the time it is added. In particular,
+ * listeners may run in the thread that calls {@code add}. Second, the thread
+ * that calls {@link #execute} may be an internal implementation thread, such
+ * as an RPC network thread, and {@code sameThreadExecutor()} listeners may
+ * run in this thread. Finally, during the execution of a {@code
+ * sameThreadExecutor} listener, all other registered but unexecuted
+ * listeners are prevented from running, even if those listeners are to run
+ * in other executors.
+ */
+ public void add(Runnable runnable, Executor executor) {
+ // Fail fast on a null. We throw NPE here because the contract of
+ // Executor states that it throws NPE on null listener, so we propagate
+ // that contract up into the add method as well.
+ Preconditions.checkNotNull(runnable, "Runnable was null.");
+ Preconditions.checkNotNull(executor, "Executor was null.");
+
+ boolean executeImmediate = false;
+
+ // Lock while we check state. We must maintain the lock while adding the
+ // new pair so that another thread can't run the list out from under us.
+ // We only add to the list if we have not yet started execution.
+ synchronized (runnables) {
+ if (!executed) {
+ runnables.add(new RunnableExecutorPair(runnable, executor));
+ } else {
+ executeImmediate = true;
+ }
+ }
+
+ // Execute the runnable immediately. Because of scheduling this may end up
+ // getting called before some of the previously added runnables, but we're
+ // OK with that. If we want to change the contract to guarantee ordering
+ // among runnables we'd have to modify the logic here to allow it.
+ if (executeImmediate) {
+ new RunnableExecutorPair(runnable, executor).execute();
+ }
+ }
+
+ /**
+ * Runs this execution list, executing all existing pairs in the order they
+ * were added. However, note that listeners added after this point may be
+ * executed before those previously added, and note that the execution order
+ * of all listeners is ultimately chosen by the implementations of the
+ * supplied executors.
+ *
+ * <p>This method is idempotent. Calling it several times in parallel is
+ * semantically equivalent to calling it exactly once.
+ *
+ * @since 10.0 (present in 1.0 as {@code run})
+ */
+ public void execute() {
+ // Lock while we update our state so the add method above will finish adding
+ // any listeners before we start to run them.
+ synchronized (runnables) {
+ if (executed) {
+ return;
+ }
+ executed = true;
+ }
+
+ // At this point the runnables will never be modified by another
+ // thread, so we are safe using it outside of the synchronized block.
+ while (!runnables.isEmpty()) {
+ runnables.poll().execute();
+ }
+ }
+
+ private static class RunnableExecutorPair {
+ final Runnable runnable;
+ final Executor executor;
+
+ RunnableExecutorPair(Runnable runnable, Executor executor) {
+ this.runnable = runnable;
+ this.executor = executor;
+ }
+
+ void execute() {
+ try {
+ executor.execute(runnable);
+ } catch (RuntimeException e) {
+ // Log it and keep going, bad runnable and/or executor. Don't
+ // punish the other runnables if we're given a bad one. We only
+ // catch RuntimeException because we want Errors to propagate up.
+ log.log(Level.SEVERE, "RuntimeException while executing runnable "
+ + runnable + " with executor " + executor, e);
+ }
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/FakeTimeLimiter.java b/guava/src/com/google/common/util/concurrent/FakeTimeLimiter.java
new file mode 100644
index 0000000..890479d
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/FakeTimeLimiter.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A TimeLimiter implementation which actually does not attempt to limit time
+ * at all. This may be desirable to use in some unit tests. More importantly,
+ * attempting to debug a call which is time-limited would be extremely annoying,
+ * so this gives you a time-limiter you can easily swap in for your real
+ * time-limiter while you're debugging.
+ *
+ * @author Kevin Bourrillion
+ * @since 1.0
+ */
+@Beta
+public final class FakeTimeLimiter implements TimeLimiter {
+ @Override
+ public <T> T newProxy(T target, Class<T> interfaceType, long timeoutDuration,
+ TimeUnit timeoutUnit) {
+ return target; // ha ha
+ }
+
+ @Override
+ public <T> T callWithTimeout(Callable<T> callable, long timeoutDuration,
+ TimeUnit timeoutUnit, boolean amInterruptible) throws Exception {
+ return callable.call(); // fooled you
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/ForwardingBlockingQueue.java b/guava/src/com/google/common/util/concurrent/ForwardingBlockingQueue.java
new file mode 100644
index 0000000..f7257a2
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ForwardingBlockingQueue.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.collect.ForwardingQueue;
+
+import java.util.Collection;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link BlockingQueue} which forwards all its method calls to another
+ * {@link BlockingQueue}. Subclasses should override one or more methods to
+ * modify the behavior of the backing collection as desired per the <a
+ * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
+ *
+ * @author Raimundo Mirisola
+ *
+ * @param <E> the type of elements held in this collection
+ * @since 4.0
+ */
+public abstract class ForwardingBlockingQueue<E> extends ForwardingQueue<E>
+ implements BlockingQueue<E> {
+
+ /** Constructor for use by subclasses. */
+ protected ForwardingBlockingQueue() {}
+
+ @Override protected abstract BlockingQueue<E> delegate();
+
+ @Override public int drainTo(
+ Collection<? super E> c, int maxElements) {
+ return delegate().drainTo(c, maxElements);
+ }
+
+ @Override public int drainTo(Collection<? super E> c) {
+ return delegate().drainTo(c);
+ }
+
+ @Override public boolean offer(E e, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return delegate().offer(e, timeout, unit);
+ }
+
+ @Override public E poll(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return delegate().poll(timeout, unit);
+ }
+
+ @Override public void put(E e) throws InterruptedException {
+ delegate().put(e);
+ }
+
+ @Override public int remainingCapacity() {
+ return delegate().remainingCapacity();
+ }
+
+ @Override public E take() throws InterruptedException {
+ return delegate().take();
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/ForwardingCheckedFuture.java b/guava/src/com/google/common/util/concurrent/ForwardingCheckedFuture.java
new file mode 100644
index 0000000..1dee47a
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ForwardingCheckedFuture.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A future which forwards all its method calls to another future. Subclasses
+ * should override one or more methods to modify the behavior of the backing
+ * future as desired per the <a href=
+ * "http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
+ *
+ * <p>Most subclasses can simply extend {@link SimpleForwardingCheckedFuture}.
+ *
+ * @param <V> The result type returned by this Future's {@code get} method
+ * @param <X> The type of the Exception thrown by the Future's
+ * {@code checkedGet} method
+ *
+ * @author Anthony Zana
+ * @since 9.0
+ */
+@Beta
+public abstract class ForwardingCheckedFuture<V, X extends Exception>
+ extends ForwardingListenableFuture<V> implements CheckedFuture<V, X> {
+
+ @Override
+ public V checkedGet() throws X {
+ return delegate().checkedGet();
+ }
+
+ @Override
+ public V checkedGet(long timeout, TimeUnit unit) throws TimeoutException, X {
+ return delegate().checkedGet(timeout, unit);
+ }
+
+ @Override
+ protected abstract CheckedFuture<V, X> delegate();
+
+ // TODO(cpovirk): Use Standard Javadoc form for SimpleForwarding*
+ /**
+ * A simplified version of {@link ForwardingCheckedFuture} where subclasses
+ * can pass in an already constructed {@link CheckedFuture} as the delegate.
+ *
+ * @since 9.0
+ */
+ @Beta
+ public abstract static class SimpleForwardingCheckedFuture<
+ V, X extends Exception> extends ForwardingCheckedFuture<V, X> {
+ private final CheckedFuture<V, X> delegate;
+
+ protected SimpleForwardingCheckedFuture(CheckedFuture<V, X> delegate) {
+ this.delegate = Preconditions.checkNotNull(delegate);
+ }
+
+ @Override
+ protected final CheckedFuture<V, X> delegate() {
+ return delegate;
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/ForwardingExecutorService.java b/guava/src/com/google/common/util/concurrent/ForwardingExecutorService.java
new file mode 100644
index 0000000..9c09af0
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ForwardingExecutorService.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.collect.ForwardingObject;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * An executor service which forwards all its method calls to another executor
+ * service. Subclasses should override one or more methods to modify the
+ * behavior of the backing executor service as desired per the <a
+ * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
+ *
+ * @author Kurt Alfred Kluever
+ * @since 10.0
+ */
+public abstract class ForwardingExecutorService extends ForwardingObject
+ implements ExecutorService {
+ /** Constructor for use by subclasses. */
+ protected ForwardingExecutorService() {}
+
+ @Override
+ protected abstract ExecutorService delegate();
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return delegate().awaitTermination(timeout, unit);
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(
+ Collection<? extends Callable<T>> tasks) throws InterruptedException {
+ return delegate().invokeAll(tasks);
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return delegate().invokeAll(tasks, timeout, unit);
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ return delegate().invokeAny(tasks);
+ }
+
+ @Override
+ public <T> T invokeAny(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return delegate().invokeAny(tasks, timeout, unit);
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return delegate().isShutdown();
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return delegate().isTerminated();
+ }
+
+ @Override
+ public void shutdown() {
+ delegate().shutdown();
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ return delegate().shutdownNow();
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ delegate().execute(command);
+ }
+
+ public <T> Future<T> submit(Callable<T> task) {
+ return delegate().submit(task);
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ return delegate().submit(task);
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ return delegate().submit(task, result);
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/ForwardingFuture.java b/guava/src/com/google/common/util/concurrent/ForwardingFuture.java
new file mode 100644
index 0000000..9fcd119
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ForwardingFuture.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ForwardingObject;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A {@link Future} which forwards all its method calls to another future.
+ * Subclasses should override one or more methods to modify the behavior of
+ * the backing future as desired per the <a
+ * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
+ *
+ * <p>Most subclasses can just use {@link SimpleForwardingFuture}.
+ *
+ * @author Sven Mawson
+ * @since 1.0
+ */
+public abstract class ForwardingFuture<V> extends ForwardingObject
+ implements Future<V> {
+
+ /** Constructor for use by subclasses. */
+ protected ForwardingFuture() {}
+
+ @Override protected abstract Future<V> delegate();
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return delegate().cancel(mayInterruptIfRunning);
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return delegate().isCancelled();
+ }
+
+ @Override
+ public boolean isDone() {
+ return delegate().isDone();
+ }
+
+ @Override
+ public V get() throws InterruptedException, ExecutionException {
+ return delegate().get();
+ }
+
+ @Override
+ public V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return delegate().get(timeout, unit);
+ }
+
+ /*
+ * TODO(cpovirk): Use standard Javadoc form for SimpleForwarding* class and
+ * constructor
+ */
+ /**
+ * A simplified version of {@link ForwardingFuture} where subclasses
+ * can pass in an already constructed {@link Future} as the delegate.
+ *
+ * @since 9.0
+ */
+ public abstract static class SimpleForwardingFuture<V>
+ extends ForwardingFuture<V> {
+ private final Future<V> delegate;
+
+ protected SimpleForwardingFuture(Future<V> delegate) {
+ this.delegate = Preconditions.checkNotNull(delegate);
+ }
+
+ @Override
+ protected final Future<V> delegate() {
+ return delegate;
+ }
+
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/ForwardingListenableFuture.java b/guava/src/com/google/common/util/concurrent/ForwardingListenableFuture.java
new file mode 100644
index 0000000..79f6d53
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ForwardingListenableFuture.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.base.Preconditions;
+
+import java.util.concurrent.Executor;
+
+/**
+ * A {@link ListenableFuture} which forwards all its method calls to another
+ * future. Subclasses should override one or more methods to modify the behavior
+ * of the backing future as desired per the <a
+ * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
+ *
+ * <p>Most subclasses can just use {@link SimpleForwardingListenableFuture}.
+ *
+ * @param <V> The result type returned by this Future's {@code get} method
+ *
+ * @author Shardul Deo
+ * @since 4.0
+ */
+public abstract class ForwardingListenableFuture<V> extends ForwardingFuture<V>
+ implements ListenableFuture<V> {
+
+ /** Constructor for use by subclasses. */
+ protected ForwardingListenableFuture() {}
+
+ @Override
+ protected abstract ListenableFuture<V> delegate();
+
+ @Override
+ public void addListener(Runnable listener, Executor exec) {
+ delegate().addListener(listener, exec);
+ }
+
+ /*
+ * TODO(cpovirk): Use standard Javadoc form for SimpleForwarding* class and
+ * constructor
+ */
+ /**
+ * A simplified version of {@link ForwardingListenableFuture} where subclasses
+ * can pass in an already constructed {@link ListenableFuture}
+ * as the delegate.
+ *
+ * @since 9.0
+ */
+ public abstract static class SimpleForwardingListenableFuture<V>
+ extends ForwardingListenableFuture<V> {
+ private final ListenableFuture<V> delegate;
+
+ protected SimpleForwardingListenableFuture(ListenableFuture<V> delegate) {
+ this.delegate = Preconditions.checkNotNull(delegate);
+ }
+
+ @Override
+ protected final ListenableFuture<V> delegate() {
+ return delegate;
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/ForwardingListeningExecutorService.java b/guava/src/com/google/common/util/concurrent/ForwardingListeningExecutorService.java
new file mode 100644
index 0000000..27e44de
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ForwardingListeningExecutorService.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import java.util.concurrent.Callable;
+
+/**
+ * A listening executor service which forwards all its method calls to another
+ * listening executor service. Subclasses should override one or more methods to
+ * modify the behavior of the backing executor service as desired per the <a
+ * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
+ *
+ * @author Isaac Shum
+ * @since 10.0
+ */
+public abstract class ForwardingListeningExecutorService
+ extends ForwardingExecutorService implements ListeningExecutorService {
+ /** Constructor for use by subclasses. */
+ protected ForwardingListeningExecutorService() {}
+
+ @Override
+ protected abstract ListeningExecutorService delegate();
+
+ @Override
+ public <T> ListenableFuture<T> submit(Callable<T> task) {
+ return delegate().submit(task);
+ }
+
+ @Override
+ public ListenableFuture<?> submit(Runnable task) {
+ return delegate().submit(task);
+ }
+
+ @Override
+ public <T> ListenableFuture<T> submit(Runnable task, T result) {
+ return delegate().submit(task, result);
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/ForwardingService.java b/guava/src/com/google/common/util/concurrent/ForwardingService.java
new file mode 100644
index 0000000..0fff279
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ForwardingService.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ForwardingObject;
+
+import java.util.concurrent.Executor;
+
+/**
+ * A {@link Service} that forwards all method calls to another service.
+ *
+ * @author Chris Nokleberg
+ * @since 1.0
+ */
+@Beta
+public abstract class ForwardingService extends ForwardingObject
+ implements Service {
+
+ /** Constructor for use by subclasses. */
+ protected ForwardingService() {}
+
+ @Override protected abstract Service delegate();
+
+ @Override public ListenableFuture<State> start() {
+ return delegate().start();
+ }
+
+ @Override public State state() {
+ return delegate().state();
+ }
+
+ @Override public ListenableFuture<State> stop() {
+ return delegate().stop();
+ }
+
+ @Override public State startAndWait() {
+ return delegate().startAndWait();
+ }
+
+ @Override public State stopAndWait() {
+ return delegate().stopAndWait();
+ }
+
+ @Override public boolean isRunning() {
+ return delegate().isRunning();
+ }
+
+ @Override public void addListener(Listener listener, Executor executor) {
+ delegate().addListener(listener, executor);
+ }
+
+ /**
+ * A sensible default implementation of {@link #startAndWait()}, in terms of
+ * {@link #start}. If you override {@link #start}, you may wish to override
+ * {@link #startAndWait()} to forward to this implementation.
+ * @since 9.0
+ */
+ protected State standardStartAndWait() {
+ return Futures.getUnchecked(start());
+ }
+
+ /**
+ * A sensible default implementation of {@link #stopAndWait()}, in terms of
+ * {@link #stop}. If you override {@link #stop}, you may wish to override
+ * {@link #stopAndWait()} to forward to this implementation.
+ * @since 9.0
+ */
+ protected State standardStopAndWait() {
+ return Futures.getUnchecked(stop());
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/FutureCallback.java b/guava/src/com/google/common/util/concurrent/FutureCallback.java
new file mode 100644
index 0000000..7b39d4a
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/FutureCallback.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * A callback for accepting the results of a {@link java.util.concurrent.Future}
+ * computation asynchronously.
+ *
+ * <p>To attach to a {@link ListenableFuture} use {@link Futures#addCallback}.
+ *
+ * @author Anthony Zana
+ * @since 10.0
+ */
+@Beta
+public interface FutureCallback<V> {
+ /**
+ * Invoked with the result of the {@code Future} computation when it is
+ * successful.
+ */
+ void onSuccess(V result);
+
+ /**
+ * Invoked when a {@code Future} computation fails or is canceled.
+ *
+ * <p>If the future's {@link Future#get() get} method throws an {@link
+ * ExecutionException}, then the cause is passed to this method. Any other
+ * thrown object is passed unaltered.
+ */
+ void onFailure(Throwable t);
+}
diff --git a/guava/src/com/google/common/util/concurrent/Futures.java b/guava/src/com/google/common/util/concurrent/Futures.java
new file mode 100644
index 0000000..0ff8e8a
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/Futures.java
@@ -0,0 +1,1249 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
+import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
+import static com.google.common.util.concurrent.Uninterruptibles.putUninterruptibly;
+import static com.google.common.util.concurrent.Uninterruptibles.takeUninterruptibly;
+import static java.lang.Thread.currentThread;
+import static java.util.Arrays.asList;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Ordering;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.annotation.Nullable;
+
+/**
+ * Static utility methods pertaining to the {@link Future} interface.
+ *
+ * <p>Many of these methods use the {@link ListenableFuture} API; consult the
+ * Guava User Guide article on <a href=
+ * "http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained">
+ * {@code ListenableFuture}</a>.
+ *
+ * @author Kevin Bourrillion
+ * @author Nishant Thakkar
+ * @author Sven Mawson
+ * @since 1.0
+ */
+@Beta
+public final class Futures {
+ private Futures() {}
+
+ /**
+ * Creates a {@link CheckedFuture} out of a normal {@link ListenableFuture}
+ * and a {@link Function} that maps from {@link Exception} instances into the
+ * appropriate checked type.
+ *
+ * <p>The given mapping function will be applied to an
+ * {@link InterruptedException}, a {@link CancellationException}, or an
+ * {@link ExecutionException} with the actual cause of the exception.
+ * See {@link Future#get()} for details on the exceptions thrown.
+ *
+ * @since 9.0 (source-compatible since 1.0)
+ */
+ public static <V, X extends Exception> CheckedFuture<V, X> makeChecked(
+ ListenableFuture<V> future, Function<Exception, X> mapper) {
+ return new MappingCheckedFuture<V, X>(checkNotNull(future), mapper);
+ }
+
+ /**
+ * Creates a {@code ListenableFuture} which has its value set immediately upon
+ * construction. The getters just return the value. This {@code Future} can't
+ * be canceled or timed out and its {@code isDone()} method always returns
+ * {@code true}.
+ */
+ public static <V> ListenableFuture<V> immediateFuture(@Nullable V value) {
+ SettableFuture<V> future = SettableFuture.create();
+ future.set(value);
+ return future;
+ }
+
+ /**
+ * Returns a {@code CheckedFuture} which has its value set immediately upon
+ * construction.
+ *
+ * <p>The returned {@code Future} can't be cancelled, and its {@code isDone()}
+ * method always returns {@code true}. Calling {@code get()} or {@code
+ * checkedGet()} will immediately return the provided value.
+ */
+ public static <V, X extends Exception> CheckedFuture<V, X>
+ immediateCheckedFuture(@Nullable V value) {
+ SettableFuture<V> future = SettableFuture.create();
+ future.set(value);
+ return Futures.makeChecked(future, new Function<Exception, X>() {
+ @Override
+ public X apply(Exception e) {
+ throw new AssertionError("impossible");
+ }
+ });
+ }
+
+ /**
+ * Returns a {@code ListenableFuture} which has an exception set immediately
+ * upon construction.
+ *
+ * <p>The returned {@code Future} can't be cancelled, and its {@code isDone()}
+ * method always returns {@code true}. Calling {@code get()} will immediately
+ * throw the provided {@code Throwable} wrapped in an {@code
+ * ExecutionException}.
+ *
+ * @throws Error if the throwable is an {@link Error}.
+ */
+ public static <V> ListenableFuture<V> immediateFailedFuture(
+ Throwable throwable) {
+ checkNotNull(throwable);
+ SettableFuture<V> future = SettableFuture.create();
+ future.setException(throwable);
+ return future;
+ }
+
+ /**
+ * Returns a {@code CheckedFuture} which has an exception set immediately upon
+ * construction.
+ *
+ * <p>The returned {@code Future} can't be cancelled, and its {@code isDone()}
+ * method always returns {@code true}. Calling {@code get()} will immediately
+ * throw the provided {@code Throwable} wrapped in an {@code
+ * ExecutionException}, and calling {@code checkedGet()} will throw the
+ * provided exception itself.
+ *
+ * @throws Error if the throwable is an {@link Error}.
+ */
+ public static <V, X extends Exception> CheckedFuture<V, X>
+ immediateFailedCheckedFuture(final X exception) {
+ checkNotNull(exception);
+ return makeChecked(Futures.<V>immediateFailedFuture(exception),
+ new Function<Exception, X>() {
+ @Override
+ public X apply(Exception e) {
+ return exception;
+ }
+ });
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is asynchronously
+ * derived from the result of the given {@code Future}. More precisely, the
+ * returned {@code Future} takes its result from a {@code Future} produced by
+ * applying the given {@code AsyncFunction} to the result of the original
+ * {@code Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+ * AsyncFunction<RowKey, QueryResult> queryFunction =
+ * new AsyncFunction<RowKey, QueryResult>() {
+ * public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+ * return dataService.read(rowKey);
+ * }
+ * };
+ * ListenableFuture<QueryResult> queryFuture =
+ * transform(rowKeyFuture, queryFunction);
+ * }</pre>
+ *
+ * Note: If the derived {@code Future} is slow or heavyweight to create
+ * (whether the {@code Future} itself is slow or heavyweight to complete is
+ * irrelevant), consider {@linkplain #transform(ListenableFuture,
+ * AsyncFunction, Executor) supplying an executor}. If you do not supply an
+ * executor, {@code transform} will use {@link
+ * MoreExecutors#sameThreadExecutor sameThreadExecutor}, which carries some
+ * caveats for heavier operations. For example, the call to {@code
+ * function.apply} may run on an unpredictable or undesirable thread:
+ *
+ * <ul>
+ * <li>If the input {@code Future} is done at the time {@code transform} is
+ * called, {@code transform} will call {@code function.apply} inline.
+ * <li>If the input {@code Future} is not yet done, {@code transform} will
+ * schedule {@code function.apply} to be run by the thread that completes the
+ * input {@code Future}, which may be an internal system thread such as an
+ * RPC network thread.
+ * </ul>
+ *
+ * Also note that, regardless of which thread executes {@code
+ * function.apply}, all other registered but unexecuted listeners are
+ * prevented from running during its execution, even if those listeners are
+ * to run in other executors.
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in
+ * sync with that of the input future and that of the future returned by the
+ * function. That is, if the returned {@code Future} is cancelled, it will
+ * attempt to cancel the other two, and if either of the other two is
+ * cancelled, the returned {@code Future} will receive a callback in which it
+ * will attempt to cancel itself.
+ *
+ * @param input The future to transform
+ * @param function A function to transform the result of the input future
+ * to the result of the output future
+ * @return A future that holds result of the function (if the input succeeded)
+ * or the original input's failure (if not)
+ * @since 11.0
+ */
+ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+ AsyncFunction<? super I, ? extends O> function) {
+ return transform(input, function, MoreExecutors.sameThreadExecutor());
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is asynchronously
+ * derived from the result of the given {@code Future}. More precisely, the
+ * returned {@code Future} takes its result from a {@code Future} produced by
+ * applying the given {@code AsyncFunction} to the result of the original
+ * {@code Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
+ * AsyncFunction<RowKey, QueryResult> queryFunction =
+ * new AsyncFunction<RowKey, QueryResult>() {
+ * public ListenableFuture<QueryResult> apply(RowKey rowKey) {
+ * return dataService.read(rowKey);
+ * }
+ * };
+ * ListenableFuture<QueryResult> queryFuture =
+ * transform(rowKeyFuture, queryFunction, executor);
+ * }</pre>
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in
+ * sync with that of the input future and that of the future returned by the
+ * chain function. That is, if the returned {@code Future} is cancelled, it
+ * will attempt to cancel the other two, and if either of the other two is
+ * cancelled, the returned {@code Future} will receive a callback in which it
+ * will attempt to cancel itself.
+ *
+ * <p>When the execution of {@code function.apply} is fast and lightweight
+ * (though the {@code Future} it returns need not meet these criteria),
+ * consider {@linkplain #transform(ListenableFuture, AsyncFunction) omitting
+ * the executor} or explicitly specifying {@code sameThreadExecutor}.
+ * However, be aware of the caveats documented in the link above.
+ *
+ * @param input The future to transform
+ * @param function A function to transform the result of the input future
+ * to the result of the output future
+ * @param executor Executor to run the function in.
+ * @return A future that holds result of the function (if the input succeeded)
+ * or the original input's failure (if not)
+ * @since 11.0
+ */
+ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+ AsyncFunction<? super I, ? extends O> function,
+ Executor executor) {
+ ChainingListenableFuture<I, O> output =
+ new ChainingListenableFuture<I, O>(function, input);
+ input.addListener(output, executor);
+ return output;
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is the product of
+ * applying the given {@code Function} to the result of the given {@code
+ * Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<QueryResult> queryFuture = ...;
+ * Function<QueryResult, List<Row>> rowsFunction =
+ * new Function<QueryResult, List<Row>>() {
+ * public List<Row> apply(QueryResult queryResult) {
+ * return queryResult.getRows();
+ * }
+ * };
+ * ListenableFuture<List<Row>> rowsFuture =
+ * transform(queryFuture, rowsFunction);
+ * }</pre>
+ *
+ * Note: If the transformation is slow or heavyweight, consider {@linkplain
+ * #transform(ListenableFuture, Function, Executor) supplying an executor}.
+ * If you do not supply an executor, {@code transform} will use {@link
+ * MoreExecutors#sameThreadExecutor sameThreadExecutor}, which carries some
+ * caveats for heavier operations. For example, the call to {@code
+ * function.apply} may run on an unpredictable or undesirable thread:
+ *
+ * <ul>
+ * <li>If the input {@code Future} is done at the time {@code transform} is
+ * called, {@code transform} will call {@code function.apply} inline.
+ * <li>If the input {@code Future} is not yet done, {@code transform} will
+ * schedule {@code function.apply} to be run by the thread that completes the
+ * input {@code Future}, which may be an internal system thread such as an
+ * RPC network thread.
+ * </ul>
+ *
+ * Also note that, regardless of which thread executes {@code
+ * function.apply}, all other registered but unexecuted listeners are
+ * prevented from running during its execution, even if those listeners are
+ * to run in other executors.
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in
+ * sync with that of the input future. That is, if the returned {@code Future}
+ * is cancelled, it will attempt to cancel the input, and if the input is
+ * cancelled, the returned {@code Future} will receive a callback in which it
+ * will attempt to cancel itself.
+ *
+ * <p>An example use of this method is to convert a serializable object
+ * returned from an RPC into a POJO.
+ *
+ * @param input The future to transform
+ * @param function A Function to transform the results of the provided future
+ * to the results of the returned future. This will be run in the thread
+ * that notifies input it is complete.
+ * @return A future that holds result of the transformation.
+ * @since 9.0 (in 1.0 as {@code compose})
+ */
+ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+ final Function<? super I, ? extends O> function) {
+ return transform(input, function, MoreExecutors.sameThreadExecutor());
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is the product of
+ * applying the given {@code Function} to the result of the given {@code
+ * Future}. Example:
+ *
+ * <pre> {@code
+ * ListenableFuture<QueryResult> queryFuture = ...;
+ * Function<QueryResult, List<Row>> rowsFunction =
+ * new Function<QueryResult, List<Row>>() {
+ * public List<Row> apply(QueryResult queryResult) {
+ * return queryResult.getRows();
+ * }
+ * };
+ * ListenableFuture<List<Row>> rowsFuture =
+ * transform(queryFuture, rowsFunction, executor);
+ * }</pre>
+ *
+ * <p>The returned {@code Future} attempts to keep its cancellation state in
+ * sync with that of the input future. That is, if the returned {@code Future}
+ * is cancelled, it will attempt to cancel the input, and if the input is
+ * cancelled, the returned {@code Future} will receive a callback in which it
+ * will attempt to cancel itself.
+ *
+ * <p>An example use of this method is to convert a serializable object
+ * returned from an RPC into a POJO.
+ *
+ * <p>When the transformation is fast and lightweight, consider {@linkplain
+ * #transform(ListenableFuture, Function) omitting the executor} or
+ * explicitly specifying {@code sameThreadExecutor}. However, be aware of the
+ * caveats documented in the link above.
+ *
+ * @param input The future to transform
+ * @param function A Function to transform the results of the provided future
+ * to the results of the returned future.
+ * @param executor Executor to run the function in.
+ * @return A future that holds result of the transformation.
+ * @since 9.0 (in 2.0 as {@code compose})
+ */
+ public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input,
+ final Function<? super I, ? extends O> function, Executor executor) {
+ checkNotNull(function);
+ AsyncFunction<I, O> wrapperFunction
+ = new AsyncFunction<I, O>() {
+ @Override public ListenableFuture<O> apply(I input) {
+ O output = function.apply(input);
+ return immediateFuture(output);
+ }
+ };
+ return transform(input, wrapperFunction, executor);
+ }
+
+ /**
+ * Like {@link #transform(ListenableFuture, Function)} except that the
+ * transformation {@code function} is invoked on each call to
+ * {@link Future#get() get()} on the returned future.
+ *
+ * <p>The returned {@code Future} reflects the input's cancellation
+ * state directly, and any attempt to cancel the returned Future is likewise
+ * passed through to the input Future.
+ *
+ * <p>Note that calls to {@linkplain Future#get(long, TimeUnit) timed get}
+ * only apply the timeout to the execution of the underlying {@code Future},
+ * <em>not</em> to the execution of the transformation function.
+ *
+ * <p>The primary audience of this method is callers of {@code transform}
+ * who don't have a {@code ListenableFuture} available and
+ * do not mind repeated, lazy function evaluation.
+ *
+ * @param input The future to transform
+ * @param function A Function to transform the results of the provided future
+ * to the results of the returned future.
+ * @return A future that returns the result of the transformation.
+ * @since 10.0
+ */
+ @Beta
+ public static <I, O> Future<O> lazyTransform(final Future<I> input,
+ final Function<? super I, ? extends O> function) {
+ checkNotNull(input);
+ checkNotNull(function);
+ return new Future<O>() {
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return input.cancel(mayInterruptIfRunning);
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return input.isCancelled();
+ }
+
+ @Override
+ public boolean isDone() {
+ return input.isDone();
+ }
+
+ @Override
+ public O get() throws InterruptedException, ExecutionException {
+ return applyTransformation(input.get());
+ }
+
+ @Override
+ public O get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return applyTransformation(input.get(timeout, unit));
+ }
+
+ private O applyTransformation(I input) throws ExecutionException {
+ try {
+ return function.apply(input);
+ } catch (Throwable t) {
+ throw new ExecutionException(t);
+ }
+ }
+ };
+ }
+
+ /**
+ * An implementation of {@code ListenableFuture} that also implements
+ * {@code Runnable} so that it can be used to nest ListenableFutures.
+ * Once the passed-in {@code ListenableFuture} is complete, it calls the
+ * passed-in {@code Function} to generate the result.
+ *
+ * <p>If the function throws any checked exceptions, they should be wrapped
+ * in a {@code UndeclaredThrowableException} so that this class can get
+ * access to the cause.
+ */
+ private static class ChainingListenableFuture<I, O>
+ extends AbstractFuture<O> implements Runnable {
+
+ private AsyncFunction<? super I, ? extends O> function;
+ private ListenableFuture<? extends I> inputFuture;
+ private volatile ListenableFuture<? extends O> outputFuture;
+ private final BlockingQueue<Boolean> mayInterruptIfRunningChannel =
+ new LinkedBlockingQueue<Boolean>(1);
+ private final CountDownLatch outputCreated = new CountDownLatch(1);
+
+ private ChainingListenableFuture(
+ AsyncFunction<? super I, ? extends O> function,
+ ListenableFuture<? extends I> inputFuture) {
+ this.function = checkNotNull(function);
+ this.inputFuture = checkNotNull(inputFuture);
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ /*
+ * Our additional cancellation work needs to occur even if
+ * !mayInterruptIfRunning, so we can't move it into interruptTask().
+ */
+ if (super.cancel(mayInterruptIfRunning)) {
+ // This should never block since only one thread is allowed to cancel
+ // this Future.
+ putUninterruptibly(mayInterruptIfRunningChannel, mayInterruptIfRunning);
+ cancel(inputFuture, mayInterruptIfRunning);
+ cancel(outputFuture, mayInterruptIfRunning);
+ return true;
+ }
+ return false;
+ }
+
+ private void cancel(@Nullable Future<?> future,
+ boolean mayInterruptIfRunning) {
+ if (future != null) {
+ future.cancel(mayInterruptIfRunning);
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ I sourceResult;
+ try {
+ sourceResult = getUninterruptibly(inputFuture);
+ } catch (CancellationException e) {
+ // Cancel this future and return.
+ // At this point, inputFuture is cancelled and outputFuture doesn't
+ // exist, so the value of mayInterruptIfRunning is irrelevant.
+ cancel(false);
+ return;
+ } catch (ExecutionException e) {
+ // Set the cause of the exception as this future's exception
+ setException(e.getCause());
+ return;
+ }
+
+ final ListenableFuture<? extends O> outputFuture = this.outputFuture =
+ function.apply(sourceResult);
+ if (isCancelled()) {
+ // Handles the case where cancel was called while the function was
+ // being applied.
+ // There is a gap in cancel(boolean) between calling sync.cancel()
+ // and storing the value of mayInterruptIfRunning, so this thread
+ // needs to block, waiting for that value.
+ outputFuture.cancel(
+ takeUninterruptibly(mayInterruptIfRunningChannel));
+ this.outputFuture = null;
+ return;
+ }
+ outputFuture.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ // Here it would have been nice to have had an
+ // UninterruptibleListenableFuture, but we don't want to start a
+ // combinatorial explosion of interfaces, so we have to make do.
+ set(getUninterruptibly(outputFuture));
+ } catch (CancellationException e) {
+ // Cancel this future and return.
+ // At this point, inputFuture and outputFuture are done, so the
+ // value of mayInterruptIfRunning is irrelevant.
+ cancel(false);
+ return;
+ } catch (ExecutionException e) {
+ // Set the cause of the exception as this future's exception
+ setException(e.getCause());
+ } finally {
+ // Don't pin inputs beyond completion
+ ChainingListenableFuture.this.outputFuture = null;
+ }
+ }
+ }, MoreExecutors.sameThreadExecutor());
+ } catch (UndeclaredThrowableException e) {
+ // Set the cause of the exception as this future's exception
+ setException(e.getCause());
+ } catch (Exception e) {
+ // This exception is irrelevant in this thread, but useful for the
+ // client
+ setException(e);
+ } catch (Error e) {
+ // Propagate errors up ASAP - our superclass will rethrow the error
+ setException(e);
+ } finally {
+ // Don't pin inputs beyond completion
+ function = null;
+ inputFuture = null;
+ // Allow our get routines to examine outputFuture now.
+ outputCreated.countDown();
+ }
+ }
+ }
+
+ /**
+ * Returns a new {@code ListenableFuture} whose result is the product of
+ * calling {@code get()} on the {@code Future} nested within the given {@code
+ * Future}, effectively chaining the futures one after the other. Example:
+ *
+ * <pre> {@code
+ * SettableFuture<ListenableFuture<String>> nested = SettableFuture.create();
+ * ListenableFuture<String> dereferenced = dereference(nested);
+ * }</pre>
+ *
+ * <p>This call has the same cancellation and execution semantics as {@link
+ * #transform(ListenableFuture, AsyncFunction)}, in that the returned {@code
+ * Future} attempts to keep its cancellation state in sync with both the
+ * input {@code Future} and the nested {@code Future}. The transformation
+ * is very lightweight and therefore takes place in the thread that called
+ * {@code dereference}.
+ *
+ * @param nested The nested future to transform.
+ * @return A future that holds result of the inner future.
+ * @since 13.0
+ */
+ @Beta
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public static <V> ListenableFuture<V> dereference(
+ ListenableFuture<? extends ListenableFuture<? extends V>> nested) {
+ return Futures.transform((ListenableFuture) nested, (AsyncFunction) DEREFERENCER);
+ }
+
+ /**
+ * Helper {@code Function} for {@link #dereference}.
+ */
+ private static final AsyncFunction<ListenableFuture<Object>, Object> DEREFERENCER =
+ new AsyncFunction<ListenableFuture<Object>, Object>() {
+ @Override public ListenableFuture<Object> apply(ListenableFuture<Object> input) {
+ return input;
+ }
+ };
+
+ /**
+ * Creates a new {@code ListenableFuture} whose value is a list containing the
+ * values of all its input futures, if all succeed. If any input fails, the
+ * returned future fails.
+ *
+ * <p>The list of results is in the same order as the input list.
+ *
+ * <p>Canceling this future does not cancel any of the component futures;
+ * however, if any of the provided futures fails or is canceled, this one is,
+ * too.
+ *
+ * @param futures futures to combine
+ * @return a future that provides a list of the results of the component
+ * futures
+ * @since 10.0
+ */
+ @Beta
+ public static <V> ListenableFuture<List<V>> allAsList(
+ ListenableFuture<? extends V>... futures) {
+ return new ListFuture<V>(ImmutableList.copyOf(futures), true,
+ MoreExecutors.sameThreadExecutor());
+ }
+
+ /**
+ * Creates a new {@code ListenableFuture} whose value is a list containing the
+ * values of all its input futures, if all succeed. If any input fails, the
+ * returned future fails.
+ *
+ * <p>The list of results is in the same order as the input list.
+ *
+ * <p>Canceling this future does not cancel any of the component futures;
+ * however, if any of the provided futures fails or is canceled, this one is,
+ * too.
+ *
+ * @param futures futures to combine
+ * @return a future that provides a list of the results of the component
+ * futures
+ * @since 10.0
+ */
+ @Beta
+ public static <V> ListenableFuture<List<V>> allAsList(
+ Iterable<? extends ListenableFuture<? extends V>> futures) {
+ return new ListFuture<V>(ImmutableList.copyOf(futures), true,
+ MoreExecutors.sameThreadExecutor());
+ }
+
+ /**
+ * Creates a new {@code ListenableFuture} whose value is a list containing the
+ * values of all its successful input futures. The list of results is in the
+ * same order as the input list, and if any of the provided futures fails or
+ * is canceled, its corresponding position will contain {@code null} (which is
+ * indistinguishable from the future having a successful value of
+ * {@code null}).
+ *
+ * @param futures futures to combine
+ * @return a future that provides a list of the results of the component
+ * futures
+ * @since 10.0
+ */
+ @Beta
+ public static <V> ListenableFuture<List<V>> successfulAsList(
+ ListenableFuture<? extends V>... futures) {
+ return new ListFuture<V>(ImmutableList.copyOf(futures), false,
+ MoreExecutors.sameThreadExecutor());
+ }
+
+ /**
+ * Creates a new {@code ListenableFuture} whose value is a list containing the
+ * values of all its successful input futures. The list of results is in the
+ * same order as the input list, and if any of the provided futures fails or
+ * is canceled, its corresponding position will contain {@code null} (which is
+ * indistinguishable from the future having a successful value of
+ * {@code null}).
+ *
+ * @param futures futures to combine
+ * @return a future that provides a list of the results of the component
+ * futures
+ * @since 10.0
+ */
+ @Beta
+ public static <V> ListenableFuture<List<V>> successfulAsList(
+ Iterable<? extends ListenableFuture<? extends V>> futures) {
+ return new ListFuture<V>(ImmutableList.copyOf(futures), false,
+ MoreExecutors.sameThreadExecutor());
+ }
+
+ /**
+ * Registers separate success and failure callbacks to be run when the {@code
+ * Future}'s computation is {@linkplain java.util.concurrent.Future#isDone()
+ * complete} or, if the computation is already complete, immediately.
+ *
+ * <p>There is no guaranteed ordering of execution of callbacks, but any
+ * callback added through this method is guaranteed to be called once the
+ * computation is complete.
+ *
+ * Example: <pre> {@code
+ * ListenableFuture<QueryResult> future = ...;
+ * addCallback(future,
+ * new FutureCallback<QueryResult> {
+ * public void onSuccess(QueryResult result) {
+ * storeInCache(result);
+ * }
+ * public void onFailure(Throwable t) {
+ * reportError(t);
+ * }
+ * });}</pre>
+ *
+ * Note: If the callback is slow or heavyweight, consider {@linkplain
+ * #addCallback(ListenableFuture, FutureCallback, Executor) supplying an
+ * executor}. If you do not supply an executor, {@code addCallback} will use
+ * {@link MoreExecutors#sameThreadExecutor sameThreadExecutor}, which carries
+ * some caveats for heavier operations. For example, the callback may run on
+ * an unpredictable or undesirable thread:
+ *
+ * <ul>
+ * <li>If the input {@code Future} is done at the time {@code addCallback} is
+ * called, {@code addCallback} will execute the callback inline.
+ * <li>If the input {@code Future} is not yet done, {@code addCallback} will
+ * schedule the callback to be run by the thread that completes the input
+ * {@code Future}, which may be an internal system thread such as an RPC
+ * network thread.
+ * </ul>
+ *
+ * Also note that, regardless of which thread executes the callback, all
+ * other registered but unexecuted listeners are prevented from running
+ * during its execution, even if those listeners are to run in other
+ * executors.
+ *
+ * <p>For a more general interface to attach a completion listener to a
+ * {@code Future}, see {@link ListenableFuture#addListener addListener}.
+ *
+ * @param future The future attach the callback to.
+ * @param callback The callback to invoke when {@code future} is completed.
+ * @since 10.0
+ */
+ public static <V> void addCallback(ListenableFuture<V> future,
+ FutureCallback<? super V> callback) {
+ addCallback(future, callback, MoreExecutors.sameThreadExecutor());
+ }
+
+ /**
+ * Registers separate success and failure callbacks to be run when the {@code
+ * Future}'s computation is {@linkplain java.util.concurrent.Future#isDone()
+ * complete} or, if the computation is already complete, immediately.
+ *
+ * <p>The callback is run in {@code executor}.
+ * There is no guaranteed ordering of execution of callbacks, but any
+ * callback added through this method is guaranteed to be called once the
+ * computation is complete.
+ *
+ * Example: <pre> {@code
+ * ListenableFuture<QueryResult> future = ...;
+ * Executor e = ...
+ * addCallback(future, e,
+ * new FutureCallback<QueryResult> {
+ * public void onSuccess(QueryResult result) {
+ * storeInCache(result);
+ * }
+ * public void onFailure(Throwable t) {
+ * reportError(t);
+ * }
+ * });}</pre>
+ *
+ * When the callback is fast and lightweight, consider {@linkplain
+ * #addCallback(ListenableFuture, FutureCallback) omitting the executor} or
+ * explicitly specifying {@code sameThreadExecutor}. However, be aware of the
+ * caveats documented in the link above.
+ *
+ * <p>For a more general interface to attach a completion listener to a
+ * {@code Future}, see {@link ListenableFuture#addListener addListener}.
+ *
+ * @param future The future attach the callback to.
+ * @param callback The callback to invoke when {@code future} is completed.
+ * @param executor The executor to run {@code callback} when the future
+ * completes.
+ * @since 10.0
+ */
+ public static <V> void addCallback(final ListenableFuture<V> future,
+ final FutureCallback<? super V> callback, Executor executor) {
+ Preconditions.checkNotNull(callback);
+ Runnable callbackListener = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ // TODO(user): (Before Guava release), validate that this
+ // is the thing for IE.
+ V value = getUninterruptibly(future);
+ callback.onSuccess(value);
+ } catch (ExecutionException e) {
+ callback.onFailure(e.getCause());
+ } catch (RuntimeException e) {
+ callback.onFailure(e);
+ } catch (Error e) {
+ callback.onFailure(e);
+ }
+ }
+ };
+ future.addListener(callbackListener, executor);
+ }
+
+ /**
+ * Returns the result of {@link Future#get()}, converting most exceptions to a
+ * new instance of the given checked exception type. This reduces boilerplate
+ * for a common use of {@code Future} in which it is unnecessary to
+ * programmatically distinguish between exception types or to extract other
+ * information from the exception instance.
+ *
+ * <p>Exceptions from {@code Future.get} are treated as follows:
+ * <ul>
+ * <li>Any {@link ExecutionException} has its <i>cause</i> wrapped in an
+ * {@code X} if the cause is a checked exception, an {@link
+ * UncheckedExecutionException} if the cause is a {@code
+ * RuntimeException}, or an {@link ExecutionError} if the cause is an
+ * {@code Error}.
+ * <li>Any {@link InterruptedException} is wrapped in an {@code X} (after
+ * restoring the interrupt).
+ * <li>Any {@link CancellationException} is propagated untouched, as is any
+ * other {@link RuntimeException} (though {@code get} implementations are
+ * discouraged from throwing such exceptions).
+ * </ul>
+ *
+ * The overall principle is to continue to treat every checked exception as a
+ * checked exception, every unchecked exception as an unchecked exception, and
+ * every error as an error. In addition, the cause of any {@code
+ * ExecutionException} is wrapped in order to ensure that the new stack trace
+ * matches that of the current thread.
+ *
+ * <p>Instances of {@code exceptionClass} are created by choosing an arbitrary
+ * public constructor that accepts zero or more arguments, all of type {@code
+ * String} or {@code Throwable} (preferring constructors with at least one
+ * {@code String}) and calling the constructor via reflection. If the
+ * exception did not already have a cause, one is set by calling {@link
+ * Throwable#initCause(Throwable)} on it. If no such constructor exists, an
+ * {@code IllegalArgumentException} is thrown.
+ *
+ * @throws X if {@code get} throws any checked exception except for an {@code
+ * ExecutionException} whose cause is not itself a checked exception
+ * @throws UncheckedExecutionException if {@code get} throws an {@code
+ * ExecutionException} with a {@code RuntimeException} as its cause
+ * @throws ExecutionError if {@code get} throws an {@code ExecutionException}
+ * with an {@code Error} as its cause
+ * @throws CancellationException if {@code get} throws a {@code
+ * CancellationException}
+ * @throws IllegalArgumentException if {@code exceptionClass} extends {@code
+ * RuntimeException} or does not have a suitable constructor
+ * @since 10.0
+ */
+ @Beta
+ public static <V, X extends Exception> V get(
+ Future<V> future, Class<X> exceptionClass) throws X {
+ checkNotNull(future);
+ checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass),
+ "Futures.get exception type (%s) must not be a RuntimeException",
+ exceptionClass);
+ try {
+ return future.get();
+ } catch (InterruptedException e) {
+ currentThread().interrupt();
+ throw newWithCause(exceptionClass, e);
+ } catch (ExecutionException e) {
+ wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Returns the result of {@link Future#get(long, TimeUnit)}, converting most
+ * exceptions to a new instance of the given checked exception type. This
+ * reduces boilerplate for a common use of {@code Future} in which it is
+ * unnecessary to programmatically distinguish between exception types or to
+ * extract other information from the exception instance.
+ *
+ * <p>Exceptions from {@code Future.get} are treated as follows:
+ * <ul>
+ * <li>Any {@link ExecutionException} has its <i>cause</i> wrapped in an
+ * {@code X} if the cause is a checked exception, an {@link
+ * UncheckedExecutionException} if the cause is a {@code
+ * RuntimeException}, or an {@link ExecutionError} if the cause is an
+ * {@code Error}.
+ * <li>Any {@link InterruptedException} is wrapped in an {@code X} (after
+ * restoring the interrupt).
+ * <li>Any {@link TimeoutException} is wrapped in an {@code X}.
+ * <li>Any {@link CancellationException} is propagated untouched, as is any
+ * other {@link RuntimeException} (though {@code get} implementations are
+ * discouraged from throwing such exceptions).
+ * </ul>
+ *
+ * The overall principle is to continue to treat every checked exception as a
+ * checked exception, every unchecked exception as an unchecked exception, and
+ * every error as an error. In addition, the cause of any {@code
+ * ExecutionException} is wrapped in order to ensure that the new stack trace
+ * matches that of the current thread.
+ *
+ * <p>Instances of {@code exceptionClass} are created by choosing an arbitrary
+ * public constructor that accepts zero or more arguments, all of type {@code
+ * String} or {@code Throwable} (preferring constructors with at least one
+ * {@code String}) and calling the constructor via reflection. If the
+ * exception did not already have a cause, one is set by calling {@link
+ * Throwable#initCause(Throwable)} on it. If no such constructor exists, an
+ * {@code IllegalArgumentException} is thrown.
+ *
+ * @throws X if {@code get} throws any checked exception except for an {@code
+ * ExecutionException} whose cause is not itself a checked exception
+ * @throws UncheckedExecutionException if {@code get} throws an {@code
+ * ExecutionException} with a {@code RuntimeException} as its cause
+ * @throws ExecutionError if {@code get} throws an {@code ExecutionException}
+ * with an {@code Error} as its cause
+ * @throws CancellationException if {@code get} throws a {@code
+ * CancellationException}
+ * @throws IllegalArgumentException if {@code exceptionClass} extends {@code
+ * RuntimeException} or does not have a suitable constructor
+ * @since 10.0
+ */
+ @Beta
+ public static <V, X extends Exception> V get(
+ Future<V> future, long timeout, TimeUnit unit, Class<X> exceptionClass)
+ throws X {
+ checkNotNull(future);
+ checkNotNull(unit);
+ checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass),
+ "Futures.get exception type (%s) must not be a RuntimeException",
+ exceptionClass);
+ try {
+ return future.get(timeout, unit);
+ } catch (InterruptedException e) {
+ currentThread().interrupt();
+ throw newWithCause(exceptionClass, e);
+ } catch (TimeoutException e) {
+ throw newWithCause(exceptionClass, e);
+ } catch (ExecutionException e) {
+ wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
+ throw new AssertionError();
+ }
+ }
+
+ private static <X extends Exception> void wrapAndThrowExceptionOrError(
+ Throwable cause, Class<X> exceptionClass) throws X {
+ if (cause instanceof Error) {
+ throw new ExecutionError((Error) cause);
+ }
+ if (cause instanceof RuntimeException) {
+ throw new UncheckedExecutionException(cause);
+ }
+ throw newWithCause(exceptionClass, cause);
+ }
+
+ /**
+ * Returns the result of calling {@link Future#get()} uninterruptibly on a
+ * task known not to throw a checked exception. This makes {@code Future} more
+ * suitable for lightweight, fast-running tasks that, barring bugs in the
+ * code, will not fail. This gives it exception-handling behavior similar to
+ * that of {@code ForkJoinTask.join}.
+ *
+ * <p>Exceptions from {@code Future.get} are treated as follows:
+ * <ul>
+ * <li>Any {@link ExecutionException} has its <i>cause</i> wrapped in an
+ * {@link UncheckedExecutionException} (if the cause is an {@code
+ * Exception}) or {@link ExecutionError} (if the cause is an {@code
+ * Error}).
+ * <li>Any {@link InterruptedException} causes a retry of the {@code get}
+ * call. The interrupt is restored before {@code getUnchecked} returns.
+ * <li>Any {@link CancellationException} is propagated untouched. So is any
+ * other {@link RuntimeException} ({@code get} implementations are
+ * discouraged from throwing such exceptions).
+ * </ul>
+ *
+ * The overall principle is to eliminate all checked exceptions: to loop to
+ * avoid {@code InterruptedException}, to pass through {@code
+ * CancellationException}, and to wrap any exception from the underlying
+ * computation in an {@code UncheckedExecutionException} or {@code
+ * ExecutionError}.
+ *
+ * <p>For an uninterruptible {@code get} that preserves other exceptions, see
+ * {@link Uninterruptibles#getUninterruptibly(Future)}.
+ *
+ * @throws UncheckedExecutionException if {@code get} throws an {@code
+ * ExecutionException} with an {@code Exception} as its cause
+ * @throws ExecutionError if {@code get} throws an {@code ExecutionException}
+ * with an {@code Error} as its cause
+ * @throws CancellationException if {@code get} throws a {@code
+ * CancellationException}
+ * @since 10.0
+ */
+ @Beta
+ public static <V> V getUnchecked(Future<V> future) {
+ checkNotNull(future);
+ try {
+ return getUninterruptibly(future);
+ } catch (ExecutionException e) {
+ wrapAndThrowUnchecked(e.getCause());
+ throw new AssertionError();
+ }
+ }
+
+ private static void wrapAndThrowUnchecked(Throwable cause) {
+ if (cause instanceof Error) {
+ throw new ExecutionError((Error) cause);
+ }
+ /*
+ * It's a non-Error, non-Exception Throwable. From my survey of such
+ * classes, I believe that most users intended to extend Exception, so we'll
+ * treat it like an Exception.
+ */
+ throw new UncheckedExecutionException(cause);
+ }
+
+ /*
+ * TODO(user): FutureChecker interface for these to be static methods on? If
+ * so, refer to it in the (static-method) Futures.get documentation
+ */
+
+ /*
+ * Arguably we don't need a timed getUnchecked because any operation slow
+ * enough to require a timeout is heavyweight enough to throw a checked
+ * exception and therefore be inappropriate to use with getUnchecked. Further,
+ * it's not clear that converting the checked TimeoutException to a
+ * RuntimeException -- especially to an UncheckedExecutionException, since it
+ * wasn't thrown by the computation -- makes sense, and if we don't convert
+ * it, the user still has to write a try-catch block.
+ *
+ * If you think you would use this method, let us know.
+ */
+
+ private static <X extends Exception> X newWithCause(
+ Class<X> exceptionClass, Throwable cause) {
+ // getConstructors() guarantees this as long as we don't modify the array.
+ @SuppressWarnings("unchecked")
+ List<Constructor<X>> constructors =
+ (List) Arrays.asList(exceptionClass.getConstructors());
+ for (Constructor<X> constructor : preferringStrings(constructors)) {
+ @Nullable X instance = newFromConstructor(constructor, cause);
+ if (instance != null) {
+ if (instance.getCause() == null) {
+ instance.initCause(cause);
+ }
+ return instance;
+ }
+ }
+ throw new IllegalArgumentException(
+ "No appropriate constructor for exception of type " + exceptionClass
+ + " in response to chained exception", cause);
+ }
+
+ private static <X extends Exception> List<Constructor<X>>
+ preferringStrings(List<Constructor<X>> constructors) {
+ return WITH_STRING_PARAM_FIRST.sortedCopy(constructors);
+ }
+
+ private static final Ordering<Constructor<?>> WITH_STRING_PARAM_FIRST =
+ Ordering.natural().onResultOf(new Function<Constructor<?>, Boolean>() {
+ @Override public Boolean apply(Constructor<?> input) {
+ return asList(input.getParameterTypes()).contains(String.class);
+ }
+ }).reverse();
+
+ @Nullable private static <X> X newFromConstructor(
+ Constructor<X> constructor, Throwable cause) {
+ Class<?>[] paramTypes = constructor.getParameterTypes();
+ Object[] params = new Object[paramTypes.length];
+ for (int i = 0; i < paramTypes.length; i++) {
+ Class<?> paramType = paramTypes[i];
+ if (paramType.equals(String.class)) {
+ params[i] = cause.toString();
+ } else if (paramType.equals(Throwable.class)) {
+ params[i] = cause;
+ } else {
+ return null;
+ }
+ }
+ try {
+ return constructor.newInstance(params);
+ } catch (IllegalArgumentException e) {
+ return null;
+ } catch (InstantiationException e) {
+ return null;
+ } catch (IllegalAccessException e) {
+ return null;
+ } catch (InvocationTargetException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Class that implements {@link #allAsList} and {@link #successfulAsList}.
+ * The idea is to create a (null-filled) List and register a listener with
+ * each component future to fill out the value in the List when that future
+ * completes.
+ */
+ private static class ListFuture<V> extends AbstractFuture<List<V>> {
+ ImmutableList<? extends ListenableFuture<? extends V>> futures;
+ final boolean allMustSucceed;
+ final AtomicInteger remaining;
+ List<V> values;
+
+ /**
+ * Constructor.
+ *
+ * @param futures all the futures to build the list from
+ * @param allMustSucceed whether a single failure or cancellation should
+ * propagate to this future
+ * @param listenerExecutor used to run listeners on all the passed in
+ * futures.
+ */
+ ListFuture(
+ final ImmutableList<? extends ListenableFuture<? extends V>> futures,
+ final boolean allMustSucceed, final Executor listenerExecutor) {
+ this.futures = futures;
+ this.values = Lists.newArrayListWithCapacity(futures.size());
+ this.allMustSucceed = allMustSucceed;
+ this.remaining = new AtomicInteger(futures.size());
+
+ init(listenerExecutor);
+ }
+
+ private void init(final Executor listenerExecutor) {
+ // First, schedule cleanup to execute when the Future is done.
+ addListener(new Runnable() {
+ @Override
+ public void run() {
+ // By now the values array has either been set as the Future's value,
+ // or (in case of failure) is no longer useful.
+ ListFuture.this.values = null;
+
+ // Let go of the memory held by other futures
+ ListFuture.this.futures = null;
+ }
+ }, MoreExecutors.sameThreadExecutor());
+
+ // Now begin the "real" initialization.
+
+ // Corner case: List is empty.
+ if (futures.isEmpty()) {
+ set(Lists.newArrayList(values));
+ return;
+ }
+
+ // Populate the results list with null initially.
+ for (int i = 0; i < futures.size(); ++i) {
+ values.add(null);
+ }
+
+ // Register a listener on each Future in the list to update
+ // the state of this future.
+ // Note that if all the futures on the list are done prior to completing
+ // this loop, the last call to addListener() will callback to
+ // setOneValue(), transitively call our cleanup listener, and set
+ // this.futures to null.
+ // We store a reference to futures to avoid the NPE.
+ ImmutableList<? extends ListenableFuture<? extends V>> localFutures = futures;
+ for (int i = 0; i < localFutures.size(); i++) {
+ final ListenableFuture<? extends V> listenable = localFutures.get(i);
+ final int index = i;
+ listenable.addListener(new Runnable() {
+ @Override
+ public void run() {
+ setOneValue(index, listenable);
+ }
+ }, listenerExecutor);
+ }
+ }
+
+ /**
+ * Sets the value at the given index to that of the given future.
+ */
+ private void setOneValue(int index, Future<? extends V> future) {
+ List<V> localValues = values;
+ if (isDone() || localValues == null) {
+ // Some other future failed or has been cancelled, causing this one to
+ // also be cancelled or have an exception set. This should only happen
+ // if allMustSucceed is true.
+ checkState(allMustSucceed,
+ "Future was done before all dependencies completed");
+ return;
+ }
+
+ try {
+ checkState(future.isDone(),
+ "Tried to set value from future which is not done");
+ localValues.set(index, getUninterruptibly(future));
+ } catch (CancellationException e) {
+ if (allMustSucceed) {
+ // Set ourselves as cancelled. Let the input futures keep running
+ // as some of them may be used elsewhere.
+ // (Currently we don't override interruptTask, so
+ // mayInterruptIfRunning==false isn't technically necessary.)
+ cancel(false);
+ }
+ } catch (ExecutionException e) {
+ if (allMustSucceed) {
+ // As soon as the first one fails, throw the exception up.
+ // The result of all other inputs is then ignored.
+ setException(e.getCause());
+ }
+ } catch (RuntimeException e) {
+ if (allMustSucceed) {
+ setException(e);
+ }
+ } catch (Error e) {
+ // Propagate errors up ASAP - our superclass will rethrow the error
+ setException(e);
+ } finally {
+ int newRemaining = remaining.decrementAndGet();
+ checkState(newRemaining >= 0, "Less than 0 remaining futures");
+ if (newRemaining == 0) {
+ localValues = values;
+ if (localValues != null) {
+ set(Lists.newArrayList(localValues));
+ } else {
+ checkState(isDone());
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * A checked future that uses a function to map from exceptions to the
+ * appropriate checked type.
+ */
+ private static class MappingCheckedFuture<V, X extends Exception> extends
+ AbstractCheckedFuture<V, X> {
+
+ final Function<Exception, X> mapper;
+
+ MappingCheckedFuture(ListenableFuture<V> delegate,
+ Function<Exception, X> mapper) {
+ super(delegate);
+
+ this.mapper = checkNotNull(mapper);
+ }
+
+ @Override
+ protected X mapException(Exception e) {
+ return mapper.apply(e);
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java b/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java
new file mode 100644
index 0000000..645a648
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/JdkFutureAdapters.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2009 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Utilities necessary for working with libraries that supply plain {@link
+ * Future} instances. Note that, whenver possible, it is strongly preferred to
+ * modify those libraries to return {@code ListenableFuture} directly.
+ *
+ * @author Sven Mawson
+ * @since 10.0 (replacing {@code Futures.makeListenable}, which
+ * existed in 1.0)
+ */
+@Beta
+public final class JdkFutureAdapters {
+ /**
+ * Assigns a thread to the given {@link Future} to provide {@link
+ * ListenableFuture} functionality.
+ *
+ * <p><b>Warning:</b> If the input future does not already implement {@code
+ * ListenableFuture}, the returned future will emulate {@link
+ * ListenableFuture#addListener} by taking a thread from an internal,
+ * unbounded pool at the first call to {@code addListener} and holding it
+ * until the future is {@linkplain Future#isDone() done}.
+ *
+ * <p>Prefer to create {@code ListenableFuture} instances with {@link
+ * SettableFuture}, {@link MoreExecutors#listeningDecorator(
+ * java.util.concurrent.ExecutorService)}, {@link ListenableFutureTask},
+ * {@link AbstractFuture}, and other utilities over creating plain {@code
+ * Future} instances to be upgraded to {@code ListenableFuture} after the
+ * fact.
+ */
+ public static <V> ListenableFuture<V> listenInPoolThread(
+ Future<V> future) {
+ if (future instanceof ListenableFuture) {
+ return (ListenableFuture<V>) future;
+ }
+ return new ListenableFutureAdapter<V>(future);
+ }
+
+ /**
+ * Submits a blocking task for the given {@link Future} to provide {@link
+ * ListenableFuture} functionality.
+ *
+ * <p><b>Warning:</b> If the input future does not already implement {@code
+ * ListenableFuture}, the returned future will emulate {@link
+ * ListenableFuture#addListener} by submitting a task to the given executor at
+ * at the first call to {@code addListener}. The task must be started by the
+ * executor promptly, or else the returned {@code ListenableFuture} may fail
+ * to work. The task's execution consists of blocking until the input future
+ * is {@linkplain Future#isDone() done}, so each call to this method may
+ * claim and hold a thread for an arbitrary length of time. Use of bounded
+ * executors or other executors that may fail to execute a task promptly may
+ * result in deadlocks.
+ *
+ * <p>Prefer to create {@code ListenableFuture} instances with {@link
+ * SettableFuture}, {@link MoreExecutors#listeningDecorator(
+ * java.util.concurrent.ExecutorService)}, {@link ListenableFutureTask},
+ * {@link AbstractFuture}, and other utilities over creating plain {@code
+ * Future} instances to be upgraded to {@code ListenableFuture} after the
+ * fact.
+ *
+ * @since 12.0
+ */
+ public static <V> ListenableFuture<V> listenInPoolThread(
+ Future<V> future, Executor executor) {
+ checkNotNull(executor);
+ if (future instanceof ListenableFuture) {
+ return (ListenableFuture<V>) future;
+ }
+ return new ListenableFutureAdapter<V>(future, executor);
+ }
+
+ /**
+ * An adapter to turn a {@link Future} into a {@link ListenableFuture}. This
+ * will wait on the future to finish, and when it completes, run the
+ * listeners. This implementation will wait on the source future
+ * indefinitely, so if the source future never completes, the adapter will
+ * never complete either.
+ *
+ * <p>If the delegate future is interrupted or throws an unexpected unchecked
+ * exception, the listeners will not be invoked.
+ */
+ private static class ListenableFutureAdapter<V> extends ForwardingFuture<V>
+ implements ListenableFuture<V> {
+
+ private static final ThreadFactory threadFactory =
+ new ThreadFactoryBuilder()
+ .setDaemon(true)
+ .setNameFormat("ListenableFutureAdapter-thread-%d")
+ .build();
+ private static final Executor defaultAdapterExecutor =
+ Executors.newCachedThreadPool(threadFactory);
+
+ private final Executor adapterExecutor;
+
+ // The execution list to hold our listeners.
+ private final ExecutionList executionList = new ExecutionList();
+
+ // This allows us to only start up a thread waiting on the delegate future
+ // when the first listener is added.
+ private final AtomicBoolean hasListeners = new AtomicBoolean(false);
+
+ // The delegate future.
+ private final Future<V> delegate;
+
+ ListenableFutureAdapter(Future<V> delegate) {
+ this(delegate, defaultAdapterExecutor);
+ }
+
+ ListenableFutureAdapter(Future<V> delegate, Executor adapterExecutor) {
+ this.delegate = checkNotNull(delegate);
+ this.adapterExecutor = checkNotNull(adapterExecutor);
+ }
+
+ @Override
+ protected Future<V> delegate() {
+ return delegate;
+ }
+
+ @Override
+ public void addListener(Runnable listener, Executor exec) {
+ executionList.add(listener, exec);
+
+ // When a listener is first added, we run a task that will wait for
+ // the delegate to finish, and when it is done will run the listeners.
+ if (hasListeners.compareAndSet(false, true)) {
+ if (delegate.isDone()) {
+ // If the delegate is already done, run the execution list
+ // immediately on the current thread.
+ executionList.execute();
+ return;
+ }
+
+ adapterExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ delegate.get();
+ } catch (Error e) {
+ throw e;
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ // Threads from our private pool are never interrupted.
+ throw new AssertionError(e);
+ } catch (Throwable e) {
+ // ExecutionException / CancellationException / RuntimeException
+ // The task is done, run the listeners.
+ }
+ executionList.execute();
+ }
+ });
+ }
+ }
+ }
+
+ private JdkFutureAdapters() {}
+}
diff --git a/guava/src/com/google/common/util/concurrent/ListenableFuture.java b/guava/src/com/google/common/util/concurrent/ListenableFuture.java
new file mode 100644
index 0000000..eb05354
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ListenableFuture.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.RejectedExecutionException;
+
+/**
+ * A {@link Future} that accepts completion listeners. Each listener has an
+ * associated executor, and it is invoked using this executor once the future's
+ * computation is {@linkplain Future#isDone() complete}. If the computation has
+ * already completed when the listener is added, the listener will execute
+ * immediately.
+ *
+ * <p>See the Guava User Guide article on <a href=
+ * "http://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained">
+ * {@code ListenableFuture}</a>.
+ *
+ * <h3>Purpose</h3>
+ *
+ * Most commonly, {@code ListenableFuture} is used as an input to another
+ * derived {@code Future}, as in {@link Futures#allAsList(Iterable)
+ * Futures.allAsList}. Many such methods are impossible to implement efficiently
+ * without listener support.
+ *
+ * <p>It is possible to call {@link #addListener addListener} directly, but this
+ * is uncommon because the {@code Runnable} interface does not provide direct
+ * access to the {@code Future} result. (Users who want such access may prefer
+ * {@link Futures#addCallback Futures.addCallback}.) Still, direct {@code
+ * addListener} calls are occasionally useful:<pre> {@code
+ * final String name = ...;
+ * inFlight.add(name);
+ * ListenableFuture<Result> future = service.query(name);
+ * future.addListener(new Runnable() {
+ * public void run() {
+ * processedCount.incrementAndGet();
+ * inFlight.remove(name);
+ * lastProcessed.set(name);
+ * logger.info("Done with {0}", name);
+ * }
+ * }, executor);}</pre>
+ *
+ * <h3>How to get an instance</h3>
+ *
+ * Developers are encouraged to return {@code ListenableFuture} from their
+ * methods so that users can take advantages of the utilities built atop the
+ * class. The way that they will create {@code ListenableFuture} instances
+ * depends on how they currently create {@code Future} instances:
+ * <ul>
+ * <li>If they are returned from an {@code ExecutorService}, convert that
+ * service to a {@link ListeningExecutorService}, usually by calling {@link
+ * MoreExecutors#listeningDecorator(ExecutorService)
+ * MoreExecutors.listeningDecorator}. (Custom executors may find it more
+ * convenient to use {@link ListenableFutureTask} directly.)
+ * <li>If they are manually filled in by a call to {@link FutureTask#set} or a
+ * similar method, create a {@link SettableFuture} instead. (Users with more
+ * complex needs may prefer {@link AbstractFuture}.)
+ * </ul>
+ *
+ * Occasionally, an API will return a plain {@code Future} and it will be
+ * impossible to change the return type. For this case, we provide a more
+ * expensive workaround in {@code JdkFutureAdapters}. However, when possible, it
+ * is more efficient and reliable to create a {@code ListenableFuture} directly.
+ *
+ * @author Sven Mawson
+ * @author Nishant Thakkar
+ * @since 1.0
+ */
+public interface ListenableFuture<V> extends Future<V> {
+ /**
+ * Registers a listener to be {@linkplain Executor#execute(Runnable) run} on
+ * the given executor. The listener will run when the {@code Future}'s
+ * computation is {@linkplain Future#isDone() complete} or, if the computation
+ * is already complete, immediately.
+ *
+ * <p>There is no guaranteed ordering of execution of listeners, but any
+ * listener added through this method is guaranteed to be called once the
+ * computation is complete.
+ *
+ * <p>Exceptions thrown by a listener will be propagated up to the executor.
+ * Any exception thrown during {@code Executor.execute} (e.g., a {@code
+ * RejectedExecutionException} or an exception thrown by {@linkplain
+ * MoreExecutors#sameThreadExecutor inline execution}) will be caught and
+ * logged.
+ *
+ * <p>Note: For fast, lightweight listeners that would be safe to execute in
+ * any thread, consider {@link MoreExecutors#sameThreadExecutor}. For heavier
+ * listeners, {@code sameThreadExecutor()} carries some caveats. For
+ * example, the listener may run on an unpredictable or undesirable thread:
+ *
+ * <ul>
+ * <li>If the input {@code Future} is done at the time {@code addListener} is
+ * called, {@code addListener} will execute the listener inline.
+ * <li>If the input {@code Future} is not yet done, {@code addListener} will
+ * schedule the listener to be run by the thread that completes the input
+ * {@code Future}, which may be an internal system thread such as an RPC
+ * network thread.
+ * </ul>
+ *
+ * Also note that, regardless of which thread executes the listener, all
+ * other registered but unexecuted listeners are prevented from running
+ * during its execution, even if those listeners are to run in other
+ * executors.
+ *
+ * <p>This is the most general listener interface. For common operations
+ * performed using listeners, see {@link
+ * com.google.common.util.concurrent.Futures}. For a simplified but general
+ * listener interface, see {@link
+ * com.google.common.util.concurrent.Futures#addCallback addCallback()}.
+ *
+ * @param listener the listener to run when the computation is complete
+ * @param executor the executor to run the listener in
+ * @throws NullPointerException if the executor or listener was null
+ * @throws RejectedExecutionException if we tried to execute the listener
+ * immediately but the executor rejected it.
+ */
+ void addListener(Runnable listener, Executor executor);
+}
diff --git a/guava/src/com/google/common/util/concurrent/ListenableFutureTask.java b/guava/src/com/google/common/util/concurrent/ListenableFutureTask.java
new file mode 100644
index 0000000..28c2a0a
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ListenableFutureTask.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.FutureTask;
+
+import javax.annotation.Nullable;
+
+/**
+ * A {@link FutureTask} that also implements the {@link ListenableFuture}
+ * interface. Unlike {@code FutureTask}, {@code ListenableFutureTask} does not
+ * provide an overrideable {@link FutureTask#done() done()} method. For similar
+ * functionality, call {@link #addListener}.
+ *
+ * <p>
+ *
+ * @author Sven Mawson
+ * @since 1.0
+ */
+public final class ListenableFutureTask<V> extends FutureTask<V>
+ implements ListenableFuture<V> {
+
+ // The execution list to hold our listeners.
+ private final ExecutionList executionList = new ExecutionList();
+
+ /**
+ * Creates a {@code ListenableFutureTask} that will upon running, execute the
+ * given {@code Callable}.
+ *
+ * @param callable the callable task
+ * @since 10.0
+ */
+ public static <V> ListenableFutureTask<V> create(Callable<V> callable) {
+ return new ListenableFutureTask<V>(callable);
+ }
+
+ /**
+ * Creates a {@code ListenableFutureTask} 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 ListenableFuture<?> f = ListenableFutureTask.create(runnable,
+ * null)}
+ * @since 10.0
+ */
+ public static <V> ListenableFutureTask<V> create(
+ Runnable runnable, @Nullable V result) {
+ return new ListenableFutureTask<V>(runnable, result);
+ }
+
+ private ListenableFutureTask(Callable<V> callable) {
+ super(callable);
+ }
+
+ private ListenableFutureTask(Runnable runnable, @Nullable V result) {
+ super(runnable, result);
+ }
+
+ @Override
+ public void addListener(Runnable listener, Executor exec) {
+ executionList.add(listener, exec);
+ }
+
+ /**
+ * Internal implementation detail used to invoke the listeners.
+ */
+ @Override
+ protected void done() {
+ executionList.execute();
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/ListeningExecutorService.java b/guava/src/com/google/common/util/concurrent/ListeningExecutorService.java
new file mode 100644
index 0000000..9ea8e48
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ListeningExecutorService.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2010 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An {@link ExecutorService} that returns {@link ListenableFuture} instances. To create an instance
+ * from an existing {@link ExecutorService}, call
+ * {@link MoreExecutors#listeningDecorator(ExecutorService)}.
+ *
+ * @author Chris Povirk
+ * @since 10.0
+ */
+public interface ListeningExecutorService extends ExecutorService {
+ /**
+ * @return a {@code ListenableFuture} representing pending completion of the task
+ * @throws RejectedExecutionException {@inheritDoc}
+ */
+ @Override
+ <T> ListenableFuture<T> submit(Callable<T> task);
+
+ /**
+ * @return a {@code ListenableFuture} representing pending completion of the task
+ * @throws RejectedExecutionException {@inheritDoc}
+ */
+ @Override
+ ListenableFuture<?> submit(Runnable task);
+
+ /**
+ * @return a {@code ListenableFuture} representing pending completion of the task
+ * @throws RejectedExecutionException {@inheritDoc}
+ */
+ @Override
+ <T> ListenableFuture<T> submit(Runnable task, T result);
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>All elements in the returned list must be {@link ListenableFuture} instances.
+ *
+ * @return A list of {@code ListenableFuture} instances representing the tasks, in the same
+ * sequential order as produced by the iterator for the given task list, each of which has
+ * completed.
+ * @throws RejectedExecutionException {@inheritDoc}
+ * @throws NullPointerException if any task is null
+ */
+ @Override
+ <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException;
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>All elements in the returned list must be {@link ListenableFuture} instances.
+ *
+ * @return a list of {@code ListenableFuture} instances 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 RejectedExecutionException {@inheritDoc}
+ * @throws NullPointerException if any task is null
+ */
+ @Override
+ <T> List<Future<T>> invokeAll(
+ Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
+ throws InterruptedException;
+}
diff --git a/guava/src/com/google/common/util/concurrent/ListeningScheduledExecutorService.java b/guava/src/com/google/common/util/concurrent/ListeningScheduledExecutorService.java
new file mode 100644
index 0000000..42dcdd2
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ListeningScheduledExecutorService.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * A {@link ScheduledExecutorService} that returns {@link ListenableFuture}
+ * instances from its {@code ExecutorService} methods. Futures returned by the
+ * {@code schedule*} methods, by contrast, need not implement {@code
+ * ListenableFuture}. (To create an instance from an existing {@link
+ * ScheduledExecutorService}, call {@link
+ * MoreExecutors#listeningDecorator(ScheduledExecutorService)}.
+ *
+ * <p>TODO(cpovirk): make at least the one-time schedule() methods return a
+ * ListenableFuture, too? But then we'll need ListenableScheduledFuture...
+ *
+ * @author Chris Povirk
+ * @since 10.0
+ */
+@Beta
+public interface ListeningScheduledExecutorService
+ extends ScheduledExecutorService, ListeningExecutorService {
+}
diff --git a/guava/src/com/google/common/util/concurrent/Monitor.java b/guava/src/com/google/common/util/concurrent/Monitor.java
new file mode 100644
index 0000000..d8c8693
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/Monitor.java
@@ -0,0 +1,942 @@
+/*
+ * Copyright (C) 2010 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
+
+/**
+ * A synchronization abstraction supporting waiting on arbitrary boolean conditions.
+ *
+ * <p>This class is intended as a replacement for {@link ReentrantLock}. Code using {@code Monitor}
+ * is less error-prone and more readable than code using {@code ReentrantLock}, without significant
+ * performance loss. {@code Monitor} even has the potential for performance gain by optimizing the
+ * evaluation and signaling of conditions. Signaling is entirely
+ * <a href="http://en.wikipedia.org/wiki/Monitor_(synchronization)#Implicit_signaling">
+ * implicit</a>.
+ * By eliminating explicit signaling, this class can guarantee that only one thread is awakened
+ * when a condition becomes true (no "signaling storms" due to use of {@link
+ * java.util.concurrent.locks.Condition#signalAll Condition.signalAll}) and that no signals are lost
+ * (no "hangs" due to incorrect use of {@link java.util.concurrent.locks.Condition#signal
+ * Condition.signal}).
+ *
+ * <p>A thread is said to <i>occupy</i> a monitor if it has <i>entered</i> the monitor but not yet
+ * <i>left</i>. Only one thread may occupy a given monitor at any moment. A monitor is also
+ * reentrant, so a thread may enter a monitor any number of times, and then must leave the same
+ * number of times. The <i>enter</i> and <i>leave</i> operations have the same synchronization
+ * semantics as the built-in Java language synchronization primitives.
+ *
+ * <p>A call to any of the <i>enter</i> methods with <b>void</b> return type should always be
+ * followed immediately by a <i>try/finally</i> block to ensure that the current thread leaves the
+ * monitor cleanly: <pre> {@code
+ *
+ * monitor.enter();
+ * try {
+ * // do things while occupying the monitor
+ * } finally {
+ * monitor.leave();
+ * }}</pre>
+ *
+ * A call to any of the <i>enter</i> methods with <b>boolean</b> return type should always appear as
+ * the condition of an <i>if</i> statement containing a <i>try/finally</i> block to ensure that the
+ * current thread leaves the monitor cleanly: <pre> {@code
+ *
+ * if (monitor.tryEnter()) {
+ * try {
+ * // do things while occupying the monitor
+ * } finally {
+ * monitor.leave();
+ * }
+ * } else {
+ * // do other things since the monitor was not available
+ * }}</pre>
+ *
+ * <h2>Comparison with {@code synchronized} and {@code ReentrantLock}</h2>
+ *
+ * <p>The following examples show a simple threadsafe holder expressed using {@code synchronized},
+ * {@link ReentrantLock}, and {@code Monitor}.
+ *
+ * <h3>{@code synchronized}</h3>
+ *
+ * <p>This version is the fewest lines of code, largely because the synchronization mechanism used
+ * is built into the language and runtime. But the programmer has to remember to avoid a couple of
+ * common bugs: The {@code wait()} must be inside a {@code while} instead of an {@code if}, and
+ * {@code notifyAll()} must be used instead of {@code notify()} because there are two different
+ * logical conditions being awaited. <pre> {@code
+ *
+ * public class SafeBox<V> {
+ * private V value;
+ *
+ * public synchronized V get() throws InterruptedException {
+ * while (value == null) {
+ * wait();
+ * }
+ * V result = value;
+ * value = null;
+ * notifyAll();
+ * return result;
+ * }
+ *
+ * public synchronized void set(V newValue) throws InterruptedException {
+ * while (value != null) {
+ * wait();
+ * }
+ * value = newValue;
+ * notifyAll();
+ * }
+ * }}</pre>
+ *
+ * <h3>{@code ReentrantLock}</h3>
+ *
+ * <p>This version is much more verbose than the {@code synchronized} version, and still suffers
+ * from the need for the programmer to remember to use {@code while} instead of {@code if}.
+ * However, one advantage is that we can introduce two separate {@code Condition} objects, which
+ * allows us to use {@code signal()} instead of {@code signalAll()}, which may be a performance
+ * benefit. <pre> {@code
+ *
+ * public class SafeBox<V> {
+ * private final ReentrantLock lock = new ReentrantLock();
+ * private final Condition valuePresent = lock.newCondition();
+ * private final Condition valueAbsent = lock.newCondition();
+ * private V value;
+ *
+ * public V get() throws InterruptedException {
+ * lock.lock();
+ * try {
+ * while (value == null) {
+ * valuePresent.await();
+ * }
+ * V result = value;
+ * value = null;
+ * valueAbsent.signal();
+ * return result;
+ * } finally {
+ * lock.unlock();
+ * }
+ * }
+ *
+ * public void set(V newValue) throws InterruptedException {
+ * lock.lock();
+ * try {
+ * while (value != null) {
+ * valueAbsent.await();
+ * }
+ * value = newValue;
+ * valuePresent.signal();
+ * } finally {
+ * lock.unlock();
+ * }
+ * }
+ * }}</pre>
+ *
+ * <h3>{@code Monitor}</h3>
+ *
+ * <p>This version adds some verbosity around the {@code Guard} objects, but removes that same
+ * verbosity, and more, from the {@code get} and {@code set} methods. {@code Monitor} implements the
+ * same efficient signaling as we had to hand-code in the {@code ReentrantLock} version above.
+ * Finally, the programmer no longer has to hand-code the wait loop, and therefore doesn't have to
+ * remember to use {@code while} instead of {@code if}. <pre> {@code
+ *
+ * public class SafeBox<V> {
+ * private final Monitor monitor = new Monitor();
+ * private final Monitor.Guard valuePresent = new Monitor.Guard(monitor) {
+ * public boolean isSatisfied() {
+ * return value != null;
+ * }
+ * };
+ * private final Monitor.Guard valueAbsent = new Monitor.Guard(monitor) {
+ * public boolean isSatisfied() {
+ * return value == null;
+ * }
+ * };
+ * private V value;
+ *
+ * public V get() throws InterruptedException {
+ * monitor.enterWhen(valuePresent);
+ * try {
+ * V result = value;
+ * value = null;
+ * return result;
+ * } finally {
+ * monitor.leave();
+ * }
+ * }
+ *
+ * public void set(V newValue) throws InterruptedException {
+ * monitor.enterWhen(valueAbsent);
+ * try {
+ * value = newValue;
+ * } finally {
+ * monitor.leave();
+ * }
+ * }
+ * }}</pre>
+ *
+ * @author Justin T. Sampson
+ * @since 10.0
+ */
+@Beta
+public final class Monitor {
+ // TODO: Use raw LockSupport or AbstractQueuedSynchronizer instead of ReentrantLock.
+
+ /**
+ * A boolean condition for which a thread may wait. A {@code Guard} is associated with a single
+ * {@code Monitor}. The monitor may check the guard at arbitrary times from any thread occupying
+ * the monitor, so code should not be written to rely on how often a guard might or might not be
+ * checked.
+ *
+ * <p>If a {@code Guard} is passed into any method of a {@code Monitor} other than the one it is
+ * associated with, an {@link IllegalMonitorStateException} is thrown.
+ *
+ * @since 10.0
+ */
+ @Beta
+ public abstract static class Guard {
+
+ final Monitor monitor;
+ final Condition condition;
+
+ @GuardedBy("monitor.lock")
+ int waiterCount = 0;
+
+ protected Guard(Monitor monitor) {
+ this.monitor = checkNotNull(monitor, "monitor");
+ this.condition = monitor.lock.newCondition();
+ }
+
+ /**
+ * Evaluates this guard's boolean condition. This method is always called with the associated
+ * monitor already occupied. Implementations of this method must depend only on state protected
+ * by the associated monitor, and must not modify that state.
+ */
+ public abstract boolean isSatisfied();
+
+ @Override
+ public final boolean equals(Object other) {
+ // Overridden as final to ensure identity semantics in Monitor.activeGuards.
+ return this == other;
+ }
+
+ @Override
+ public final int hashCode() {
+ // Overridden as final to ensure identity semantics in Monitor.activeGuards.
+ return super.hashCode();
+ }
+
+ }
+
+ /**
+ * Whether this monitor is fair.
+ */
+ private final boolean fair;
+
+ /**
+ * The lock underlying this monitor.
+ */
+ private final ReentrantLock lock;
+
+ /**
+ * The guards associated with this monitor that currently have waiters ({@code waiterCount > 0}).
+ * This is an ArrayList rather than, say, a HashSet so that iteration and almost all adds don't
+ * incur any object allocation overhead.
+ */
+ @GuardedBy("lock")
+ private final ArrayList<Guard> activeGuards = Lists.newArrayListWithCapacity(1);
+
+ /**
+ * Creates a monitor with a non-fair (but fast) ordering policy. Equivalent to {@code
+ * Monitor(false)}.
+ */
+ public Monitor() {
+ this(false);
+ }
+
+ /**
+ * Creates a monitor with the given ordering policy.
+ *
+ * @param fair whether this monitor should use a fair ordering policy rather than a non-fair (but
+ * fast) one
+ */
+ public Monitor(boolean fair) {
+ this.fair = fair;
+ this.lock = new ReentrantLock(fair);
+ }
+
+ /**
+ * Enters this monitor. Blocks indefinitely.
+ */
+ public void enter() {
+ lock.lock();
+ }
+
+ /**
+ * Enters this monitor. Blocks indefinitely, but may be interrupted.
+ */
+ public void enterInterruptibly() throws InterruptedException {
+ lock.lockInterruptibly();
+ }
+
+ /**
+ * Enters this monitor. Blocks at most the given time.
+ *
+ * @return whether the monitor was entered
+ */
+ public boolean enter(long time, TimeUnit unit) {
+ final ReentrantLock lock = this.lock;
+ if (!fair && lock.tryLock()) {
+ return true;
+ }
+ long startNanos = System.nanoTime();
+ long timeoutNanos = unit.toNanos(time);
+ long remainingNanos = timeoutNanos;
+ boolean interruptIgnored = false;
+ try {
+ while (true) {
+ try {
+ return lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS);
+ } catch (InterruptedException ignored) {
+ interruptIgnored = true;
+ remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
+ }
+ }
+ } finally {
+ if (interruptIgnored) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Enters this monitor. Blocks at most the given time, and may be interrupted.
+ *
+ * @return whether the monitor was entered
+ */
+ public boolean enterInterruptibly(long time, TimeUnit unit) throws InterruptedException {
+ return lock.tryLock(time, unit);
+ }
+
+ /**
+ * Enters this monitor if it is possible to do so immediately. Does not block.
+ *
+ * <p><b>Note:</b> This method disregards the fairness setting of this monitor.
+ *
+ * @return whether the monitor was entered
+ */
+ public boolean tryEnter() {
+ return lock.tryLock();
+ }
+
+ /**
+ * Enters this monitor when the guard is satisfied. Blocks indefinitely, but may be interrupted.
+ */
+ public void enterWhen(Guard guard) throws InterruptedException {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ final ReentrantLock lock = this.lock;
+ boolean reentrant = lock.isHeldByCurrentThread();
+ boolean success = false;
+ lock.lockInterruptibly();
+ try {
+ waitInterruptibly(guard, reentrant);
+ success = true;
+ } finally {
+ if (!success) {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Enters this monitor when the guard is satisfied. Blocks indefinitely.
+ */
+ public void enterWhenUninterruptibly(Guard guard) {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ final ReentrantLock lock = this.lock;
+ boolean reentrant = lock.isHeldByCurrentThread();
+ boolean success = false;
+ lock.lock();
+ try {
+ waitUninterruptibly(guard, reentrant);
+ success = true;
+ } finally {
+ if (!success) {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Enters this monitor when the guard is satisfied. Blocks at most the given time, including both
+ * the time to acquire the lock and the time to wait for the guard to be satisfied, and may be
+ * interrupted.
+ *
+ * @return whether the monitor was entered
+ */
+ public boolean enterWhen(Guard guard, long time, TimeUnit unit) throws InterruptedException {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ final ReentrantLock lock = this.lock;
+ boolean reentrant = lock.isHeldByCurrentThread();
+ long remainingNanos;
+ if (!fair && lock.tryLock()) {
+ remainingNanos = unit.toNanos(time);
+ } else {
+ long startNanos = System.nanoTime();
+ if (!lock.tryLock(time, unit)) {
+ return false;
+ }
+ remainingNanos = unit.toNanos(time) - (System.nanoTime() - startNanos);
+ }
+ boolean satisfied = false;
+ try {
+ satisfied = waitInterruptibly(guard, remainingNanos, reentrant);
+ } finally {
+ if (!satisfied) {
+ lock.unlock();
+ }
+ }
+ return satisfied;
+ }
+
+ /**
+ * Enters this monitor when the guard is satisfied. Blocks at most the given time, including
+ * both the time to acquire the lock and the time to wait for the guard to be satisfied.
+ *
+ * @return whether the monitor was entered
+ */
+ public boolean enterWhenUninterruptibly(Guard guard, long time, TimeUnit unit) {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ final ReentrantLock lock = this.lock;
+ boolean reentrant = lock.isHeldByCurrentThread();
+ boolean interruptIgnored = false;
+ try {
+ long remainingNanos;
+ if (!fair && lock.tryLock()) {
+ remainingNanos = unit.toNanos(time);
+ } else {
+ long startNanos = System.nanoTime();
+ long timeoutNanos = unit.toNanos(time);
+ remainingNanos = timeoutNanos;
+ while (true) {
+ try {
+ if (lock.tryLock(remainingNanos, TimeUnit.NANOSECONDS)) {
+ break;
+ } else {
+ return false;
+ }
+ } catch (InterruptedException ignored) {
+ interruptIgnored = true;
+ } finally {
+ remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
+ }
+ }
+ }
+ boolean satisfied = false;
+ try {
+ satisfied = waitUninterruptibly(guard, remainingNanos, reentrant);
+ } finally {
+ if (!satisfied) {
+ lock.unlock();
+ }
+ }
+ return satisfied;
+ } finally {
+ if (interruptIgnored) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but
+ * does not wait for the guard to be satisfied.
+ *
+ * @return whether the monitor was entered
+ */
+ public boolean enterIf(Guard guard) {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ boolean satisfied = false;
+ try {
+ satisfied = guard.isSatisfied();
+ } finally {
+ if (!satisfied) {
+ lock.unlock();
+ }
+ }
+ return satisfied;
+ }
+
+ /**
+ * Enters this monitor if the guard is satisfied. Blocks indefinitely acquiring the lock, but does
+ * not wait for the guard to be satisfied, and may be interrupted.
+ *
+ * @return whether the monitor was entered
+ */
+ public boolean enterIfInterruptibly(Guard guard) throws InterruptedException {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ boolean satisfied = false;
+ try {
+ satisfied = guard.isSatisfied();
+ } finally {
+ if (!satisfied) {
+ lock.unlock();
+ }
+ }
+ return satisfied;
+ }
+
+ /**
+ * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
+ * lock, but does not wait for the guard to be satisfied.
+ *
+ * @return whether the monitor was entered
+ */
+ public boolean enterIf(Guard guard, long time, TimeUnit unit) {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ final ReentrantLock lock = this.lock;
+ if (!enter(time, unit)) {
+ return false;
+ }
+ boolean satisfied = false;
+ try {
+ satisfied = guard.isSatisfied();
+ } finally {
+ if (!satisfied) {
+ lock.unlock();
+ }
+ }
+ return satisfied;
+ }
+
+ /**
+ * Enters this monitor if the guard is satisfied. Blocks at most the given time acquiring the
+ * lock, but does not wait for the guard to be satisfied, and may be interrupted.
+ *
+ * @return whether the monitor was entered
+ */
+ public boolean enterIfInterruptibly(Guard guard, long time, TimeUnit unit)
+ throws InterruptedException {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ final ReentrantLock lock = this.lock;
+ if (!lock.tryLock(time, unit)) {
+ return false;
+ }
+ boolean satisfied = false;
+ try {
+ satisfied = guard.isSatisfied();
+ } finally {
+ if (!satisfied) {
+ lock.unlock();
+ }
+ }
+ return satisfied;
+ }
+
+ /**
+ * Enters this monitor if it is possible to do so immediately and the guard is satisfied. Does not
+ * block acquiring the lock and does not wait for the guard to be satisfied.
+ *
+ * <p><b>Note:</b> This method disregards the fairness setting of this monitor.
+ *
+ * @return whether the monitor was entered
+ */
+ public boolean tryEnterIf(Guard guard) {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ final ReentrantLock lock = this.lock;
+ if (!lock.tryLock()) {
+ return false;
+ }
+ boolean satisfied = false;
+ try {
+ satisfied = guard.isSatisfied();
+ } finally {
+ if (!satisfied) {
+ lock.unlock();
+ }
+ }
+ return satisfied;
+ }
+
+ /**
+ * Waits for the guard to be satisfied. Waits indefinitely, but may be interrupted. May be
+ * called only by a thread currently occupying this monitor.
+ */
+ public void waitFor(Guard guard) throws InterruptedException {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ if (!lock.isHeldByCurrentThread()) {
+ throw new IllegalMonitorStateException();
+ }
+ waitInterruptibly(guard, true);
+ }
+
+ /**
+ * Waits for the guard to be satisfied. Waits indefinitely. May be called only by a thread
+ * currently occupying this monitor.
+ */
+ public void waitForUninterruptibly(Guard guard) {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ if (!lock.isHeldByCurrentThread()) {
+ throw new IllegalMonitorStateException();
+ }
+ waitUninterruptibly(guard, true);
+ }
+
+ /**
+ * Waits for the guard to be satisfied. Waits at most the given time, and may be interrupted.
+ * May be called only by a thread currently occupying this monitor.
+ *
+ * @return whether the guard is now satisfied
+ */
+ public boolean waitFor(Guard guard, long time, TimeUnit unit) throws InterruptedException {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ if (!lock.isHeldByCurrentThread()) {
+ throw new IllegalMonitorStateException();
+ }
+ return waitInterruptibly(guard, unit.toNanos(time), true);
+ }
+
+ /**
+ * Waits for the guard to be satisfied. Waits at most the given time. May be called only by a
+ * thread currently occupying this monitor.
+ *
+ * @return whether the guard is now satisfied
+ */
+ public boolean waitForUninterruptibly(Guard guard, long time, TimeUnit unit) {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ if (!lock.isHeldByCurrentThread()) {
+ throw new IllegalMonitorStateException();
+ }
+ return waitUninterruptibly(guard, unit.toNanos(time), true);
+ }
+
+ /**
+ * Leaves this monitor. May be called only by a thread currently occupying this monitor.
+ */
+ public void leave() {
+ final ReentrantLock lock = this.lock;
+ if (!lock.isHeldByCurrentThread()) {
+ throw new IllegalMonitorStateException();
+ }
+ try {
+ signalConditionsOfSatisfiedGuards(null);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns whether this monitor is using a fair ordering policy.
+ */
+ public boolean isFair() {
+ return lock.isFair();
+ }
+
+ /**
+ * Returns whether this monitor is occupied by any thread. This method is designed for use in
+ * monitoring of the system state, not for synchronization control.
+ */
+ public boolean isOccupied() {
+ return lock.isLocked();
+ }
+
+ /**
+ * Returns whether the current thread is occupying this monitor (has entered more times than it
+ * has left).
+ */
+ public boolean isOccupiedByCurrentThread() {
+ return lock.isHeldByCurrentThread();
+ }
+
+ /**
+ * Returns the number of times the current thread has entered this monitor in excess of the number
+ * of times it has left. Returns 0 if the current thread is not occupying this monitor.
+ */
+ public int getOccupiedDepth() {
+ return lock.getHoldCount();
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting to enter this monitor. 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.
+ */
+ public int getQueueLength() {
+ return lock.getQueueLength();
+ }
+
+ /**
+ * Returns whether any threads are waiting to enter this monitor. Note that because cancellations
+ * may occur at any time, a {@code true} return does not guarantee that any other thread will ever
+ * enter this monitor. This method is designed primarily for use in monitoring of the system
+ * state.
+ */
+ public boolean hasQueuedThreads() {
+ return lock.hasQueuedThreads();
+ }
+
+ /**
+ * Queries whether the given thread is waiting to enter this monitor. Note that because
+ * cancellations may occur at any time, a {@code true} return does not guarantee that this thread
+ * will ever enter this monitor. This method is designed primarily for use in monitoring of the
+ * system state.
+ */
+ public boolean hasQueuedThread(Thread thread) {
+ return lock.hasQueuedThread(thread);
+ }
+
+ /**
+ * Queries whether any threads are waiting for the given guard to become satisfied. Note that
+ * because timeouts and interrupts may occur at any time, a {@code true} return does not guarantee
+ * that the guard becoming satisfied in the future will awaken any threads. This method is
+ * designed primarily for use in monitoring of the system state.
+ */
+ public boolean hasWaiters(Guard guard) {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ lock.lock();
+ try {
+ return guard.waiterCount > 0;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting for the given guard to become satisfied.
+ * 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.
+ */
+ public int getWaitQueueLength(Guard guard) {
+ if (guard.monitor != this) {
+ throw new IllegalMonitorStateException();
+ }
+ lock.lock();
+ try {
+ return guard.waiterCount;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @GuardedBy("lock")
+ private void signalConditionsOfSatisfiedGuards(@Nullable Guard interruptedGuard) {
+ final ArrayList<Guard> guards = this.activeGuards;
+ final int guardCount = guards.size();
+ try {
+ for (int i = 0; i < guardCount; i++) {
+ Guard guard = guards.get(i);
+ if ((guard == interruptedGuard) && (guard.waiterCount == 1)) {
+ // That one waiter was just interrupted and is throwing InterruptedException rather than
+ // paying attention to the guard being satisfied, so find another waiter on another guard.
+ continue;
+ }
+ if (guard.isSatisfied()) {
+ guard.condition.signal();
+ return;
+ }
+ }
+ } catch (Throwable throwable) {
+ for (int i = 0; i < guardCount; i++) {
+ Guard guard = guards.get(i);
+ guard.condition.signalAll();
+ }
+ throw Throwables.propagate(throwable);
+ }
+ }
+
+ @GuardedBy("lock")
+ private void incrementWaiters(Guard guard) {
+ int waiters = guard.waiterCount++;
+ if (waiters == 0) {
+ activeGuards.add(guard);
+ }
+ }
+
+ @GuardedBy("lock")
+ private void decrementWaiters(Guard guard) {
+ int waiters = --guard.waiterCount;
+ if (waiters == 0) {
+ activeGuards.remove(guard);
+ }
+ }
+
+ @GuardedBy("lock")
+ private void waitInterruptibly(Guard guard, boolean signalBeforeWaiting)
+ throws InterruptedException {
+ if (!guard.isSatisfied()) {
+ if (signalBeforeWaiting) {
+ signalConditionsOfSatisfiedGuards(null);
+ }
+ incrementWaiters(guard);
+ try {
+ final Condition condition = guard.condition;
+ do {
+ try {
+ condition.await();
+ } catch (InterruptedException interrupt) {
+ try {
+ signalConditionsOfSatisfiedGuards(guard);
+ } catch (Throwable throwable) {
+ Thread.currentThread().interrupt();
+ throw Throwables.propagate(throwable);
+ }
+ throw interrupt;
+ }
+ } while (!guard.isSatisfied());
+ } finally {
+ decrementWaiters(guard);
+ }
+ }
+ }
+
+ @GuardedBy("lock")
+ private void waitUninterruptibly(Guard guard, boolean signalBeforeWaiting) {
+ if (!guard.isSatisfied()) {
+ if (signalBeforeWaiting) {
+ signalConditionsOfSatisfiedGuards(null);
+ }
+ incrementWaiters(guard);
+ try {
+ final Condition condition = guard.condition;
+ do {
+ condition.awaitUninterruptibly();
+ } while (!guard.isSatisfied());
+ } finally {
+ decrementWaiters(guard);
+ }
+ }
+ }
+
+ @GuardedBy("lock")
+ private boolean waitInterruptibly(Guard guard, long remainingNanos, boolean signalBeforeWaiting)
+ throws InterruptedException {
+ if (!guard.isSatisfied()) {
+ if (signalBeforeWaiting) {
+ signalConditionsOfSatisfiedGuards(null);
+ }
+ incrementWaiters(guard);
+ try {
+ final Condition condition = guard.condition;
+ do {
+ if (remainingNanos <= 0) {
+ return false;
+ }
+ try {
+ remainingNanos = condition.awaitNanos(remainingNanos);
+ } catch (InterruptedException interrupt) {
+ try {
+ signalConditionsOfSatisfiedGuards(guard);
+ } catch (Throwable throwable) {
+ Thread.currentThread().interrupt();
+ throw Throwables.propagate(throwable);
+ }
+ throw interrupt;
+ }
+ } while (!guard.isSatisfied());
+ } finally {
+ decrementWaiters(guard);
+ }
+ }
+ return true;
+ }
+
+ @GuardedBy("lock")
+ private boolean waitUninterruptibly(Guard guard, long timeoutNanos,
+ boolean signalBeforeWaiting) {
+ if (!guard.isSatisfied()) {
+ long startNanos = System.nanoTime();
+ if (signalBeforeWaiting) {
+ signalConditionsOfSatisfiedGuards(null);
+ }
+ boolean interruptIgnored = false;
+ try {
+ incrementWaiters(guard);
+ try {
+ final Condition condition = guard.condition;
+ long remainingNanos = timeoutNanos;
+ do {
+ if (remainingNanos <= 0) {
+ return false;
+ }
+ try {
+ remainingNanos = condition.awaitNanos(remainingNanos);
+ } catch (InterruptedException ignored) {
+ try {
+ signalConditionsOfSatisfiedGuards(guard);
+ } catch (Throwable throwable) {
+ Thread.currentThread().interrupt();
+ throw Throwables.propagate(throwable);
+ }
+ interruptIgnored = true;
+ remainingNanos = (timeoutNanos - (System.nanoTime() - startNanos));
+ }
+ } while (!guard.isSatisfied());
+ } finally {
+ decrementWaiters(guard);
+ }
+ } finally {
+ if (interruptIgnored) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/guava/src/com/google/common/util/concurrent/MoreExecutors.java b/guava/src/com/google/common/util/concurrent/MoreExecutors.java
new file mode 100644
index 0000000..8699b5a
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/MoreExecutors.java
@@ -0,0 +1,587 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Queues;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Factory and utility methods for {@link java.util.concurrent.Executor}, {@link
+ * ExecutorService}, and {@link ThreadFactory}.
+ *
+ * @author Eric Fellheimer
+ * @author Kyle Littlefield
+ * @author Justin Mahoney
+ * @since 3.0
+ */
+public final class MoreExecutors {
+ private MoreExecutors() {}
+
+ /**
+ * Converts the given ThreadPoolExecutor into an ExecutorService that exits
+ * when the application is complete. It does so by using daemon threads and
+ * adding a shutdown hook to wait for their completion.
+ *
+ * <p>This is mainly for fixed thread pools.
+ * See {@link Executors#newFixedThreadPool(int)}.
+ *
+ * @param executor the executor to modify to make sure it exits when the
+ * application is finished
+ * @param terminationTimeout how long to wait for the executor to
+ * finish before terminating the JVM
+ * @param timeUnit unit of time for the time parameter
+ * @return an unmodifiable version of the input which will not hang the JVM
+ */
+ @Beta
+ public static ExecutorService getExitingExecutorService(
+ ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
+ executor.setThreadFactory(new ThreadFactoryBuilder()
+ .setDaemon(true)
+ .setThreadFactory(executor.getThreadFactory())
+ .build());
+
+ ExecutorService service = Executors.unconfigurableExecutorService(executor);
+
+ addDelayedShutdownHook(service, terminationTimeout, timeUnit);
+
+ return service;
+ }
+
+ /**
+ * Converts the given ScheduledThreadPoolExecutor into a
+ * ScheduledExecutorService that exits when the application is complete. It
+ * does so by using daemon threads and adding a shutdown hook to wait for
+ * their completion.
+ *
+ * <p>This is mainly for fixed thread pools.
+ * See {@link Executors#newScheduledThreadPool(int)}.
+ *
+ * @param executor the executor to modify to make sure it exits when the
+ * application is finished
+ * @param terminationTimeout how long to wait for the executor to
+ * finish before terminating the JVM
+ * @param timeUnit unit of time for the time parameter
+ * @return an unmodifiable version of the input which will not hang the JVM
+ */
+ @Beta
+ public static ScheduledExecutorService getExitingScheduledExecutorService(
+ ScheduledThreadPoolExecutor executor, long terminationTimeout,
+ TimeUnit timeUnit) {
+ executor.setThreadFactory(new ThreadFactoryBuilder()
+ .setDaemon(true)
+ .setThreadFactory(executor.getThreadFactory())
+ .build());
+
+ ScheduledExecutorService service =
+ Executors.unconfigurableScheduledExecutorService(executor);
+
+ addDelayedShutdownHook(service, terminationTimeout, timeUnit);
+
+ return service;
+ }
+
+ /**
+ * Add a shutdown hook to wait for thread completion in the given
+ * {@link ExecutorService service}. This is useful if the given service uses
+ * daemon threads, and we want to keep the JVM from exiting immediately on
+ * shutdown, instead giving these daemon threads a chance to terminate
+ * normally.
+ * @param service ExecutorService which uses daemon threads
+ * @param terminationTimeout how long to wait for the executor to finish
+ * before terminating the JVM
+ * @param timeUnit unit of time for the time parameter
+ */
+ @Beta
+ public static void addDelayedShutdownHook(
+ final ExecutorService service, final long terminationTimeout,
+ final TimeUnit timeUnit) {
+ Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ // We'd like to log progress and failures that may arise in the
+ // following code, but unfortunately the behavior of logging
+ // is undefined in shutdown hooks.
+ // This is because the logging code installs a shutdown hook of its
+ // own. See Cleaner class inside {@link LogManager}.
+ service.shutdown();
+ service.awaitTermination(terminationTimeout, timeUnit);
+ } catch (InterruptedException ignored) {
+ // We're shutting down anyway, so just ignore.
+ }
+ }
+ }, "DelayedShutdownHook-for-" + service));
+ }
+
+ /**
+ * Converts the given ThreadPoolExecutor into an ExecutorService that exits
+ * when the application is complete. It does so by using daemon threads and
+ * adding a shutdown hook to wait for their completion.
+ *
+ * <p>This method waits 120 seconds before continuing with JVM termination,
+ * even if the executor has not finished its work.
+ *
+ * <p>This is mainly for fixed thread pools.
+ * See {@link Executors#newFixedThreadPool(int)}.
+ *
+ * @param executor the executor to modify to make sure it exits when the
+ * application is finished
+ * @return an unmodifiable version of the input which will not hang the JVM
+ */
+ @Beta
+ public static ExecutorService getExitingExecutorService(
+ ThreadPoolExecutor executor) {
+ return getExitingExecutorService(executor, 120, TimeUnit.SECONDS);
+ }
+
+ /**
+ * Converts the given ThreadPoolExecutor into a ScheduledExecutorService that
+ * exits when the application is complete. It does so by using daemon threads
+ * and adding a shutdown hook to wait for their completion.
+ *
+ * <p>This method waits 120 seconds before continuing with JVM termination,
+ * even if the executor has not finished its work.
+ *
+ * <p>This is mainly for fixed thread pools.
+ * See {@link Executors#newScheduledThreadPool(int)}.
+ *
+ * @param executor the executor to modify to make sure it exits when the
+ * application is finished
+ * @return an unmodifiable version of the input which will not hang the JVM
+ */
+ @Beta
+ public static ScheduledExecutorService getExitingScheduledExecutorService(
+ ScheduledThreadPoolExecutor executor) {
+ return getExitingScheduledExecutorService(executor, 120, TimeUnit.SECONDS);
+ }
+
+ /**
+ * Creates an executor service that runs each task in the thread
+ * that invokes {@code execute/submit}, as in {@link CallerRunsPolicy} This
+ * applies both to individually submitted tasks and to collections of tasks
+ * submitted via {@code invokeAll} or {@code invokeAny}. In the latter case,
+ * tasks will run serially on the calling thread. Tasks are run to
+ * completion before a {@code Future} is returned to the caller (unless the
+ * executor has been shutdown).
+ *
+ * <p>Although all tasks are immediately executed in the thread that
+ * submitted the task, this {@code ExecutorService} imposes a small
+ * locking overhead on each task submission in order to implement shutdown
+ * and termination behavior.
+ *
+ * <p>The implementation deviates from the {@code ExecutorService}
+ * specification with regards to the {@code shutdownNow} method. First,
+ * "best-effort" with regards to canceling running tasks is implemented
+ * as "no-effort". No interrupts or other attempts are made to stop
+ * threads executing tasks. Second, the returned list will always be empty,
+ * as any submitted task is considered to have started execution.
+ * This applies also to tasks given to {@code invokeAll} or {@code invokeAny}
+ * which are pending serial execution, even the subset of the tasks that
+ * have not yet started execution. It is unclear from the
+ * {@code ExecutorService} specification if these should be included, and
+ * it's much easier to implement the interpretation that they not be.
+ * Finally, a call to {@code shutdown} or {@code shutdownNow} may result
+ * in concurrent calls to {@code invokeAll/invokeAny} throwing
+ * RejectedExecutionException, although a subset of the tasks may already
+ * have been executed.
+ *
+ * @since 10.0 (<a href="http://code.google.com/p/guava-libraries/wiki/Compatibility"
+ * >mostly source-compatible</a> since 3.0)
+ */
+ public static ListeningExecutorService sameThreadExecutor() {
+ return new SameThreadExecutorService();
+ }
+
+ // See sameThreadExecutor javadoc for behavioral notes.
+ private static class SameThreadExecutorService
+ extends AbstractListeningExecutorService {
+ /**
+ * Lock used whenever accessing the state variables
+ * (runningTasks, shutdown, terminationCondition) of the executor
+ */
+ private final Lock lock = new ReentrantLock();
+
+ /** Signaled after the executor is shutdown and running tasks are done */
+ private final Condition termination = lock.newCondition();
+
+ /*
+ * Conceptually, these two variables describe the executor being in
+ * one of three states:
+ * - Active: shutdown == false
+ * - Shutdown: runningTasks > 0 and shutdown == true
+ * - Terminated: runningTasks == 0 and shutdown == true
+ */
+ private int runningTasks = 0;
+ private boolean shutdown = false;
+
+ @Override
+ public void execute(Runnable command) {
+ startTask();
+ try {
+ command.run();
+ } finally {
+ endTask();
+ }
+ }
+
+ @Override
+ public boolean isShutdown() {
+ lock.lock();
+ try {
+ return shutdown;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public void shutdown() {
+ lock.lock();
+ try {
+ shutdown = true;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ // See sameThreadExecutor javadoc for unusual behavior of this method.
+ @Override
+ public List<Runnable> shutdownNow() {
+ shutdown();
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isTerminated() {
+ lock.lock();
+ try {
+ return shutdown && runningTasks == 0;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ lock.lock();
+ try {
+ for (;;) {
+ if (isTerminated()) {
+ return true;
+ } else if (nanos <= 0) {
+ return false;
+ } else {
+ nanos = termination.awaitNanos(nanos);
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Checks if the executor has been shut down and increments the running
+ * task count.
+ *
+ * @throws RejectedExecutionException if the executor has been previously
+ * shutdown
+ */
+ private void startTask() {
+ lock.lock();
+ try {
+ if (isShutdown()) {
+ throw new RejectedExecutionException("Executor already shutdown");
+ }
+ runningTasks++;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Decrements the running task count.
+ */
+ private void endTask() {
+ lock.lock();
+ try {
+ runningTasks--;
+ if (isTerminated()) {
+ termination.signalAll();
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Creates an {@link ExecutorService} whose {@code submit} and {@code
+ * invokeAll} methods submit {@link ListenableFutureTask} instances to the
+ * given delegate executor. Those methods, as well as {@code execute} and
+ * {@code invokeAny}, are implemented in terms of calls to {@code
+ * delegate.execute}. All other methods are forwarded unchanged to the
+ * delegate. This implies that the returned {@code ListeningExecutorService}
+ * never calls the delegate's {@code submit}, {@code invokeAll}, and {@code
+ * invokeAny} methods, so any special handling of tasks must be implemented in
+ * the delegate's {@code execute} method or by wrapping the returned {@code
+ * ListeningExecutorService}.
+ *
+ * <p>If the delegate executor was already an instance of {@code
+ * ListeningExecutorService}, it is returned untouched, and the rest of this
+ * documentation does not apply.
+ *
+ * @since 10.0
+ */
+ public static ListeningExecutorService listeningDecorator(
+ ExecutorService delegate) {
+ return (delegate instanceof ListeningExecutorService)
+ ? (ListeningExecutorService) delegate
+ : (delegate instanceof ScheduledExecutorService)
+ ? new ScheduledListeningDecorator((ScheduledExecutorService) delegate)
+ : new ListeningDecorator(delegate);
+ }
+
+ /**
+ * Creates a {@link ScheduledExecutorService} whose {@code submit} and {@code
+ * invokeAll} methods submit {@link ListenableFutureTask} instances to the
+ * given delegate executor. Those methods, as well as {@code execute} and
+ * {@code invokeAny}, are implemented in terms of calls to {@code
+ * delegate.execute}. All other methods are forwarded unchanged to the
+ * delegate. This implies that the returned {@code
+ * SchedulingListeningExecutorService} never calls the delegate's {@code
+ * submit}, {@code invokeAll}, and {@code invokeAny} methods, so any special
+ * handling of tasks must be implemented in the delegate's {@code execute}
+ * method or by wrapping the returned {@code
+ * SchedulingListeningExecutorService}.
+ *
+ * <p>If the delegate executor was already an instance of {@code
+ * ListeningScheduledExecutorService}, it is returned untouched, and the rest
+ * of this documentation does not apply.
+ *
+ * @since 10.0
+ */
+ public static ListeningScheduledExecutorService listeningDecorator(
+ ScheduledExecutorService delegate) {
+ return (delegate instanceof ListeningScheduledExecutorService)
+ ? (ListeningScheduledExecutorService) delegate
+ : new ScheduledListeningDecorator(delegate);
+ }
+
+ private static class ListeningDecorator
+ extends AbstractListeningExecutorService {
+ final ExecutorService delegate;
+
+ ListeningDecorator(ExecutorService delegate) {
+ this.delegate = checkNotNull(delegate);
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return delegate.awaitTermination(timeout, unit);
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return delegate.isShutdown();
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return delegate.isTerminated();
+ }
+
+ @Override
+ public void shutdown() {
+ delegate.shutdown();
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ return delegate.shutdownNow();
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ delegate.execute(command);
+ }
+ }
+
+ private static class ScheduledListeningDecorator
+ extends ListeningDecorator implements ListeningScheduledExecutorService {
+ @SuppressWarnings("hiding")
+ final ScheduledExecutorService delegate;
+
+ ScheduledListeningDecorator(ScheduledExecutorService delegate) {
+ super(delegate);
+ this.delegate = checkNotNull(delegate);
+ }
+
+ @Override
+ public ScheduledFuture<?> schedule(
+ Runnable command, long delay, TimeUnit unit) {
+ return delegate.schedule(command, delay, unit);
+ }
+
+ @Override
+ public <V> ScheduledFuture<V> schedule(
+ Callable<V> callable, long delay, TimeUnit unit) {
+ return delegate.schedule(callable, delay, unit);
+ }
+
+ @Override
+ public ScheduledFuture<?> scheduleAtFixedRate(
+ Runnable command, long initialDelay, long period, TimeUnit unit) {
+ return delegate.scheduleAtFixedRate(command, initialDelay, period, unit);
+ }
+
+ @Override
+ public ScheduledFuture<?> scheduleWithFixedDelay(
+ Runnable command, long initialDelay, long delay, TimeUnit unit) {
+ return delegate.scheduleWithFixedDelay(
+ command, initialDelay, delay, unit);
+ }
+ }
+
+ /*
+ * This following method is a modified version of one found in
+ * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/test/tck/AbstractExecutorServiceTest.java?revision=1.30
+ * which contained the following notice:
+ *
+ * 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/
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+ /**
+ * An implementation of {@link ExecutorService#invokeAny} for {@link ListeningExecutorService}
+ * implementations.
+ */ static <T> T invokeAnyImpl(ListeningExecutorService executorService,
+ Collection<? extends Callable<T>> tasks, boolean timed, long nanos)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ int ntasks = tasks.size();
+ checkArgument(ntasks > 0);
+ List<Future<T>> futures = Lists.newArrayListWithCapacity(ntasks);
+ BlockingQueue<Future<T>> futureQueue = Queues.newLinkedBlockingQueue();
+
+ // 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;
+ long lastTime = timed ? System.nanoTime() : 0;
+ Iterator<? extends Callable<T>> it = tasks.iterator();
+
+ futures.add(submitAndAddQueueListener(executorService, it.next(), futureQueue));
+ --ntasks;
+ int active = 1;
+
+ for (;;) {
+ Future<T> f = futureQueue.poll();
+ if (f == null) {
+ if (ntasks > 0) {
+ --ntasks;
+ futures.add(submitAndAddQueueListener(executorService, it.next(), futureQueue));
+ ++active;
+ } else if (active == 0) {
+ break;
+ } else if (timed) {
+ f = futureQueue.poll(nanos, TimeUnit.NANOSECONDS);
+ if (f == null) {
+ throw new TimeoutException();
+ }
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ } else {
+ f = futureQueue.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(null);
+ }
+ throw ee;
+ } finally {
+ for (Future<T> f : futures) {
+ f.cancel(true);
+ }
+ }
+ }
+
+ /**
+ * Submits the task and adds a listener that adds the future to {@code queue} when it completes.
+ */
+ private static <T> ListenableFuture<T> submitAndAddQueueListener(
+ ListeningExecutorService executorService, Callable<T> task,
+ final BlockingQueue<Future<T>> queue) {
+ final ListenableFuture<T> future = executorService.submit(task);
+ future.addListener(new Runnable() {
+ @Override public void run() {
+ queue.add(future);
+ }
+ }, MoreExecutors.sameThreadExecutor());
+ return future;
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/RateLimiter.java b/guava/src/com/google/common/util/concurrent/RateLimiter.java
new file mode 100644
index 0000000..eaf3aa9
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/RateLimiter.java
@@ -0,0 +1,658 @@
+/*
+ * Copyright (C) 2012 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Ticker;
+
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * A rate limiter. Conceptually, a rate limiter distributes permits at a
+ * configurable rate. Each {@link #acquire()} blocks if necessary until a permit is
+ * available, and then takes it. Once acquired, permits need not be released.
+ *
+ * <p>Rate limiters are often used to restrict the rate at which some
+ * physical or logical resource is accessed. This is in contrast to {@link
+ * java.util.concurrent.Semaphore} which restricts the number of concurrent
+ * accesses instead of the rate (note though that concurrency and rate are closely related,
+ * e.g. see <a href="http://en.wikipedia.org/wiki/Little's_law">Little's Law</a>).
+ *
+ * <p>A {@code RateLimiter} is defined primarily by the rate at which permits
+ * are issued. Absent additional configuration, permits will be distributed at a
+ * fixed rate, defined in terms of permits per second. Permits will be distributed
+ * smoothly, with the delay between individual permits being adjusted to ensure
+ * that the configured rate is maintained.
+ *
+ * <p>It is possible to configure a {@code RateLimiter} to have a warmup
+ * period during which time the permits issued each second steadily increases until
+ * it hits the stable rate.
+ *
+ * <p>As an example, imagine that we have a list of tasks to execute, but we don't want to
+ * submit more than 2 per second:
+ *<pre> {@code
+ * final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
+ * void submitTasks(List<Runnable> tasks, Executor executor) {
+ * for (Runnable task : tasks) {
+ * rateLimiter.acquire(); // may wait
+ * executor.execute(task);
+ * }
+ * }
+ *}</pre>
+ *
+ * <p>As another example, imagine that we produce a stream of data, and we want to cap it
+ * at 5kb per second. This could be accomplished by requiring a permit per byte, and specifying
+ * a rate of 5000 permits per second:
+ *<pre> {@code
+ * final RateLimiter rateLimiter = RateLimiter.create(5000.0); // rate = 5000 permits per second
+ * void submitPacket(byte[] packet) {
+ * rateLimiter.acquire(packet.length);
+ * networkService.send(packet);
+ * }
+ *}</pre>
+ *
+ * <p>It is important to note that the number of permits requested <i>never</i>
+ * affect the throttling of the request itself (an invocation to {@code acquire(1)}
+ * and an invocation to {@code acquire(1000)} will result in exactly the same throttling, if any),
+ * but it affects the throttling of the <i>next</i> request. I.e., if an expensive task
+ * arrives at an idle RateLimiter, it will be granted immediately, but it is the <i>next</i>
+ * request that will experience extra throttling, thus paying for the cost of the expensive
+ * task.
+ *
+ * <p>Note: {@code RateLimiter} does not provide fairness guarantees.
+ *
+ * @author Dimitris Andreou
+ * @since 13.0
+ */
+// TODO(user): switch to nano precision. A natural unit of cost is "bytes", and a micro precision
+// would mean a maximum rate of "1MB/s", which might be small in some cases.
+@ThreadSafe
+@Beta
+public abstract class RateLimiter {
+ /*
+ * How is the RateLimiter designed, and why?
+ *
+ * The primary feature of a RateLimiter is its "stable rate", the maximum rate that
+ * is should allow at normal conditions. This is enforced by "throttling" incoming
+ * requests as needed, i.e. compute, for an incoming request, the appropriate throttle time,
+ * and make the calling thread wait as much.
+ *
+ * The simplest way to maintain a rate of QPS is to keep the timestamp of the last
+ * granted request, and ensure that (1/QPS) seconds have elapsed since then. For example,
+ * for a rate of QPS=5 (5 tokens per second), if we ensure that a request isn't granted
+ * earlier than 200ms after the the last one, then we achieve the intended rate.
+ * If a request comes and the last request was granted only 100ms ago, then we wait for
+ * another 100ms. At this rate, serving 15 fresh permits (i.e. for an acquire(15) request)
+ * naturally takes 3 seconds.
+ *
+ * It is important to realize that such a RateLimiter has a very superficial memory
+ * of the past: it only remembers the last request. What if the RateLimiter was unused for
+ * a long period of time, then a request arrived and was immediately granted?
+ * This RateLimiter would immediately forget about that past underutilization. This may
+ * result in either underutilization or overflow, depending on the real world consequences
+ * of not using the expected rate.
+ *
+ * Past underutilization could mean that excess resources are available. Then, the RateLimiter
+ * should speed up for a while, to take advantage of these resources. This is important
+ * when the rate is applied to networking (limiting bandwidth), where past underutilization
+ * typically translates to "almost empty buffers", which can be filled immediately.
+ *
+ * On the other hand, past underutilization could mean that "the server responsible for
+ * handling the request has become less ready for future requests", i.e. its caches become
+ * stale, and requests become more likely to trigger expensive operations (a more extreme
+ * case of this example is when a server has just booted, and it is mostly busy with getting
+ * itself up to speed).
+ *
+ * To deal with such scenarios, we add an extra dimension, that of "past underutilization",
+ * modeled by "storedPermits" variable. This variable is zero when there is no
+ * underutilization, and it can grow up to maxStoredPermits, for sufficiently large
+ * underutilization. So, the requested permits, by an invocation acquire(permits),
+ * are served from:
+ * - stored permits (if available)
+ * - fresh permits (for any remaining permits)
+ *
+ * How this works is best explained with an example:
+ *
+ * For a RateLimiter that produces 1 token per second, every second
+ * that goes by with the RateLimiter being unused, we increase storedPermits by 1.
+ * Say we leave the RateLimiter unused for 10 seconds (i.e., we expected a request at time
+ * X, but we are at time X + 10 seconds before a request actually arrives; this is
+ * also related to the point made in the last paragraph), thus storedPermits
+ * becomes 10.0 (assuming maxStoredPermits >= 10.0). At that point, a request of acquire(3)
+ * arrives. We serve this request out of storedPermits, and reduce that to 7.0 (how this is
+ * translated to throttling time is discussed later). Immediately after, assume that an
+ * acquire(10) request arriving. We serve the request partly from storedPermits,
+ * using all the remaining 7.0 permits, and the remaining 3.0, we serve them by fresh permits
+ * produced by the rate limiter.
+ *
+ * We already know how much time it takes to serve 3 fresh permits: if the rate is
+ * "1 token per second", then this will take 3 seconds. But what does it mean to serve 7
+ * stored permits? As explained above, there is no unique answer. If we are primarily
+ * interested to deal with underutilization, then we want stored permits to be given out
+ * /faster/ than fresh ones, because underutilization = free resources for the taking.
+ * If we are primarily interested to deal with overflow, then stored permits could
+ * be given out /slower/ than fresh ones. Thus, we require a (different in each case)
+ * function that translates storedPermits to throtting time.
+ *
+ * This role is played by storedPermitsToWaitTime(double storedPermits, double permitsToTake).
+ * The underlying model is a continuous function mapping storedPermits
+ * (from 0.0 to maxStoredPermits) onto the 1/rate (i.e. intervals) that is effective at the given
+ * storedPermits. "storedPermits" essentially measure unused time; we spend unused time
+ * buying/storing permits. Rate is "permits / time", thus "1 / rate = time / permits".
+ * Thus, "1/rate" (time / permits) times "permits" gives time, i.e., integrals on this
+ * function (which is what storedPermitsToWaitTime() computes) correspond to minimum intervals
+ * between subsequent requests, for the specified number of requested permits.
+ *
+ * Here is an example of storedPermitsToWaitTime:
+ * If storedPermits == 10.0, and we want 3 permits, we take them from storedPermits,
+ * reducing them to 7.0, and compute the throttling for these as a call to
+ * storedPermitsToWaitTime(storedPermits = 10.0, permitsToTake = 3.0), which will
+ * evaluate the integral of the function from 7.0 to 10.0.
+ *
+ * Using integrals guarantees that the effect of a single acquire(3) is equivalent
+ * to { acquire(1); acquire(1); acquire(1); }, or { acquire(2); acquire(1); }, etc,
+ * since the integral of the function in [7.0, 10.0] is equivalent to the sum of the
+ * integrals of [7.0, 8.0], [8.0, 9.0], [9.0, 10.0] (and so on), no matter
+ * what the function is. This guarantees that we handle correctly requests of varying weight
+ * (permits), /no matter/ what the actual function is - so we can tweak the latter freely.
+ * (The only requirement, obviously, is that we can compute its integrals).
+ *
+ * Note well that if, for this function, we chose a horizontal line, at height of exactly
+ * (1/QPS), then the effect of the function is non-existent: we serve storedPermits at
+ * exactly the same cost as fresh ones (1/QPS is the cost for each). We use this trick later.
+ *
+ * If we pick a function that goes /below/ that horizontal line, it means that we reduce
+ * the area of the function, thus time. Thus, the RateLimiter becomes /faster/ after a
+ * period of underutilization. If, on the other hand, we pick a function that
+ * goes /above/ that horizontal line, then it means that the area (time) is increased,
+ * thus storedPermits are more costly than fresh permits, thus the RateLimiter becomes
+ * /slower/ after a period of underutilization.
+ *
+ * Last, but not least: consider a RateLimiter with rate of 1 permit per second, currently
+ * completely unused, and an expensive acquire(100) request comes. It would be nonsensical
+ * to just wait for 100 seconds, and /then/ start the actual task. Why wait without doing
+ * anything? A much better approach is to /allow/ the request right away (as if it was an
+ * acquire(1) request instead), and postpone /subsequent/ requests as needed. In this version,
+ * we allow starting the task immediately, and postpone by 100 seconds future requests,
+ * thus we allow for work to get done in the meantime instead of waiting idly.
+ *
+ * This has important consequences: it means that the RateLimiter doesn't remember the time
+ * of the _last_ request, but it remembers the (expected) time of the _next_ request. This
+ * also enables us to tell immediately (see tryAcquire(timeout)) whether a particular
+ * timeout is enough to get us to the point of the next scheduling time, since we always
+ * maintain that. And what we mean by "an unused RateLimiter" is also defined by that
+ * notion: when we observe that the "expected arrival time of the next request" is actually
+ * in the past, then the difference (now - past) is the amount of time that the RateLimiter
+ * was formally unused, and it is that amount of time which we translate to storedPermits.
+ * (We increase storedPermits with the amount of permits that would have been produced
+ * in that idle time). So, if rate == 1 permit per second, and arrivals come exactly
+ * one second after the previous, then storedPermits is _never_ increased -- we would only
+ * increase it for arrivals _later_ than the expected one second.
+ */
+
+ /**
+ * Creates a {@code RateLimiter} with the specified stable throughput, given as
+ * "permits per second" (commonly referred to as <i>QPS</i>, queries per second).
+ *
+ * <p>The returned {@code RateLimiter} ensures that on average no more than {@code
+ * permitsPerSecond} are issued during any given second, with sustained requests
+ * being smoothly spread over each second. When the incoming request rate exceeds
+ * {@code permitsPerSecond} the rate limiter will release one permit every {@code
+ * (1.0 / permitsPerSecond)} seconds. When the rate limiter is unused,
+ * bursts of up to {@code permitsPerSecond} permits will be allowed, with subsequent
+ * requests being smoothly limited at the stable rate of {@code permitsPerSecond}.
+ *
+ * @param permitsPerSecond the rate of the returned {@code RateLimiter}, measured in
+ * how many permits become available per second.
+ */
+ public static RateLimiter create(double permitsPerSecond) {
+ return create(SleepingTicker.SYSTEM_TICKER, permitsPerSecond);
+ }
+
+ @VisibleForTesting
+ static RateLimiter create(SleepingTicker ticker, double permitsPerSecond) {
+ RateLimiter rateLimiter = new Bursty(ticker);
+ rateLimiter.setRate(permitsPerSecond);
+ return rateLimiter;
+ }
+
+ /**
+ * Creates a {@code RateLimiter} with the specified stable throughput, given as
+ * "permits per second" (commonly referred to as <i>QPS</i>, queries per second), and a
+ * <i>warmup period</i>, during which the {@code RateLimiter} smoothly ramps up its rate,
+ * until it reaches its maximum rate at the end of the period (as long as there are enough
+ * requests to saturate it). Similarly, if the {@code RateLimiter} is left <i>unused</i> for
+ * a duration of {@code warmupPeriod}, it will gradually return to its "cold" state,
+ * i.e. it will go through the same warming up process as when it was first created.
+ *
+ * <p>The returned {@code RateLimiter} is intended for cases where the resource that actually
+ * fulfils the requests (e.g., a remote server) needs "warmup" time, rather than
+ * being immediately accessed at the stable (maximum) rate.
+ *
+ * <p>The returned {@code RateLimiter} starts in a "cold" state (i.e. the warmup period
+ * will follow), and if it is left unused for long enough, it will return to that state.
+ *
+ * @param permitsPerSecond the rate of the returned {@code RateLimiter}, measured in
+ * how many permits become available per second
+ * @param warmupPeriod the duration of the period where the {@code RateLimiter} ramps up its
+ * rate, before reaching its stable (maximum) rate
+ * @param unit the time unit of the warmupPeriod argument
+ */
+ // TODO(user): add a burst size of 1-second-worth of permits, as in the metronome?
+ public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) {
+ return create(SleepingTicker.SYSTEM_TICKER, permitsPerSecond, warmupPeriod, unit);
+ }
+
+ @VisibleForTesting
+ static RateLimiter create(
+ SleepingTicker ticker, double permitsPerSecond, long warmupPeriod, TimeUnit timeUnit) {
+ RateLimiter rateLimiter = new WarmingUp(ticker, warmupPeriod, timeUnit);
+ rateLimiter.setRate(permitsPerSecond);
+ return rateLimiter;
+ }
+
+ @VisibleForTesting
+ static RateLimiter createBursty(
+ SleepingTicker ticker, double permitsPerSecond, int maxBurstSize) {
+ Bursty rateLimiter = new Bursty(ticker);
+ rateLimiter.setRate(permitsPerSecond);
+ rateLimiter.maxPermits = maxBurstSize;
+ return rateLimiter;
+ }
+
+ /**
+ * The underlying timer; used both to measure elapsed time and sleep as necessary. A separate
+ * object to facilitate testing.
+ */
+ private final SleepingTicker ticker;
+
+ /**
+ * The timestamp when the RateLimiter was created; used to avoid possible overflow/time-wrapping
+ * errors.
+ */
+ private final long offsetNanos;
+
+ /**
+ * The currently stored permits.
+ */
+ double storedPermits;
+
+ /**
+ * The maximum number of stored permits.
+ */
+ double maxPermits;
+
+ /**
+ * The interval between two unit requests, at our stable rate. E.g., a stable rate of 5 permits
+ * per second has a stable interval of 200ms.
+ */
+ double stableIntervalMicros;
+
+ /**
+ * The time when the next request (no matter its size) will be granted. After granting a request,
+ * this is pushed further in the future. Large requests push this further than small requests.
+ */
+ private long nextFreeTicketMicros = 0L; // could be either in the past or future
+
+ private RateLimiter(SleepingTicker ticker) {
+ this.ticker = ticker;
+ this.offsetNanos = ticker.read();
+ }
+
+ /**
+ * Updates the stable rate of this {@code RateLimiter}, that is, the
+ * {@code permitsPerSecond} argument provided in the factory method that
+ * constructed the {@code RateLimiter}. Currently throttled threads will <b>not</b>
+ * be awakened as a result of this invocation, thus they do not observe the new rate;
+ * only subsequent requests will.
+ *
+ * <p>Note though that, since each request repays (by waiting, if necessary) the cost
+ * of the <i>previous</i> request, this means that the very next request
+ * after an invocation to {@code setRate} will not be affected by the new rate;
+ * it will pay the cost of the previous request, which is in terms of the previous rate.
+ *
+ * <p>The behavior of the {@code RateLimiter} is not modified in any other way,
+ * e.g. if the {@code RateLimiter} was configured with a warmup period of 20 seconds,
+ * it still has a warmup period of 20 seconds after this method invocation.
+ *
+ * @param permitsPerSecond the new stable rate of this {@code RateLimiter}.
+ */
+ public final synchronized void setRate(double permitsPerSecond) {
+ Preconditions.checkArgument(permitsPerSecond > 0.0
+ && !Double.isNaN(permitsPerSecond), "rate must be positive");
+ resync(readSafeMicros());
+ double stableIntervalMicros = TimeUnit.SECONDS.toMicros(1L) / permitsPerSecond;
+ this.stableIntervalMicros = stableIntervalMicros;
+ doSetRate(permitsPerSecond, stableIntervalMicros);
+ }
+
+ abstract void doSetRate(double permitsPerSecond, double stableIntervalMicros);
+
+ /**
+ * Returns the stable rate (as {@code permits per seconds}) with which this
+ * {@code RateLimiter} is configured with. The initial value of this is the same as
+ * the {@code permitsPerSecond} argument passed in the factory method that produced
+ * this {@code RateLimiter}, and it is only updated after invocations
+ * to {@linkplain #setRate}.
+ */
+ public final synchronized double getRate() {
+ return TimeUnit.SECONDS.toMicros(1L) / stableIntervalMicros;
+ }
+
+ /**
+ * Acquires a permit from this {@code RateLimiter}, blocking until the request can be granted.
+ *
+ * <p>This method is equivalent to {@code acquire(1)}.
+ */
+ public void acquire() {
+ acquire(1);
+ }
+
+ /**
+ * Acquires the given number of permits from this {@code RateLimiter}, blocking until the
+ * request be granted.
+ *
+ * @param permits the number of permits to acquire
+ */
+ public void acquire(int permits) {
+ checkPermits(permits);
+ long microsToWait;
+ synchronized (this) {
+ microsToWait = reserveNextTicket(permits, readSafeMicros());
+ }
+ ticker.sleepMicrosUninterruptibly(microsToWait);
+ }
+
+ /**
+ * Acquires a permit from this {@code RateLimiter} if it can be obtained
+ * without exceeding the specified {@code timeout}, or returns {@code false}
+ * immediately (without waiting) if the permit would not have been granted
+ * before the timeout expired.
+ *
+ * <p>This method is equivalent to {@code tryAcquire(1, timeout, unit)}.
+ *
+ * @param timeout the maximum time to wait for the permit
+ * @param unit the time unit of the timeout argument
+ * @return {@code true} if the permit was acquired, {@code false} otherwise
+ */
+ public boolean tryAcquire(long timeout, TimeUnit unit) {
+ return tryAcquire(1, timeout, unit);
+ }
+
+ /**
+ * Acquires the given number of permits from this {@code RateLimiter} if it can be obtained
+ * without exceeding the specified {@code timeout}, or returns {@code false}
+ * immediately (without waiting) if the permits would not have been granted
+ * before the timeout expired.
+ *
+ * @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 timeout argument
+ * @return {@code true} if the permits were acquired, {@code false} otherwise
+ */
+ public boolean tryAcquire(int permits, long timeout, TimeUnit unit) {
+ checkPermits(permits);
+ long timeoutMicros = unit.toMicros(timeout);
+ long microsToWait;
+ synchronized (this) {
+ long nowMicros = readSafeMicros();
+ if (nextFreeTicketMicros > nowMicros + timeoutMicros) {
+ return false;
+ } else {
+ microsToWait = reserveNextTicket(permits, nowMicros);
+ }
+ }
+ ticker.sleepMicrosUninterruptibly(microsToWait);
+ return true;
+ }
+
+ private static void checkPermits(int permits) {
+ Preconditions.checkArgument(permits > 0, "Requested permits must be positive");
+ }
+
+ /**
+ * Reserves next ticket and returns the wait time that the caller must wait for.
+ */
+ private long reserveNextTicket(double requiredPermits, long nowMicros) {
+ resync(nowMicros);
+ long microsToNextFreeTicket = nextFreeTicketMicros - nowMicros;
+ double storedPermitsToSpend = Math.min(requiredPermits, this.storedPermits);
+ double freshPermits = requiredPermits - storedPermitsToSpend;
+
+ long waitMicros = storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
+ + (long) (freshPermits * stableIntervalMicros);
+
+ this.nextFreeTicketMicros = nextFreeTicketMicros + waitMicros;
+ this.storedPermits -= storedPermitsToSpend;
+ return microsToNextFreeTicket;
+ }
+
+ /**
+ * Translates a specified portion of our currently stored permits which we want to
+ * spend/acquire, into a throttling time. Conceptually, this evaluates the integral
+ * of the underlying function we use, for the range of
+ * [(storedPermits - permitsToTake), storedPermits].
+ *
+ * This always holds: {@code 0 <= permitsToTake <= storedPermits}
+ */
+ abstract long storedPermitsToWaitTime(double storedPermits, double permitsToTake);
+
+ private void resync(long nowMicros) {
+ // if nextFreeTicket is in the past, resync to now
+ if (nowMicros > nextFreeTicketMicros) {
+ storedPermits = Math.min(maxPermits,
+ storedPermits + (nowMicros - nextFreeTicketMicros) / stableIntervalMicros);
+ nextFreeTicketMicros = nowMicros;
+ }
+ }
+
+ private long readSafeMicros() {
+ return TimeUnit.NANOSECONDS.toMicros(ticker.read() - offsetNanos);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("RateLimiter[stableRate=%3.1fqps]", 1000000.0 / stableIntervalMicros);
+ }
+
+ /**
+ * This implements the following function:
+ *
+ * ^ throttling
+ * |
+ * 3*stable + /
+ * interval | /.
+ * (cold) | / .
+ * | / . <-- "warmup period" is the area of the trapezoid between
+ * 2*stable + / . halfPermits and maxPermits
+ * interval | / .
+ * | / .
+ * | / .
+ * stable +----------/ WARM . }
+ * interval | . UP . } <-- this rectangle (from 0 to maxPermits, and
+ * | . PERIOD. } height == stableInterval) defines the cooldown period,
+ * | . . } and we want cooldownPeriod == warmupPeriod
+ * |---------------------------------> storedPermits
+ * (halfPermits) (maxPermits)
+ *
+ * Before going into the details of this particular function, let's keep in mind the basics:
+ * 1) The state of the RateLimiter (storedPermits) is a vertical line in this figure.
+ * 2) When the RateLimiter is not used, this goes right (up to maxPermits)
+ * 3) When the RateLimiter is used, this goes left (down to zero), since if we have storedPermits,
+ * we serve from those first
+ * 4) When _unused_, we go right at the same speed (rate)! I.e., if our rate is
+ * 2 permits per second, and 3 unused seconds pass, we will always save 6 permits
+ * (no matter what our initial position was), up to maxPermits.
+ * If we invert the rate, we get the "stableInterval" (interval between two requests
+ * in a perfectly spaced out sequence of requests of the given rate). Thus, if you
+ * want to see "how much time it will take to go from X storedPermits to X+K storedPermits?",
+ * the answer is always stableInterval * K. In the same example, for 2 permits per second,
+ * stableInterval is 500ms. Thus to go from X storedPermits to X+6 storedPermits, we
+ * require 6 * 500ms = 3 seconds.
+ *
+ * In short, the time it takes to move to the right (save K permits) is equal to the
+ * rectangle of width == K and height == stableInterval.
+ * 4) When _used_, the time it takes, as explained in the introductory class note, is
+ * equal to the integral of our function, between X permits and X-K permits, assuming
+ * we want to spend K saved permits.
+ *
+ * In summary, the time it takes to move to the left (spend K permits), is equal to the
+ * area of the function of width == K.
+ *
+ * Let's dive into this function now:
+ *
+ * When we have storedPermits <= halfPermits (the left portion of the function), then
+ * we spend them at the exact same rate that
+ * fresh permits would be generated anyway (that rate is 1/stableInterval). We size
+ * this area to be equal to _half_ the specified warmup period. Why we need this?
+ * And why half? We'll explain shortly below (after explaining the second part).
+ *
+ * Stored permits that are beyond halfPermits, are mapped to an ascending line, that goes
+ * from stableInterval to 3 * stableInterval. The average height for that part is
+ * 2 * stableInterval, and is sized appropriately to have an area _equal_ to the
+ * specified warmup period. Thus, by point (4) above, it takes "warmupPeriod" amount of time
+ * to go from maxPermits to halfPermits.
+ *
+ * BUT, by point (3) above, it only takes "warmupPeriod / 2" amount of time to return back
+ * to maxPermits, from halfPermits! (Because the trapezoid has double the area of the rectangle
+ * of height stableInterval and equivalent width). We decided that the "cooldown period"
+ * time should be equivalent to "warmup period", thus a fully saturated RateLimiter
+ * (with zero stored permits, serving only fresh ones) can go to a fully unsaturated
+ * (with storedPermits == maxPermits) in the same amount of time it takes for a fully
+ * unsaturated RateLimiter to return to the stableInterval -- which happens in halfPermits,
+ * since beyond that point, we use a horizontal line of "stableInterval" height, simulating
+ * the regular rate.
+ *
+ * Thus, we have figured all dimensions of this shape, to give all the desired
+ * properties:
+ * - the width is warmupPeriod / stableInterval, to make cooldownPeriod == warmupPeriod
+ * - the slope starts at the middle, and goes from stableInterval to 3*stableInterval so
+ * to have halfPermits being spend in double the usual time (half the rate), while their
+ * respective rate is steadily ramping up
+ */
+ private static class WarmingUp extends RateLimiter {
+
+ final long warmupPeriodMicros;
+ /**
+ * The slope of the line from the stable interval (when permits == 0), to the cold interval
+ * (when permits == maxPermits)
+ */
+ private double slope;
+ private double halfPermits;
+
+ WarmingUp(SleepingTicker ticker, long warmupPeriod, TimeUnit timeUnit) {
+ super(ticker);
+ this.warmupPeriodMicros = timeUnit.toMicros(warmupPeriod);
+ }
+
+ @Override
+ void doSetRate(double permitsPerSecond, double stableIntervalMicros) {
+ double oldMaxPermits = maxPermits;
+ maxPermits = warmupPeriodMicros / stableIntervalMicros;
+ halfPermits = maxPermits / 2.0;
+ // Stable interval is x, cold is 3x, so on average it's 2x. Double the time -> halve the rate
+ double coldIntervalMicros = stableIntervalMicros * 3.0;
+ slope = (coldIntervalMicros - stableIntervalMicros) / halfPermits;
+ if (oldMaxPermits == Double.POSITIVE_INFINITY) {
+ // if we don't special-case this, we would get storedPermits == NaN, below
+ storedPermits = 0.0;
+ } else {
+ storedPermits = (oldMaxPermits == 0.0)
+ ? maxPermits // initial state is cold
+ : storedPermits * maxPermits / oldMaxPermits;
+ }
+ }
+
+ @Override
+ long storedPermitsToWaitTime(double storedPermits, double permitsToTake) {
+ double availablePermitsAboveHalf = storedPermits - halfPermits;
+ long micros = 0;
+ // measuring the integral on the right part of the function (the climbing line)
+ if (availablePermitsAboveHalf > 0.0) {
+ double permitsAboveHalfToTake = Math.min(availablePermitsAboveHalf, permitsToTake);
+ micros = (long) (permitsAboveHalfToTake * (permitsToTime(availablePermitsAboveHalf)
+ + permitsToTime(availablePermitsAboveHalf - permitsAboveHalfToTake)) / 2.0);
+ permitsToTake -= permitsAboveHalfToTake;
+ }
+ // measuring the integral on the left part of the function (the horizontal line)
+ micros += (stableIntervalMicros * permitsToTake);
+ return micros;
+ }
+
+ private double permitsToTime(double permits) {
+ return stableIntervalMicros + permits * slope;
+ }
+ }
+
+ /**
+ * This implements a trivial function, where storedPermits are translated to
+ * zero throttling - thus, a client gets an infinite speedup for permits acquired out
+ * of the storedPermits pool. This is also used for the special case of the "metronome",
+ * where the width of the function is also zero; maxStoredPermits is zero, thus
+ * storedPermits and permitsToTake are always zero as well. Such a RateLimiter can
+ * not save permits when unused, thus all permits it serves are fresh, using the
+ * designated rate.
+ */
+ private static class Bursty extends RateLimiter {
+ Bursty(SleepingTicker ticker) {
+ super(ticker);
+ }
+
+ @Override
+ void doSetRate(double permitsPerSecond, double stableIntervalMicros) {
+ double oldMaxPermits = this.maxPermits;
+ /*
+ * We allow the equivalent work of up to one second to be granted with zero waiting, if the
+ * rate limiter has been unused for as much. This is to avoid potentially producing tiny
+ * wait interval between subsequent requests for sufficiently large rates, which would
+ * unnecessarily overconstrain the thread scheduler.
+ */
+ maxPermits = permitsPerSecond; // one second worth of permits
+ storedPermits = (oldMaxPermits == 0.0)
+ ? 0.0 // initial state
+ : storedPermits * maxPermits / oldMaxPermits;
+ }
+
+ @Override
+ long storedPermitsToWaitTime(double storedPermits, double permitsToTake) {
+ return 0L;
+ }
+ }
+
+ @VisibleForTesting
+ static abstract class SleepingTicker extends Ticker {
+ abstract void sleepMicrosUninterruptibly(long micros);
+
+ static final SleepingTicker SYSTEM_TICKER = new SleepingTicker() {
+ @Override
+ public long read() {
+ return systemTicker().read();
+ }
+
+ @Override
+ public void sleepMicrosUninterruptibly(long micros) {
+ if (micros > 0) {
+ Uninterruptibles.sleepUninterruptibly(micros, TimeUnit.MICROSECONDS);
+ }
+ }
+ };
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/Service.java b/guava/src/com/google/common/util/concurrent/Service.java
new file mode 100644
index 0000000..1c3bed6
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/Service.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2009 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+
+/**
+ * An object with an operational state, plus asynchronous {@link #start()} and {@link #stop()}
+ * lifecycle methods to transition between states. Example services include webservers, RPC servers
+ * and timers.
+ *
+ * <p>The normal lifecycle of a service is:
+ * <ul>
+ * <li>{@linkplain State#NEW NEW} -&gt;
+ * <li>{@linkplain State#STARTING STARTING} -&gt;
+ * <li>{@linkplain State#RUNNING RUNNING} -&gt;
+ * <li>{@linkplain State#STOPPING STOPPING} -&gt;
+ * <li>{@linkplain State#TERMINATED TERMINATED}
+ * </ul>
+ *
+ * <p>There are deviations from this if there are failures or if {@link Service#stop} is called
+ * before the {@link Service} reaches the {@linkplain State#RUNNING RUNNING} state. The set of legal
+ * transitions form a <a href="http://en.wikipedia.org/wiki/Directed_acyclic_graph">DAG</a>,
+ * therefore every method of the listener will be called at most once. N.B. The {@link State#FAILED}
+ * and {@link State#TERMINATED} states are terminal states, once a service enters either of these
+ * states it cannot ever leave them.
+ *
+ * <p>Implementors of this interface are strongly encouraged to extend one of the abstract classes
+ * in this package which implement this interface and make the threading and state management
+ * easier.
+ *
+ * @author Jesse Wilson
+ * @author Luke Sandberg
+ * @since 9.0 (in 1.0 as {@code com.google.common.base.Service})
+ */
+@Beta
+public interface Service {
+ /**
+ * If the service state is {@link State#NEW}, this initiates service startup and returns
+ * immediately. If the service has already been started, this method returns immediately without
+ * taking action. A stopped service may not be restarted.
+ *
+ * @return a future for the startup result, regardless of whether this call initiated startup.
+ * Calling {@link ListenableFuture#get} will block until the service has finished
+ * starting, and returns one of {@link State#RUNNING}, {@link State#STOPPING} or
+ * {@link State#TERMINATED}. If the service fails to start, {@link ListenableFuture#get}
+ * will throw an {@link ExecutionException}, and the service's state will be
+ * {@link State#FAILED}. If it has already finished starting, {@link ListenableFuture#get}
+ * returns immediately. Cancelling this future has no effect on the service.
+ */
+ ListenableFuture<State> start();
+
+ /**
+ * Initiates service startup (if necessary), returning once the service has finished starting.
+ * Unlike calling {@code start().get()}, this method throws no checked exceptions, and it cannot
+ * be {@linkplain Thread#interrupt interrupted}.
+ *
+ * @throws UncheckedExecutionException if startup failed
+ * @return the state of the service when startup finished.
+ */
+ State startAndWait();
+
+ /**
+ * Returns {@code true} if this service is {@linkplain State#RUNNING running}.
+ */
+ boolean isRunning();
+
+ /**
+ * Returns the lifecycle state of the service.
+ */
+ State state();
+
+ /**
+ * If the service is {@linkplain State#STARTING starting} or {@linkplain State#RUNNING running},
+ * this initiates service shutdown and returns immediately. If the service is
+ * {@linkplain State#NEW new}, it is {@linkplain State#TERMINATED terminated} without having been
+ * started nor stopped. If the service has already been stopped, this method returns immediately
+ * without taking action.
+ *
+ * @return a future for the shutdown result, regardless of whether this call initiated shutdown.
+ * Calling {@link ListenableFuture#get} will block until the service has finished shutting
+ * down, and either returns {@link State#TERMINATED} or throws an
+ * {@link ExecutionException}. If it has already finished stopping,
+ * {@link ListenableFuture#get} returns immediately. Cancelling this future has no effect
+ * on the service.
+ */
+ ListenableFuture<State> stop();
+
+ /**
+ * Initiates service shutdown (if necessary), returning once the service has finished stopping. If
+ * this is {@link State#STARTING}, startup will be cancelled. If this is {@link State#NEW}, it is
+ * {@link State#TERMINATED terminated} without having been started nor stopped. Unlike calling
+ * {@code stop().get()}, this method throws no checked exceptions.
+ *
+ * @throws UncheckedExecutionException if the service has failed or fails during shutdown
+ * @return the state of the service when shutdown finished.
+ */
+ State stopAndWait();
+
+ /**
+ * Registers a {@link Listener} to be {@linkplain Executor#execute executed} on the given
+ * executor. The listener will have the corresponding transition method called whenever the
+ * service changes state. The listener will not have previous state changes replayed, so it is
+ * suggested that listeners are added before the service starts.
+ *
+ * <p>There is no guaranteed ordering of execution of listeners, but any listener added through
+ * this method is guaranteed to be called whenever there is a state change.
+ *
+ * <p>Exceptions thrown by a listener will be propagated up to the executor. Any exception thrown
+ * during {@code Executor.execute} (e.g., a {@code RejectedExecutionException} or an exception
+ * thrown by {@linkplain MoreExecutors#sameThreadExecutor inline execution}) will be caught and
+ * logged.
+ *
+ * @param listener the listener to run when the service changes state is complete
+ * @param executor the executor in which the the listeners callback methods will be run. For fast,
+ * lightweight listeners that would be safe to execute in any thread, consider
+ * {@link MoreExecutors#sameThreadExecutor}.
+ * @since 13.0
+ */
+ void addListener(Listener listener, Executor executor);
+
+ /**
+ * The lifecycle states of a service.
+ *
+ * @since 9.0 (in 1.0 as {@code com.google.common.base.Service.State})
+ */
+ @Beta // should come out of Beta when Service does
+ enum State {
+ /**
+ * A service in this state is inactive. It does minimal work and consumes
+ * minimal resources.
+ */
+ NEW,
+
+ /**
+ * A service in this state is transitioning to {@link #RUNNING}.
+ */
+ STARTING,
+
+ /**
+ * A service in this state is operational.
+ */
+ RUNNING,
+
+ /**
+ * A service in this state is transitioning to {@link #TERMINATED}.
+ */
+ STOPPING,
+
+ /**
+ * A service in this state has completed execution normally. It does minimal work and consumes
+ * minimal resources.
+ */
+ TERMINATED,
+
+ /**
+ * A service in this state has encountered a problem and may not be operational. It cannot be
+ * started nor stopped.
+ */
+ FAILED
+ }
+
+ /**
+ * A listener for the various state changes that a {@link Service} goes through in its lifecycle.
+ *
+ * @author Luke Sandberg
+ * @since 13.0
+ */
+ @Beta // should come out of Beta when Service does
+ interface Listener {
+ /**
+ * Called when the service transitions from {@linkplain State#NEW NEW} to
+ * {@linkplain State#STARTING STARTING}. This occurs when {@link Service#start} or
+ * {@link Service#startAndWait} is called the first time.
+ */
+ void starting();
+
+ /**
+ * Called when the service transitions from {@linkplain State#STARTING STARTING} to
+ * {@linkplain State#RUNNING RUNNING}. This occurs when a service has successfully started.
+ */
+ void running();
+
+ /**
+ * Called when the service transitions to the {@linkplain State#STOPPING STOPPING} state. The
+ * only valid values for {@code from} are {@linkplain State#STARTING STARTING} or
+ * {@linkplain State#RUNNING RUNNING}. This occurs when {@link Service#stop} is called.
+ *
+ * @param from The previous state that is being transitioned from.
+ */
+ void stopping(State from);
+
+ /**
+ * Called when the service transitions to the {@linkplain State#TERMINATED TERMINATED} state.
+ * The {@linkplain State#TERMINATED TERMINATED} state is a terminal state in the transition
+ * diagram. Therefore, if this method is called, no other methods will be called on the
+ * {@link Listener}.
+ *
+ * @param from The previous state that is being transitioned from. The only valid values for
+ * this are {@linkplain State#NEW NEW}, {@linkplain State#RUNNING RUNNING} or
+ * {@linkplain State#STOPPING STOPPING}.
+ */
+ void terminated(State from);
+
+ /**
+ * Called when the service transitions to the {@linkplain State#FAILED FAILED} state. The
+ * {@linkplain State#FAILED FAILED} state is a terminal state in the transition diagram.
+ * Therefore, if this method is called, no other methods will be called on the {@link Listener}.
+ *
+ * @param from The previous state that is being transitioned from. Failure can occur in any
+ * state with the exception of {@linkplain State#NEW NEW} or
+ * {@linkplain State#TERMINATED TERMINATED}.
+ * @param failure The exception that caused the failure.
+ */
+ void failed(State from, Throwable failure);
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/SettableFuture.java b/guava/src/com/google/common/util/concurrent/SettableFuture.java
new file mode 100644
index 0000000..23e14f9
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/SettableFuture.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import javax.annotation.Nullable;
+
+/**
+ * A {@link ListenableFuture} whose result may be set by a {@link #set(Object)}
+ * or {@link #setException(Throwable)} call. It may also be cancelled.
+ *
+ * @author Sven Mawson
+ * @since 9.0 (in 1.0 as {@code ValueFuture})
+ */
+public final class SettableFuture<V> extends AbstractFuture<V> {
+
+ /**
+ * Creates a new {@code SettableFuture} in the default state.
+ */
+ public static <V> SettableFuture<V> create() {
+ return new SettableFuture<V>();
+ }
+
+ /**
+ * Explicit private constructor, use the {@link #create} factory method to
+ * create instances of {@code SettableFuture}.
+ */
+ private SettableFuture() {}
+
+ /**
+ * Sets the value of this future. This method will return {@code true} if
+ * the value was successfully set, or {@code false} if the future has already
+ * been set or cancelled.
+ *
+ * @param value the value the future should hold.
+ * @return true if the value was successfully set.
+ */
+ @Override
+ public boolean set(@Nullable V value) {
+ return super.set(value);
+ }
+
+ /**
+ * Sets the future to having failed with the given exception. This exception
+ * will be wrapped in an {@code ExecutionException} and thrown from the {@code
+ * get} methods. This method will return {@code true} if the exception was
+ * successfully set, or {@code false} if the future has already been set or
+ * cancelled.
+ *
+ * @param throwable the exception the future should hold.
+ * @return true if the exception was successfully set.
+ */
+ @Override
+ public boolean setException(Throwable throwable) {
+ return super.setException(throwable);
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/SimpleTimeLimiter.java b/guava/src/com/google/common/util/concurrent/SimpleTimeLimiter.java
new file mode 100644
index 0000000..0f7c3e4
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/SimpleTimeLimiter.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ObjectArrays;
+import com.google.common.collect.Sets;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A TimeLimiter that runs method calls in the background using an
+ * {@link ExecutorService}. If the time limit expires for a given method call,
+ * the thread running the call will be interrupted.
+ *
+ * @author Kevin Bourrillion
+ * @since 1.0
+ */
+@Beta
+public final class SimpleTimeLimiter implements TimeLimiter {
+
+ private final ExecutorService executor;
+
+ /**
+ * Constructs a TimeLimiter instance using the given executor service to
+ * execute proxied method calls.
+ * <p>
+ * <b>Warning:</b> using a bounded executor
+ * may be counterproductive! If the thread pool fills up, any time callers
+ * spend waiting for a thread may count toward their time limit, and in
+ * this case the call may even time out before the target method is ever
+ * invoked.
+ *
+ * @param executor the ExecutorService that will execute the method calls on
+ * the target objects; for example, a {@link
+ * Executors#newCachedThreadPool()}.
+ */
+ public SimpleTimeLimiter(ExecutorService executor) {
+ this.executor = checkNotNull(executor);
+ }
+
+ /**
+ * Constructs a TimeLimiter instance using a {@link
+ * Executors#newCachedThreadPool()} to execute proxied method calls.
+ *
+ * <p><b>Warning:</b> using a bounded executor may be counterproductive! If
+ * the thread pool fills up, any time callers spend waiting for a thread may
+ * count toward their time limit, and in this case the call may even time out
+ * before the target method is ever invoked.
+ */
+ public SimpleTimeLimiter() {
+ this(Executors.newCachedThreadPool());
+ }
+
+ @Override
+ public <T> T newProxy(final T target, Class<T> interfaceType,
+ final long timeoutDuration, final TimeUnit timeoutUnit) {
+ checkNotNull(target);
+ checkNotNull(interfaceType);
+ checkNotNull(timeoutUnit);
+ checkArgument(timeoutDuration > 0, "bad timeout: " + timeoutDuration);
+ checkArgument(interfaceType.isInterface(),
+ "interfaceType must be an interface type");
+
+ final Set<Method> interruptibleMethods
+ = findInterruptibleMethods(interfaceType);
+
+ InvocationHandler handler = new InvocationHandler() {
+ @Override
+ public Object invoke(Object obj, final Method method, final Object[] args)
+ throws Throwable {
+ Callable<Object> callable = new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ try {
+ return method.invoke(target, args);
+ } catch (InvocationTargetException e) {
+ throwCause(e, false);
+ throw new AssertionError("can't get here");
+ }
+ }
+ };
+ return callWithTimeout(callable, timeoutDuration, timeoutUnit,
+ interruptibleMethods.contains(method));
+ }
+ };
+ return newProxy(interfaceType, handler);
+ }
+
+ // TODO: should this actually throw only ExecutionException?
+ @Override
+ public <T> T callWithTimeout(Callable<T> callable, long timeoutDuration,
+ TimeUnit timeoutUnit, boolean amInterruptible) throws Exception {
+ checkNotNull(callable);
+ checkNotNull(timeoutUnit);
+ checkArgument(timeoutDuration > 0, "timeout must be positive: %s",
+ timeoutDuration);
+ Future<T> future = executor.submit(callable);
+ try {
+ if (amInterruptible) {
+ try {
+ return future.get(timeoutDuration, timeoutUnit);
+ } catch (InterruptedException e) {
+ future.cancel(true);
+ throw e;
+ }
+ } else {
+ return Uninterruptibles.getUninterruptibly(future,
+ timeoutDuration, timeoutUnit);
+ }
+ } catch (ExecutionException e) {
+ throw throwCause(e, true);
+ } catch (TimeoutException e) {
+ future.cancel(true);
+ throw new UncheckedTimeoutException(e);
+ }
+ }
+
+ private static Exception throwCause(Exception e, boolean combineStackTraces)
+ throws Exception {
+ Throwable cause = e.getCause();
+ if (cause == null) {
+ throw e;
+ }
+ if (combineStackTraces) {
+ StackTraceElement[] combined = ObjectArrays.concat(cause.getStackTrace(),
+ e.getStackTrace(), StackTraceElement.class);
+ cause.setStackTrace(combined);
+ }
+ if (cause instanceof Exception) {
+ throw (Exception) cause;
+ }
+ if (cause instanceof Error) {
+ throw (Error) cause;
+ }
+ // The cause is a weird kind of Throwable, so throw the outer exception.
+ throw e;
+ }
+
+ private static Set<Method> findInterruptibleMethods(Class<?> interfaceType) {
+ Set<Method> set = Sets.newHashSet();
+ for (Method m : interfaceType.getMethods()) {
+ if (declaresInterruptedEx(m)) {
+ set.add(m);
+ }
+ }
+ return set;
+ }
+
+ private static boolean declaresInterruptedEx(Method method) {
+ for (Class<?> exType : method.getExceptionTypes()) {
+ // debate: == or isAssignableFrom?
+ if (exType == InterruptedException.class) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // TODO: replace with version in common.reflect if and when it's open-sourced
+ private static <T> T newProxy(
+ Class<T> interfaceType, InvocationHandler handler) {
+ Object object = Proxy.newProxyInstance(interfaceType.getClassLoader(),
+ new Class<?>[] { interfaceType }, handler);
+ return interfaceType.cast(object);
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/Striped.java b/guava/src/com/google/common/util/concurrent/Striped.java
new file mode 100644
index 0000000..3c426f0
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/Striped.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Functions;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.MapMaker;
+import com.google.common.math.IntMath;
+import com.google.common.primitives.Ints;
+
+import java.math.RoundingMode;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * A striped {@code Lock/Semaphore/ReadWriteLock}. This offers the underlying lock striping
+ * similar to that of {@code ConcurrentHashMap} in a reusable form, and extends it for
+ * semaphores and read-write locks. Conceptually, lock striping is the technique of dividing a lock
+ * into many <i>stripes</i>, increasing the granularity of a single lock and allowing independent
+ * operations to lock different stripes and proceed concurrently, instead of creating contention
+ * for a single lock.
+ *
+ * <p>The guarantee provided by this class is that equal keys lead to the same lock (or semaphore),
+ * i.e. {@code if (key1.equals(key2))} then {@code striped.get(key1) == striped.get(key2)}
+ * (assuming {@link Object#hashCode()} is correctly implemented for the keys). Note
+ * that if {@code key1} is <strong>not</strong> equal to {@code key2}, it is <strong>not</strong>
+ * guaranteed that {@code striped.get(key1) != striped.get(key2)}; the elements might nevertheless
+ * be mapped to the same lock. The lower the number of stripes, the higher the probability of this
+ * happening.
+ *
+ * <p>There are three flavors of this class: {@code Striped<Lock>}, {@code Striped<Semaphore>},
+ * and {@code Striped<ReadWriteLock>}. For each type, two implementations are offered:
+ * {@linkplain #lock(int) strong} and {@linkplain #lazyWeakLock(int) weak}
+ * {@code Striped<Lock>}, {@linkplain #semaphore(int, int) strong} and {@linkplain
+ * #lazyWeakSemaphore(int, int) weak} {@code Striped<Semaphore>}, and {@linkplain
+ * #readWriteLock(int) strong} and {@linkplain #lazyWeakReadWriteLock(int) weak}
+ * {@code Striped<ReadWriteLock>}. <i>Strong</i> means that all stripes (locks/semaphores) are
+ * initialized eagerly, and are not reclaimed unless {@code Striped} itself is reclaimable.
+ * <i>Weak</i> means that locks/semaphores are created lazily, and they are allowed to be reclaimed
+ * if nobody is holding on to them. This is useful, for example, if one wants to create a {@code
+ * Striped<Lock>} of many locks, but worries that in most cases only a small portion of these
+ * would be in use.
+ *
+ * <p>Prior to this class, one might be tempted to use {@code Map<K, Lock>}, where {@code K}
+ * represents the task. This maximizes concurrency by having each unique key mapped to a unique
+ * lock, but also maximizes memory footprint. On the other extreme, one could use a single lock
+ * for all tasks, which minimizes memory footprint but also minimizes concurrency. Instead of
+ * choosing either of these extremes, {@code Striped} allows the user to trade between required
+ * concurrency and memory footprint. For example, if a set of tasks are CPU-bound, one could easily
+ * create a very compact {@code Striped<Lock>} of {@code availableProcessors() * 4} stripes,
+ * instead of possibly thousands of locks which could be created in a {@code Map<K, Lock>}
+ * structure.
+ *
+ * @author Dimitris Andreou
+ * @since 13.0
+ */
+@Beta
+public abstract class Striped<L> {
+ private Striped() {}
+
+ /**
+ * Returns the stripe that corresponds to the passed key. It is always guaranteed that if
+ * {@code key1.equals(key2)}, then {@code get(key1) == get(key2)}.
+ *
+ * @param key an arbitrary, non-null key
+ * @return the stripe that the passed key corresponds to
+ */
+ public abstract L get(Object key);
+
+ /**
+ * Returns the stripe at the specified index. Valid indexes are 0, inclusively, to
+ * {@code size()}, exclusively.
+ *
+ * @param index the index of the stripe to return; must be in {@code [0...size())}
+ * @return the stripe at the specified index
+ */
+ public abstract L getAt(int index);
+
+ /**
+ * Returns the index to which the given key is mapped, so that getAt(indexFor(key)) == get(key).
+ */
+ abstract int indexFor(Object key);
+
+ /**
+ * Returns the total number of stripes in this instance.
+ */
+ public abstract int size();
+
+ /**
+ * Returns the stripes that correspond to the passed objects, in ascending (as per
+ * {@link #getAt(int)}) order. Thus, threads that use the stripes in the order returned
+ * by this method are guaranteed to not deadlock each other.
+ *
+ * <p>It should be noted that using a {@code Striped<L>} with relatively few stripes, and
+ * {@code bulkGet(keys)} with a relative large number of keys can cause an excessive number
+ * of shared stripes (much like the birthday paradox, where much fewer than anticipated birthdays
+ * are needed for a pair of them to match). Please consider carefully the implications of the
+ * number of stripes, the intended concurrency level, and the typical number of keys used in a
+ * {@code bulkGet(keys)} operation. See <a href="http://www.mathpages.com/home/kmath199.htm">Balls
+ * in Bins model</a> for mathematical formulas that can be used to estimate the probability of
+ * collisions.
+ *
+ * @param keys arbitrary non-null keys
+ * @return the stripes corresponding to the objects (one per each object, derived by delegating
+ * to {@link #get(Object)}; may contain duplicates), in an increasing index order.
+ */
+ public Iterable<L> bulkGet(Iterable<?> keys) {
+ // Initially using the array to store the keys, then reusing it to store the respective L's
+ final Object[] array = Iterables.toArray(keys, Object.class);
+ int[] stripes = new int[array.length];
+ for (int i = 0; i < array.length; i++) {
+ stripes[i] = indexFor(array[i]);
+ }
+ Arrays.sort(stripes);
+ for (int i = 0; i < array.length; i++) {
+ array[i] = getAt(stripes[i]);
+ }
+ /*
+ * Note that the returned Iterable holds references to the returned stripes, to avoid
+ * error-prone code like:
+ *
+ * Striped<Lock> stripedLock = Striped.lazyWeakXXX(...)'
+ * Iterable<Lock> locks = stripedLock.bulkGet(keys);
+ * for (Lock lock : locks) {
+ * lock.lock();
+ * }
+ * operation();
+ * for (Lock lock : locks) {
+ * lock.unlock();
+ * }
+ *
+ * If we only held the int[] stripes, translating it on the fly to L's, the original locks
+ * might be garbage collected after locking them, ending up in a huge mess.
+ */
+ @SuppressWarnings("unchecked") // we carefully replaced all keys with their respective L's
+ List<L> asList = (List<L>) Arrays.asList(array);
+ return Collections.unmodifiableList(asList);
+ }
+
+ // Static factories
+
+ /**
+ * Creates a {@code Striped<Lock>} with eagerly initialized, strongly referenced locks, with the
+ * specified fairness. Every lock is reentrant.
+ *
+ * @param stripes the minimum number of stripes (locks) required
+ * @return a new {@code Striped<Lock>}
+ */
+ public static Striped<Lock> lock(int stripes) {
+ return new CompactStriped<Lock>(stripes, new Supplier<Lock>() {
+ public Lock get() {
+ return new PaddedLock();
+ }
+ });
+ }
+
+ /**
+ * Creates a {@code Striped<Lock>} with lazily initialized, weakly referenced locks, with the
+ * specified fairness. Every lock is reentrant.
+ *
+ * @param stripes the minimum number of stripes (locks) required
+ * @return a new {@code Striped<Lock>}
+ */
+ public static Striped<Lock> lazyWeakLock(int stripes) {
+ return new LazyStriped<Lock>(stripes, new Supplier<Lock>() {
+ public Lock get() {
+ return new ReentrantLock(false);
+ }
+ });
+ }
+
+ /**
+ * Creates a {@code Striped<Semaphore>} with eagerly initialized, strongly referenced semaphores,
+ * with the specified number of permits and fairness.
+ *
+ * @param stripes the minimum number of stripes (semaphores) required
+ * @param permits the number of permits in each semaphore
+ * @return a new {@code Striped<Semaphore>}
+ */
+ public static Striped<Semaphore> semaphore(int stripes, final int permits) {
+ return new CompactStriped<Semaphore>(stripes, new Supplier<Semaphore>() {
+ public Semaphore get() {
+ return new PaddedSemaphore(permits);
+ }
+ });
+ }
+
+ /**
+ * Creates a {@code Striped<Semaphore>} with lazily initialized, weakly referenced semaphores,
+ * with the specified number of permits and fairness.
+ *
+ * @param stripes the minimum number of stripes (semaphores) required
+ * @param permits the number of permits in each semaphore
+ * @return a new {@code Striped<Semaphore>}
+ */
+ public static Striped<Semaphore> lazyWeakSemaphore(int stripes, final int permits) {
+ return new LazyStriped<Semaphore>(stripes, new Supplier<Semaphore>() {
+ public Semaphore get() {
+ return new Semaphore(permits, false);
+ }
+ });
+ }
+
+ /**
+ * Creates a {@code Striped<ReadWriteLock>} with eagerly initialized, strongly referenced
+ * read-write locks, with the specified fairness. Every lock is reentrant.
+ *
+ * @param stripes the minimum number of stripes (locks) required
+ * @return a new {@code Striped<ReadWriteLock>}
+ */
+ public static Striped<ReadWriteLock> readWriteLock(int stripes) {
+ return new CompactStriped<ReadWriteLock>(stripes, READ_WRITE_LOCK_SUPPLIER);
+ }
+
+ /**
+ * Creates a {@code Striped<ReadWriteLock>} with lazily initialized, weakly referenced
+ * read-write locks, with the specified fairness. Every lock is reentrant.
+ *
+ * @param stripes the minimum number of stripes (locks) required
+ * @return a new {@code Striped<ReadWriteLock>}
+ */
+ public static Striped<ReadWriteLock> lazyWeakReadWriteLock(int stripes) {
+ return new LazyStriped<ReadWriteLock>(stripes, READ_WRITE_LOCK_SUPPLIER);
+ }
+
+ // ReentrantReadWriteLock is large enough to make padding probably unnecessary
+ private static final Supplier<ReadWriteLock> READ_WRITE_LOCK_SUPPLIER =
+ new Supplier<ReadWriteLock>() {
+ public ReadWriteLock get() {
+ return new ReentrantReadWriteLock();
+ }
+ };
+
+ private abstract static class PowerOfTwoStriped<L> extends Striped<L> {
+ /** Capacity (power of two) minus one, for fast mod evaluation */
+ final int mask;
+
+ PowerOfTwoStriped(int stripes) {
+ Preconditions.checkArgument(stripes > 0, "Stripes must be positive");
+ this.mask = stripes > Ints.MAX_POWER_OF_TWO ? ALL_SET : ceilToPowerOfTwo(stripes) - 1;
+ }
+
+ @Override final int indexFor(Object key) {
+ int hash = smear(key.hashCode());
+ return hash & mask;
+ }
+
+ @Override public final L get(Object key) {
+ return getAt(indexFor(key));
+ }
+ }
+
+ /**
+ * Implementation of Striped where 2^k stripes are represented as an array of the same length,
+ * eagerly initialized.
+ */
+ private static class CompactStriped<L> extends PowerOfTwoStriped<L> {
+ /** Size is a power of two. */
+ private final Object[] array;
+
+ private CompactStriped(int stripes, Supplier<L> supplier) {
+ super(stripes);
+ Preconditions.checkArgument(stripes <= Ints.MAX_POWER_OF_TWO, "Stripes must be <= 2^30)");
+
+ this.array = new Object[mask + 1];
+ for (int i = 0; i < array.length; i++) {
+ array[i] = supplier.get();
+ }
+ }
+
+ @SuppressWarnings("unchecked") // we only put L's in the array
+ @Override public L getAt(int index) {
+ return (L) array[index];
+ }
+
+ @Override public int size() {
+ return array.length;
+ }
+ }
+
+ /**
+ * Implementation of Striped where up to 2^k stripes can be represented, using a Cache
+ * where the key domain is [0..2^k). To map a user key into a stripe, we take a k-bit slice of the
+ * user key's (smeared) hashCode(). The stripes are lazily initialized and are weakly referenced.
+ */
+ private static class LazyStriped<L> extends PowerOfTwoStriped<L> {
+ final ConcurrentMap<Integer, L> cache;
+ final int size;
+
+ LazyStriped(int stripes, Supplier<L> supplier) {
+ super(stripes);
+ this.size = (mask == ALL_SET) ? Integer.MAX_VALUE : mask + 1;
+ this.cache = new MapMaker().weakValues().makeComputingMap(Functions.forSupplier(supplier));
+ }
+
+ @Override public L getAt(int index) {
+ Preconditions.checkElementIndex(index, size());
+ return cache.get(index);
+ }
+
+ @Override public int size() {
+ return size;
+ }
+ }
+
+ /**
+ * A bit mask were all bits are set.
+ */
+ private static final int ALL_SET = ~0;
+
+ private static int ceilToPowerOfTwo(int x) {
+ return 1 << IntMath.log2(x, RoundingMode.CEILING);
+ }
+
+ /*
+ * This method was 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/licenses/publicdomain
+ *
+ * As of 2010/06/11, this method is identical to the (package private) hash
+ * method in OpenJDK 7's java.util.HashMap class.
+ */
+ // Copied from java/com/google/common/collect/Hashing.java
+ private static int smear(int hashCode) {
+ hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
+ return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4);
+ }
+
+ private static class PaddedLock extends ReentrantLock {
+ /*
+ * Padding from 40 into 64 bytes, same size as cache line. Might be beneficial to add
+ * a fourth long here, to minimize chance of interference between consecutive locks,
+ * but I couldn't observe any benefit from that.
+ */
+ @SuppressWarnings("unused")
+ long q1, q2, q3;
+
+ PaddedLock() {
+ super(false);
+ }
+ }
+
+ private static class PaddedSemaphore extends Semaphore {
+ // See PaddedReentrantLock comment
+ @SuppressWarnings("unused")
+ long q1, q2, q3;
+
+ PaddedSemaphore(int permits) {
+ super(permits, false);
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java b/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java
new file mode 100644
index 0000000..167ad11
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/ThreadFactoryBuilder.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2010 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * A ThreadFactory builder, providing any combination of these features:
+ * <ul>
+ * <li> whether threads should be marked as {@linkplain Thread#setDaemon daemon}
+ * threads
+ * <li> a {@linkplain ThreadFactoryBuilder#setNameFormat naming format}
+ * <li> a {@linkplain Thread#setPriority thread priority}
+ * <li> an {@linkplain Thread#setUncaughtExceptionHandler uncaught exception
+ * handler}
+ * <li> a {@linkplain ThreadFactory#newThread backing thread factory}
+ * </ul>
+ * If no backing thread factory is provided, a default backing thread factory is
+ * used as if by calling {@code setThreadFactory(}{@link
+ * Executors#defaultThreadFactory()}{@code )}.
+ *
+ * @author Kurt Alfred Kluever
+ * @since 4.0
+ */
+public final class ThreadFactoryBuilder {
+ private String nameFormat = null;
+ private Boolean daemon = null;
+ private Integer priority = null;
+ private UncaughtExceptionHandler uncaughtExceptionHandler = null;
+ private ThreadFactory backingThreadFactory = null;
+
+ /**
+ * Creates a new {@link ThreadFactory} builder.
+ */
+ public ThreadFactoryBuilder() {}
+
+ /**
+ * Sets the naming format to use when naming threads ({@link Thread#setName})
+ * which are created with this ThreadFactory.
+ *
+ * @param nameFormat a {@link String#format(String, Object...)}-compatible
+ * format String, to which a unique integer (0, 1, etc.) will be supplied
+ * as the single parameter. This integer will be unique to the built
+ * instance of the ThreadFactory and will be assigned sequentially.
+ * @return this for the builder pattern
+ */
+ public ThreadFactoryBuilder setNameFormat(String nameFormat) {
+ String.format(nameFormat, 0); // fail fast if the format is bad or null
+ this.nameFormat = nameFormat;
+ return this;
+ }
+
+ /**
+ * Sets daemon or not for new threads created with this ThreadFactory.
+ *
+ * @param daemon whether or not new Threads created with this ThreadFactory
+ * will be daemon threads
+ * @return this for the builder pattern
+ */
+ public ThreadFactoryBuilder setDaemon(boolean daemon) {
+ this.daemon = daemon;
+ return this;
+ }
+
+ /**
+ * Sets the priority for new threads created with this ThreadFactory.
+ *
+ * @param priority the priority for new Threads created with this
+ * ThreadFactory
+ * @return this for the builder pattern
+ */
+ public ThreadFactoryBuilder setPriority(int priority) {
+ // Thread#setPriority() already checks for validity. These error messages
+ // are nicer though and will fail-fast.
+ checkArgument(priority >= Thread.MIN_PRIORITY,
+ "Thread priority (%s) must be >= %s", priority, Thread.MIN_PRIORITY);
+ checkArgument(priority <= Thread.MAX_PRIORITY,
+ "Thread priority (%s) must be <= %s", priority, Thread.MAX_PRIORITY);
+ this.priority = priority;
+ return this;
+ }
+
+ /**
+ * Sets the {@link UncaughtExceptionHandler} for new threads created with this
+ * ThreadFactory.
+ *
+ * @param uncaughtExceptionHandler the uncaught exception handler for new
+ * Threads created with this ThreadFactory
+ * @return this for the builder pattern
+ */
+ public ThreadFactoryBuilder setUncaughtExceptionHandler(
+ UncaughtExceptionHandler uncaughtExceptionHandler) {
+ this.uncaughtExceptionHandler = checkNotNull(uncaughtExceptionHandler);
+ return this;
+ }
+
+ /**
+ * Sets the backing {@link ThreadFactory} for new threads created with this
+ * ThreadFactory. Threads will be created by invoking #newThread(Runnable) on
+ * this backing {@link ThreadFactory}.
+ *
+ * @param backingThreadFactory the backing {@link ThreadFactory} which will
+ * be delegated to during thread creation.
+ * @return this for the builder pattern
+ *
+ * @see MoreExecutors
+ */
+ public ThreadFactoryBuilder setThreadFactory(
+ ThreadFactory backingThreadFactory) {
+ this.backingThreadFactory = checkNotNull(backingThreadFactory);
+ return this;
+ }
+
+ /**
+ * Returns a new thread factory using the options supplied during the building
+ * process. After building, it is still possible to change the options used to
+ * build the ThreadFactory and/or build again. State is not shared amongst
+ * built instances.
+ *
+ * @return the fully constructed {@link ThreadFactory}
+ */
+ public ThreadFactory build() {
+ return build(this);
+ }
+
+ private static ThreadFactory build(ThreadFactoryBuilder builder) {
+ final String nameFormat = builder.nameFormat;
+ final Boolean daemon = builder.daemon;
+ final Integer priority = builder.priority;
+ final UncaughtExceptionHandler uncaughtExceptionHandler =
+ builder.uncaughtExceptionHandler;
+ final ThreadFactory backingThreadFactory =
+ (builder.backingThreadFactory != null)
+ ? builder.backingThreadFactory
+ : Executors.defaultThreadFactory();
+ final AtomicLong count = (nameFormat != null) ? new AtomicLong(0) : null;
+ return new ThreadFactory() {
+ @Override public Thread newThread(Runnable runnable) {
+ Thread thread = backingThreadFactory.newThread(runnable);
+ if (nameFormat != null) {
+ thread.setName(String.format(nameFormat, count.getAndIncrement()));
+ }
+ if (daemon != null) {
+ thread.setDaemon(daemon);
+ }
+ if (priority != null) {
+ thread.setPriority(priority);
+ }
+ if (uncaughtExceptionHandler != null) {
+ thread.setUncaughtExceptionHandler(uncaughtExceptionHandler);
+ }
+ return thread;
+ }
+ };
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/TimeLimiter.java b/guava/src/com/google/common/util/concurrent/TimeLimiter.java
new file mode 100644
index 0000000..a9938de
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/TimeLimiter.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Produces proxies that impose a time limit on method
+ * calls to the proxied object. For example, to return the value of
+ * {@code target.someMethod()}, but substitute {@code DEFAULT_VALUE} if this
+ * method call takes over 50 ms, you can use this code:
+ * <pre>
+ * TimeLimiter limiter = . . .;
+ * TargetType proxy = limiter.newProxy(
+ * target, TargetType.class, 50, TimeUnit.MILLISECONDS);
+ * try {
+ * return proxy.someMethod();
+ * } catch (UncheckedTimeoutException e) {
+ * return DEFAULT_VALUE;
+ * }
+ * </pre>
+ * Please see {@code SimpleTimeLimiterTest} for more usage examples.
+ *
+ * @author Kevin Bourrillion
+ * @since 1.0
+ */
+@Beta
+public interface TimeLimiter {
+
+ /**
+ * Returns an instance of {@code interfaceType} that delegates all method
+ * calls to the {@code target} object, enforcing the specified time limit on
+ * each call. This time-limited delegation is also performed for calls to
+ * {@link Object#equals}, {@link Object#hashCode}, and
+ * {@link Object#toString}.
+ * <p>
+ * If the target method call finishes before the limit is reached, the return
+ * value or exception is propagated to the caller exactly as-is. If, on the
+ * other hand, the time limit is reached, the proxy will attempt to abort the
+ * call to the target, and will throw an {@link UncheckedTimeoutException} to
+ * the caller.
+ * <p>
+ * It is important to note that the primary purpose of the proxy object is to
+ * return control to the caller when the timeout elapses; aborting the target
+ * method call is of secondary concern. The particular nature and strength
+ * of the guarantees made by the proxy is implementation-dependent. However,
+ * it is important that each of the methods on the target object behaves
+ * appropriately when its thread is interrupted.
+ *
+ * @param target the object to proxy
+ * @param interfaceType the interface you wish the returned proxy to
+ * implement
+ * @param timeoutDuration with timeoutUnit, the maximum length of time that
+ * callers are willing to wait on each method call to the proxy
+ * @param timeoutUnit with timeoutDuration, the maximum length of time that
+ * callers are willing to wait on each method call to the proxy
+ * @return a time-limiting proxy
+ * @throws IllegalArgumentException if {@code interfaceType} is a regular
+ * class, enum, or annotation type, rather than an interface
+ */
+ <T> T newProxy(T target, Class<T> interfaceType,
+ long timeoutDuration, TimeUnit timeoutUnit);
+
+ /**
+ * Invokes a specified Callable, timing out after the specified time limit.
+ * If the target method call finished before the limit is reached, the return
+ * value or exception is propagated to the caller exactly as-is. If, on the
+ * other hand, the time limit is reached, we attempt to abort the call to the
+ * target, and throw an {@link UncheckedTimeoutException} to the caller.
+ * <p>
+ * <b>Warning:</b> The future of this method is in doubt. It may be nuked, or
+ * changed significantly.
+ *
+ * @param callable the Callable to execute
+ * @param timeoutDuration with timeoutUnit, the maximum length of time to wait
+ * @param timeoutUnit with timeoutDuration, the maximum length of time to wait
+ * @param interruptible whether to respond to thread interruption by aborting
+ * the operation and throwing InterruptedException; if false, the
+ * operation is allowed to complete or time out, and the current thread's
+ * interrupt status is re-asserted.
+ * @return the result returned by the Callable
+ * @throws InterruptedException if {@code interruptible} is true and our
+ * thread is interrupted during execution
+ * @throws UncheckedTimeoutException if the time limit is reached
+ * @throws Exception
+ */
+ <T> T callWithTimeout(Callable<T> callable, long timeoutDuration,
+ TimeUnit timeoutUnit, boolean interruptible) throws Exception;
+}
diff --git a/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java b/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java
new file mode 100644
index 0000000..bdff7db
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/UncaughtExceptionHandlers.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static java.util.logging.Level.SEVERE;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.logging.Logger;
+
+/**
+ * Factories for {@link UncaughtExceptionHandler} instances.
+ *
+ * @author Gregory Kick
+ * @since 8.0
+ */
+public final class UncaughtExceptionHandlers {
+ private UncaughtExceptionHandlers() {}
+
+ /**
+ * Returns an exception handler that exits the system. This is particularly useful for the main
+ * thread, which may start up other, non-daemon threads, but fail to fully initialize the
+ * application successfully.
+ *
+ * <p>Example usage:
+ * <pre>public static void main(String[] args) {
+ * Thread.currentThread().setUncaughtExceptionHandler(UncaughtExceptionHandlers.systemExit());
+ * ...
+ * </pre>
+ */
+ public static UncaughtExceptionHandler systemExit() {
+ return new Exiter(Runtime.getRuntime());
+ }
+
+ @VisibleForTesting static final class Exiter implements UncaughtExceptionHandler {
+ private static final Logger logger = Logger.getLogger(Exiter.class.getName());
+
+ private final Runtime runtime;
+
+ Exiter(Runtime runtime) {
+ this.runtime = runtime;
+ }
+
+ @Override public void uncaughtException(Thread t, Throwable e) {
+ // cannot use FormattingLogger due to a dependency loop
+ logger.log(SEVERE, String.format("Caught an exception in %s. Shutting down.", t), e);
+ runtime.exit(1);
+ }
+ }
+}
diff --git a/guava/src/com/google/common/util/concurrent/UncheckedExecutionException.java b/guava/src/com/google/common/util/concurrent/UncheckedExecutionException.java
new file mode 100644
index 0000000..ad84535
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/UncheckedExecutionException.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * Unchecked variant of {@link java.util.concurrent.ExecutionException}. As with
+ * {@code ExecutionException}, the exception's {@linkplain #getCause() cause}
+ * comes from a failed task, possibly run in another thread.
+ *
+ * <p>{@code UncheckedExecutionException} is intended as an alternative to
+ * {@code ExecutionException} when the exception thrown by a task is an
+ * unchecked exception. However, it may also wrap a checked exception in some
+ * cases.
+ *
+ * <p>When wrapping an {@code Error} from another thread, prefer {@link
+ * ExecutionError}. When wrapping a checked exception, prefer {@code
+ * ExecutionException}.
+ *
+ * @author Charles Fry
+ * @since 10.0
+ */
+@Beta
+@GwtCompatible
+public class UncheckedExecutionException extends RuntimeException {
+ /**
+ * Creates a new instance with {@code null} as its detail message.
+ */
+ protected UncheckedExecutionException() {}
+
+ /**
+ * Creates a new instance with the given detail message.
+ */
+ protected UncheckedExecutionException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new instance with the given detail message and cause.
+ */
+ public UncheckedExecutionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a new instance with the given cause.
+ */
+ public UncheckedExecutionException(Throwable cause) {
+ super(cause);
+ }
+
+ private static final long serialVersionUID = 0;
+}
diff --git a/guava/src/com/google/common/util/concurrent/UncheckedTimeoutException.java b/guava/src/com/google/common/util/concurrent/UncheckedTimeoutException.java
new file mode 100644
index 0000000..d821c84
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/UncheckedTimeoutException.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2006 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+/**
+ * Unchecked version of {@link java.util.concurrent.TimeoutException}.
+ *
+ * @author Kevin Bourrillion
+ * @since 1.0
+ */
+public class UncheckedTimeoutException extends RuntimeException {
+ public UncheckedTimeoutException() {}
+
+ public UncheckedTimeoutException(String message) {
+ super(message);
+ }
+
+ public UncheckedTimeoutException(Throwable cause) {
+ super(cause);
+ }
+
+ public UncheckedTimeoutException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ private static final long serialVersionUID = 0;
+}
diff --git a/guava/src/com/google/common/util/concurrent/Uninterruptibles.java b/guava/src/com/google/common/util/concurrent/Uninterruptibles.java
new file mode 100644
index 0000000..89f30b8
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/Uninterruptibles.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Utilities for treating interruptible operations as uninterruptible.
+ * In all cases, if a thread is interrupted during such a call, the call
+ * continues to block until the result is available or the timeout elapses,
+ * and only then re-interrupts the thread.
+ *
+ * @author Anthony Zana
+ * @since 10.0
+ */
+@Beta
+public final class Uninterruptibles {
+
+ // Implementation Note: As of 3-7-11, the logic for each blocking/timeout
+ // methods is identical, save for method being invoked.
+
+ /**
+ * Invokes {@code latch.}{@link CountDownLatch#await() await()}
+ * uninterruptibly.
+ */
+ public static void awaitUninterruptibly(CountDownLatch latch) {
+ boolean interrupted = false;
+ try {
+ while (true) {
+ try {
+ latch.await();
+ return;
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Invokes
+ * {@code latch.}{@link CountDownLatch#await(long, TimeUnit)
+ * await(timeout, unit)} uninterruptibly.
+ */
+ public static boolean awaitUninterruptibly(CountDownLatch latch,
+ long timeout, TimeUnit unit) {
+ boolean interrupted = false;
+ try {
+ long remainingNanos = unit.toNanos(timeout);
+ long end = System.nanoTime() + remainingNanos;
+
+ while (true) {
+ try {
+ // CountDownLatch treats negative timeouts just like zero.
+ return latch.await(remainingNanos, NANOSECONDS);
+ } catch (InterruptedException e) {
+ interrupted = true;
+ remainingNanos = end - System.nanoTime();
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Invokes {@code toJoin.}{@link Thread#join() join()} uninterruptibly.
+ */
+ public static void joinUninterruptibly(Thread toJoin) {
+ boolean interrupted = false;
+ try {
+ while (true) {
+ try {
+ toJoin.join();
+ return;
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Invokes {@code future.}{@link Future#get() get()} uninterruptibly.
+ * To get uninterruptibility and remove checked exceptions, see
+ * {@link Futures#getUnchecked}.
+ *
+ * <p>If instead, you wish to treat {@link InterruptedException} uniformly
+ * with other exceptions, see {@link Futures#get(Future, Class) Futures.get}
+ * or {@link Futures#makeChecked}.
+ */
+ public static <V> V getUninterruptibly(Future<V> future)
+ throws ExecutionException {
+ boolean interrupted = false;
+ try {
+ while (true) {
+ try {
+ return future.get();
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Invokes
+ * {@code future.}{@link Future#get(long, TimeUnit) get(timeout, unit)}
+ * uninterruptibly.
+ *
+ * <p>If instead, you wish to treat {@link InterruptedException} uniformly
+ * with other exceptions, see {@link Futures#get(Future, Class) Futures.get}
+ * or {@link Futures#makeChecked}.
+ */
+ public static <V> V getUninterruptibly(
+ Future<V> future, long timeout, TimeUnit unit)
+ throws ExecutionException, TimeoutException {
+ boolean interrupted = false;
+ try {
+ long remainingNanos = unit.toNanos(timeout);
+ long end = System.nanoTime() + remainingNanos;
+
+ while (true) {
+ try {
+ // Future treats negative timeouts just like zero.
+ return future.get(remainingNanos, NANOSECONDS);
+ } catch (InterruptedException e) {
+ interrupted = true;
+ remainingNanos = end - System.nanoTime();
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Invokes
+ * {@code unit.}{@link TimeUnit#timedJoin(Thread, long)
+ * timedJoin(toJoin, timeout)} uninterruptibly.
+ */
+ public static void joinUninterruptibly(Thread toJoin,
+ long timeout, TimeUnit unit) {
+ Preconditions.checkNotNull(toJoin);
+ boolean interrupted = false;
+ try {
+ long remainingNanos = unit.toNanos(timeout);
+ long end = System.nanoTime() + remainingNanos;
+ while (true) {
+ try {
+ // TimeUnit.timedJoin() treats negative timeouts just like zero.
+ NANOSECONDS.timedJoin(toJoin, remainingNanos);
+ return;
+ } catch (InterruptedException e) {
+ interrupted = true;
+ remainingNanos = end - System.nanoTime();
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Invokes {@code queue.}{@link BlockingQueue#take() take()} uninterruptibly.
+ */
+ public static <E> E takeUninterruptibly(BlockingQueue<E> queue) {
+ boolean interrupted = false;
+ try {
+ while (true) {
+ try {
+ return queue.take();
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Invokes {@code queue.}{@link BlockingQueue#put(Object) put(element)}
+ * uninterruptibly.
+ */
+ public static <E> void putUninterruptibly(BlockingQueue<E> queue, E element) {
+ boolean interrupted = false;
+ try {
+ while (true) {
+ try {
+ queue.put(element);
+ return;
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ // TODO(user): Support Sleeper somehow (wrapper or interface method)?
+ /**
+ * Invokes {@code unit.}{@link TimeUnit#sleep(long) sleep(sleepFor)}
+ * uninterruptibly.
+ */
+ public static void sleepUninterruptibly(long sleepFor, TimeUnit unit) {
+ boolean interrupted = false;
+ try {
+ long remainingNanos = unit.toNanos(sleepFor);
+ long end = System.nanoTime() + remainingNanos;
+ while (true) {
+ try {
+ // TimeUnit.sleep() treats negative timeouts just like zero.
+ NANOSECONDS.sleep(remainingNanos);
+ return;
+ } catch (InterruptedException e) {
+ interrupted = true;
+ remainingNanos = end - System.nanoTime();
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ // TODO(user): Add support for waitUninterruptibly.
+
+ private Uninterruptibles() {}
+}
diff --git a/guava/src/com/google/common/util/concurrent/package-info.java b/guava/src/com/google/common/util/concurrent/package-info.java
new file mode 100644
index 0000000..6ea5069
--- /dev/null
+++ b/guava/src/com/google/common/util/concurrent/package-info.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Concurrency utilities.
+ *
+ * <p>Commonly used types include {@link
+ * com.google.common.util.concurrent.ListenableFuture} and {@link
+ * com.google.common.util.concurrent.Service}.
+ *
+ * <p>Commonly used utilities include {@link
+ * com.google.common.util.concurrent.Futures}, {@link
+ * com.google.common.util.concurrent.MoreExecutors}, and {@link
+ * com.google.common.util.concurrent.ThreadFactoryBuilder}.
+ *
+ * <p>This package is a part of the open-source
+ * <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
+ */
+@ParametersAreNonnullByDefault
+package com.google.common.util.concurrent;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+