try new-method
This commit is contained in:
parent
78237d9c80
commit
52b4651f1a
3812 changed files with 228702 additions and 223704 deletions
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.util.concurrent.CheckedFuture;
|
||||
import com.google.common.util.concurrent.ForwardingListenableFuture;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Beta
|
||||
public abstract class AbstractCheckedFuture<V, X extends Exception>
|
||||
extends ForwardingListenableFuture.SimpleForwardingListenableFuture<V>
|
||||
implements CheckedFuture<V, X> {
|
||||
protected AbstractCheckedFuture(ListenableFuture<V> delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
protected abstract X mapException(Exception var1);
|
||||
|
||||
@Override
|
||||
public V checkedGet() throws X {
|
||||
try {
|
||||
return this.get();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw this.mapException(e);
|
||||
}
|
||||
catch (CancellationException e) {
|
||||
throw this.mapException(e);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
throw this.mapException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public V checkedGet(long timeout, TimeUnit unit) throws TimeoutException, X {
|
||||
try {
|
||||
return this.get(timeout, unit);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw this.mapException(e);
|
||||
}
|
||||
catch (CancellationException e) {
|
||||
throw this.mapException(e);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
throw this.mapException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.util.concurrent.AbstractService;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.google.common.util.concurrent.Service;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Beta
|
||||
public abstract class AbstractExecutionThreadService
|
||||
implements Service {
|
||||
private static final Logger logger = Logger.getLogger(AbstractExecutionThreadService.class.getName());
|
||||
private final Service delegate = new AbstractService(){
|
||||
|
||||
@Override
|
||||
protected final void doStart() {
|
||||
Executor executor = MoreExecutors.renamingDecorator(AbstractExecutionThreadService.this.executor(), new Supplier<String>(){
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return AbstractExecutionThreadService.this.serviceName();
|
||||
}
|
||||
});
|
||||
executor.execute(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
AbstractExecutionThreadService.this.startUp();
|
||||
this.notifyStarted();
|
||||
if (this.isRunning()) {
|
||||
try {
|
||||
AbstractExecutionThreadService.this.run();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
try {
|
||||
AbstractExecutionThreadService.this.shutDown();
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
logger.log(Level.WARNING, "Error while attempting to shut down the service after failure.", ignored);
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
AbstractExecutionThreadService.this.shutDown();
|
||||
this.notifyStopped();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.notifyFailed(t);
|
||||
throw Throwables.propagate(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
AbstractExecutionThreadService.this.triggerShutdown();
|
||||
}
|
||||
};
|
||||
|
||||
protected AbstractExecutionThreadService() {
|
||||
}
|
||||
|
||||
protected void startUp() throws Exception {
|
||||
}
|
||||
|
||||
protected abstract void run() throws Exception;
|
||||
|
||||
protected void shutDown() throws Exception {
|
||||
}
|
||||
|
||||
protected void triggerShutdown() {
|
||||
}
|
||||
|
||||
protected Executor executor() {
|
||||
return new Executor(){
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
MoreExecutors.newThread(AbstractExecutionThreadService.this.serviceName(), command).start();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String string = String.valueOf(String.valueOf(this.serviceName()));
|
||||
String string2 = String.valueOf(String.valueOf((Object)this.state()));
|
||||
return new StringBuilder(3 + string.length() + string2.length()).append(string).append(" [").append(string2).append("]").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isRunning() {
|
||||
return this.delegate.isRunning();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Service.State state() {
|
||||
return this.delegate.state();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void addListener(Service.Listener listener, Executor executor) {
|
||||
this.delegate.addListener(listener, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Throwable failureCause() {
|
||||
return this.delegate.failureCause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Service startAsync() {
|
||||
this.delegate.startAsync();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Service stopAsync() {
|
||||
this.delegate.stopAsync();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitRunning() {
|
||||
this.delegate.awaitRunning();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
this.delegate.awaitRunning(timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitTerminated() {
|
||||
this.delegate.awaitTerminated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
this.delegate.awaitTerminated(timeout, unit);
|
||||
}
|
||||
|
||||
protected String serviceName() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
}
|
185
src/com/google/common/util/concurrent/AbstractFuture.java
Normal file
185
src/com/google/common/util/concurrent/AbstractFuture.java
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.util.concurrent.ExecutionList;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
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;
|
||||
|
||||
public abstract class AbstractFuture<V>
|
||||
implements ListenableFuture<V> {
|
||||
private final Sync<V> sync = new Sync();
|
||||
private final ExecutionList executionList = new ExecutionList();
|
||||
|
||||
protected AbstractFuture() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException, ExecutionException {
|
||||
return this.sync.get(unit.toNanos(timeout));
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get() throws InterruptedException, ExecutionException {
|
||||
return this.sync.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return this.sync.isDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.sync.isCancelled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
if (!this.sync.cancel(mayInterruptIfRunning)) {
|
||||
return false;
|
||||
}
|
||||
this.executionList.execute();
|
||||
if (mayInterruptIfRunning) {
|
||||
this.interruptTask();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void interruptTask() {
|
||||
}
|
||||
|
||||
protected final boolean wasInterrupted() {
|
||||
return this.sync.wasInterrupted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(Runnable listener, Executor exec) {
|
||||
this.executionList.add(listener, exec);
|
||||
}
|
||||
|
||||
protected boolean set(@Nullable V value) {
|
||||
boolean result = this.sync.set(value);
|
||||
if (result) {
|
||||
this.executionList.execute();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean setException(Throwable throwable) {
|
||||
boolean result = this.sync.setException(Preconditions.checkNotNull(throwable));
|
||||
if (result) {
|
||||
this.executionList.execute();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static final CancellationException cancellationExceptionWithCause(@Nullable String message, @Nullable Throwable cause) {
|
||||
CancellationException exception = new CancellationException(message);
|
||||
exception.initCause(cause);
|
||||
return exception;
|
||||
}
|
||||
|
||||
static final class Sync<V>
|
||||
extends AbstractQueuedSynchronizer {
|
||||
private static final long serialVersionUID = 0L;
|
||||
static final int RUNNING = 0;
|
||||
static final int COMPLETING = 1;
|
||||
static final int COMPLETED = 2;
|
||||
static final int CANCELLED = 4;
|
||||
static final int INTERRUPTED = 8;
|
||||
private V value;
|
||||
private Throwable exception;
|
||||
|
||||
Sync() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int tryAcquireShared(int ignored) {
|
||||
if (this.isDone()) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean tryReleaseShared(int finalState) {
|
||||
this.setState(finalState);
|
||||
return true;
|
||||
}
|
||||
|
||||
V get(long nanos) throws TimeoutException, CancellationException, ExecutionException, InterruptedException {
|
||||
if (!this.tryAcquireSharedNanos(-1, nanos)) {
|
||||
throw new TimeoutException("Timeout waiting for task.");
|
||||
}
|
||||
return this.getValue();
|
||||
}
|
||||
|
||||
V get() throws CancellationException, ExecutionException, InterruptedException {
|
||||
this.acquireSharedInterruptibly(-1);
|
||||
return this.getValue();
|
||||
}
|
||||
|
||||
private V getValue() throws CancellationException, ExecutionException {
|
||||
int state = this.getState();
|
||||
switch (state) {
|
||||
case 2: {
|
||||
if (this.exception != null) {
|
||||
throw new ExecutionException(this.exception);
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
case 4:
|
||||
case 8: {
|
||||
throw AbstractFuture.cancellationExceptionWithCause("Task was cancelled.", this.exception);
|
||||
}
|
||||
}
|
||||
int n = state;
|
||||
throw new IllegalStateException(new StringBuilder(49).append("Error, synchronizer in invalid state: ").append(n).toString());
|
||||
}
|
||||
|
||||
boolean isDone() {
|
||||
return (this.getState() & 0xE) != 0;
|
||||
}
|
||||
|
||||
boolean isCancelled() {
|
||||
return (this.getState() & 0xC) != 0;
|
||||
}
|
||||
|
||||
boolean wasInterrupted() {
|
||||
return this.getState() == 8;
|
||||
}
|
||||
|
||||
boolean set(@Nullable V v) {
|
||||
return this.complete(v, null, 2);
|
||||
}
|
||||
|
||||
boolean setException(Throwable t) {
|
||||
return this.complete(null, t, 2);
|
||||
}
|
||||
|
||||
boolean cancel(boolean interrupt) {
|
||||
return this.complete(null, null, interrupt ? 8 : 4);
|
||||
}
|
||||
|
||||
private boolean complete(@Nullable V v, @Nullable Throwable t, int finalState) {
|
||||
boolean doCompletion = this.compareAndSetState(0, 1);
|
||||
if (doCompletion) {
|
||||
this.value = v;
|
||||
this.exception = (finalState & 0xC) != 0 ? new CancellationException("Future.cancel() was called.") : t;
|
||||
this.releaseShared(finalState);
|
||||
} else if (this.getState() == 1) {
|
||||
this.acquireShared(-1);
|
||||
}
|
||||
return doCompletion;
|
||||
}
|
||||
}
|
||||
}
|
145
src/com/google/common/util/concurrent/AbstractIdleService.java
Normal file
145
src/com/google/common/util/concurrent/AbstractIdleService.java
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.util.concurrent.AbstractService;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.google.common.util.concurrent.Service;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Beta
|
||||
public abstract class AbstractIdleService
|
||||
implements Service {
|
||||
private final Supplier<String> threadNameSupplier = new Supplier<String>(){
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
String string = String.valueOf(String.valueOf(AbstractIdleService.this.serviceName()));
|
||||
String string2 = String.valueOf(String.valueOf((Object)AbstractIdleService.this.state()));
|
||||
return new StringBuilder(1 + string.length() + string2.length()).append(string).append(" ").append(string2).toString();
|
||||
}
|
||||
};
|
||||
private final Service delegate = new AbstractService(){
|
||||
|
||||
@Override
|
||||
protected final void doStart() {
|
||||
MoreExecutors.renamingDecorator(AbstractIdleService.this.executor(), (Supplier<String>)AbstractIdleService.this.threadNameSupplier).execute(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
AbstractIdleService.this.startUp();
|
||||
this.notifyStarted();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.notifyFailed(t);
|
||||
throw Throwables.propagate(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void doStop() {
|
||||
MoreExecutors.renamingDecorator(AbstractIdleService.this.executor(), (Supplier<String>)AbstractIdleService.this.threadNameSupplier).execute(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
AbstractIdleService.this.shutDown();
|
||||
this.notifyStopped();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.notifyFailed(t);
|
||||
throw Throwables.propagate(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
protected AbstractIdleService() {
|
||||
}
|
||||
|
||||
protected abstract void startUp() throws Exception;
|
||||
|
||||
protected abstract void shutDown() throws Exception;
|
||||
|
||||
protected Executor executor() {
|
||||
return new Executor(){
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
MoreExecutors.newThread((String)AbstractIdleService.this.threadNameSupplier.get(), command).start();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String string = String.valueOf(String.valueOf(this.serviceName()));
|
||||
String string2 = String.valueOf(String.valueOf((Object)this.state()));
|
||||
return new StringBuilder(3 + string.length() + string2.length()).append(string).append(" [").append(string2).append("]").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isRunning() {
|
||||
return this.delegate.isRunning();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Service.State state() {
|
||||
return this.delegate.state();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void addListener(Service.Listener listener, Executor executor) {
|
||||
this.delegate.addListener(listener, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Throwable failureCause() {
|
||||
return this.delegate.failureCause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Service startAsync() {
|
||||
this.delegate.startAsync();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Service stopAsync() {
|
||||
this.delegate.stopAsync();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitRunning() {
|
||||
this.delegate.awaitRunning();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
this.delegate.awaitRunning(timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitTerminated() {
|
||||
this.delegate.awaitTerminated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
this.delegate.awaitTerminated(timeout, unit);
|
||||
}
|
||||
|
||||
protected String serviceName() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListenableFutureTask;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import java.util.concurrent.AbstractExecutorService;
|
||||
import java.util.concurrent.Callable;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
public abstract class AbstractListeningExecutorService
|
||||
extends AbstractExecutorService
|
||||
implements ListeningExecutorService {
|
||||
protected final <T> ListenableFutureTask<T> newTaskFor(Runnable runnable, T value) {
|
||||
return ListenableFutureTask.create(runnable, value);
|
||||
}
|
||||
|
||||
protected final <T> ListenableFutureTask<T> newTaskFor(Callable<T> callable) {
|
||||
return ListenableFutureTask.create(callable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<?> submit(Runnable task) {
|
||||
return (ListenableFuture)super.submit(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ListenableFuture<T> submit(Runnable task, @Nullable T result) {
|
||||
return (ListenableFuture)super.submit(task, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ListenableFuture<T> submit(Callable<T> task) {
|
||||
return (ListenableFuture)super.submit(task);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.util.concurrent.AbstractService;
|
||||
import com.google.common.util.concurrent.ForwardingFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.google.common.util.concurrent.Service;
|
||||
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.ThreadFactory;
|
||||
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.concurrent.GuardedBy;
|
||||
|
||||
@Beta
|
||||
public abstract class AbstractScheduledService
|
||||
implements Service {
|
||||
private static final Logger logger = Logger.getLogger(AbstractScheduledService.class.getName());
|
||||
private final AbstractService delegate = new AbstractService(){
|
||||
private volatile Future<?> runningTask;
|
||||
private volatile ScheduledExecutorService executorService;
|
||||
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 {
|
||||
AbstractScheduledService.this.shutDown();
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
logger.log(Level.WARNING, "Error while attempting to shut down the service after failure.", ignored);
|
||||
}
|
||||
this.notifyFailed(t);
|
||||
throw Throwables.propagate(t);
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected final void doStart() {
|
||||
this.executorService = MoreExecutors.renamingDecorator(AbstractScheduledService.this.executor(), new Supplier<String>(){
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
String string = String.valueOf(String.valueOf(AbstractScheduledService.this.serviceName()));
|
||||
String string2 = String.valueOf(String.valueOf((Object)this.state()));
|
||||
return new StringBuilder(1 + string.length() + string2.length()).append(string).append(" ").append(string2).toString();
|
||||
}
|
||||
});
|
||||
this.executorService.execute(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
lock.lock();
|
||||
try {
|
||||
AbstractScheduledService.this.startUp();
|
||||
runningTask = AbstractScheduledService.this.scheduler().schedule(AbstractScheduledService.this.delegate, executorService, task);
|
||||
this.notifyStarted();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.notifyFailed(t);
|
||||
throw Throwables.propagate(t);
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void doStop() {
|
||||
this.runningTask.cancel(false);
|
||||
this.executorService.execute(new Runnable(){
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
lock.lock();
|
||||
try {
|
||||
if (this.state() != Service.State.STOPPING) {
|
||||
return;
|
||||
}
|
||||
AbstractScheduledService.this.shutDown();
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
}
|
||||
this.notifyStopped();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.notifyFailed(t);
|
||||
throw Throwables.propagate(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
protected AbstractScheduledService() {
|
||||
}
|
||||
|
||||
protected abstract void runOneIteration() throws Exception;
|
||||
|
||||
protected void startUp() throws Exception {
|
||||
}
|
||||
|
||||
protected void shutDown() throws Exception {
|
||||
}
|
||||
|
||||
protected abstract Scheduler scheduler();
|
||||
|
||||
protected ScheduledExecutorService executor() {
|
||||
final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory(){
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable runnable) {
|
||||
return MoreExecutors.newThread(AbstractScheduledService.this.serviceName(), runnable);
|
||||
}
|
||||
});
|
||||
this.addListener(new Service.Listener(){
|
||||
|
||||
@Override
|
||||
public void terminated(Service.State from) {
|
||||
executor.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Service.State from, Throwable failure) {
|
||||
executor.shutdown();
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
return executor;
|
||||
}
|
||||
|
||||
protected String serviceName() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String string = String.valueOf(String.valueOf(this.serviceName()));
|
||||
String string2 = String.valueOf(String.valueOf((Object)this.state()));
|
||||
return new StringBuilder(3 + string.length() + string2.length()).append(string).append(" [").append(string2).append("]").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isRunning() {
|
||||
return this.delegate.isRunning();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Service.State state() {
|
||||
return this.delegate.state();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void addListener(Service.Listener listener, Executor executor) {
|
||||
this.delegate.addListener(listener, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Throwable failureCause() {
|
||||
return this.delegate.failureCause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Service startAsync() {
|
||||
this.delegate.startAsync();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Service stopAsync() {
|
||||
this.delegate.stopAsync();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitRunning() {
|
||||
this.delegate.awaitRunning();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
this.delegate.awaitRunning(timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitTerminated() {
|
||||
this.delegate.awaitTerminated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
this.delegate.awaitTerminated(timeout, unit);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static abstract class CustomScheduler
|
||||
extends Scheduler {
|
||||
@Override
|
||||
final Future<?> schedule(AbstractService service, ScheduledExecutorService executor, Runnable runnable) {
|
||||
ReschedulableCallable task = new ReschedulableCallable(service, executor, runnable);
|
||||
task.reschedule();
|
||||
return task;
|
||||
}
|
||||
|
||||
protected abstract Schedule getNextSchedule() throws Exception;
|
||||
|
||||
@Beta
|
||||
protected static final class Schedule {
|
||||
private final long delay;
|
||||
private final TimeUnit unit;
|
||||
|
||||
public Schedule(long delay, TimeUnit unit) {
|
||||
this.delay = delay;
|
||||
this.unit = Preconditions.checkNotNull(unit);
|
||||
}
|
||||
}
|
||||
|
||||
private class ReschedulableCallable
|
||||
extends ForwardingFuture<Void>
|
||||
implements Callable<Void> {
|
||||
private final Runnable wrappedRunnable;
|
||||
private final ScheduledExecutorService executor;
|
||||
private final AbstractService service;
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
@GuardedBy(value="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 {
|
||||
this.wrappedRunnable.run();
|
||||
this.reschedule();
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public void reschedule() {
|
||||
this.lock.lock();
|
||||
try {
|
||||
if (this.currentFuture == null || !this.currentFuture.isCancelled()) {
|
||||
Schedule schedule = CustomScheduler.this.getNextSchedule();
|
||||
this.currentFuture = this.executor.schedule(this, schedule.delay, schedule.unit);
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
this.service.notifyFailed(e);
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
this.lock.lock();
|
||||
try {
|
||||
boolean bl = this.currentFuture.cancel(mayInterruptIfRunning);
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Future<Void> delegate() {
|
||||
throw new UnsupportedOperationException("Only cancel is supported by this future");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class Scheduler {
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
abstract Future<?> schedule(AbstractService var1, ScheduledExecutorService var2, Runnable var3);
|
||||
|
||||
private Scheduler() {
|
||||
}
|
||||
}
|
||||
}
|
479
src/com/google/common/util/concurrent/AbstractService.java
Normal file
479
src/com/google/common/util/concurrent/AbstractService.java
Normal file
|
@ -0,0 +1,479 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.util.concurrent.ListenerCallQueue;
|
||||
import com.google.common.util.concurrent.Monitor;
|
||||
import com.google.common.util.concurrent.Service;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Beta
|
||||
public abstract class AbstractService
|
||||
implements Service {
|
||||
private static final ListenerCallQueue.Callback<Service.Listener> STARTING_CALLBACK = new ListenerCallQueue.Callback<Service.Listener>("starting()"){
|
||||
|
||||
@Override
|
||||
void call(Service.Listener listener) {
|
||||
listener.starting();
|
||||
}
|
||||
};
|
||||
private static final ListenerCallQueue.Callback<Service.Listener> RUNNING_CALLBACK = new ListenerCallQueue.Callback<Service.Listener>("running()"){
|
||||
|
||||
@Override
|
||||
void call(Service.Listener listener) {
|
||||
listener.running();
|
||||
}
|
||||
};
|
||||
private static final ListenerCallQueue.Callback<Service.Listener> STOPPING_FROM_STARTING_CALLBACK = AbstractService.stoppingCallback(Service.State.STARTING);
|
||||
private static final ListenerCallQueue.Callback<Service.Listener> STOPPING_FROM_RUNNING_CALLBACK = AbstractService.stoppingCallback(Service.State.RUNNING);
|
||||
private static final ListenerCallQueue.Callback<Service.Listener> TERMINATED_FROM_NEW_CALLBACK = AbstractService.terminatedCallback(Service.State.NEW);
|
||||
private static final ListenerCallQueue.Callback<Service.Listener> TERMINATED_FROM_RUNNING_CALLBACK = AbstractService.terminatedCallback(Service.State.RUNNING);
|
||||
private static final ListenerCallQueue.Callback<Service.Listener> TERMINATED_FROM_STOPPING_CALLBACK = AbstractService.terminatedCallback(Service.State.STOPPING);
|
||||
private final Monitor monitor = new Monitor();
|
||||
private final Monitor.Guard isStartable = new Monitor.Guard(this.monitor){
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return AbstractService.this.state() == Service.State.NEW;
|
||||
}
|
||||
};
|
||||
private final Monitor.Guard isStoppable = new Monitor.Guard(this.monitor){
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return AbstractService.this.state().compareTo(Service.State.RUNNING) <= 0;
|
||||
}
|
||||
};
|
||||
private final Monitor.Guard hasReachedRunning = new Monitor.Guard(this.monitor){
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return AbstractService.this.state().compareTo(Service.State.RUNNING) >= 0;
|
||||
}
|
||||
};
|
||||
private final Monitor.Guard isStopped = new Monitor.Guard(this.monitor){
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return AbstractService.this.state().isTerminal();
|
||||
}
|
||||
};
|
||||
@GuardedBy(value="monitor")
|
||||
private final List<ListenerCallQueue<Service.Listener>> listeners = Collections.synchronizedList(new ArrayList());
|
||||
@GuardedBy(value="monitor")
|
||||
private volatile StateSnapshot snapshot = new StateSnapshot(Service.State.NEW);
|
||||
|
||||
private static ListenerCallQueue.Callback<Service.Listener> terminatedCallback(final Service.State from) {
|
||||
String string = String.valueOf(String.valueOf((Object)from));
|
||||
return new ListenerCallQueue.Callback<Service.Listener>(new StringBuilder(21 + string.length()).append("terminated({from = ").append(string).append("})").toString()){
|
||||
|
||||
@Override
|
||||
void call(Service.Listener listener) {
|
||||
listener.terminated(from);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static ListenerCallQueue.Callback<Service.Listener> stoppingCallback(final Service.State from) {
|
||||
String string = String.valueOf(String.valueOf((Object)from));
|
||||
return new ListenerCallQueue.Callback<Service.Listener>(new StringBuilder(19 + string.length()).append("stopping({from = ").append(string).append("})").toString()){
|
||||
|
||||
@Override
|
||||
void call(Service.Listener listener) {
|
||||
listener.stopping(from);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected AbstractService() {
|
||||
}
|
||||
|
||||
protected abstract void doStart();
|
||||
|
||||
protected abstract void doStop();
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public final Service startAsync() {
|
||||
if (this.monitor.enterIf(this.isStartable)) {
|
||||
try {
|
||||
this.snapshot = new StateSnapshot(Service.State.STARTING);
|
||||
this.starting();
|
||||
this.doStart();
|
||||
}
|
||||
catch (Throwable startupFailure) {
|
||||
this.notifyFailed(startupFailure);
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
this.executeListeners();
|
||||
}
|
||||
} else {
|
||||
String string = String.valueOf(String.valueOf(this));
|
||||
throw new IllegalStateException(new StringBuilder(33 + string.length()).append("Service ").append(string).append(" has already been started").toString());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
* Enabled force condition propagation
|
||||
* Lifted jumps to return sites
|
||||
*/
|
||||
@Override
|
||||
public final Service stopAsync() {
|
||||
if (!this.monitor.enterIf(this.isStoppable)) return this;
|
||||
try {
|
||||
Service.State previous = this.state();
|
||||
switch (previous) {
|
||||
case NEW: {
|
||||
this.snapshot = new StateSnapshot(Service.State.TERMINATED);
|
||||
this.terminated(Service.State.NEW);
|
||||
return this;
|
||||
}
|
||||
case STARTING: {
|
||||
this.snapshot = new StateSnapshot(Service.State.STARTING, true, null);
|
||||
this.stopping(Service.State.STARTING);
|
||||
return this;
|
||||
}
|
||||
case RUNNING: {
|
||||
this.snapshot = new StateSnapshot(Service.State.STOPPING);
|
||||
this.stopping(Service.State.RUNNING);
|
||||
this.doStop();
|
||||
return this;
|
||||
}
|
||||
case STOPPING:
|
||||
case TERMINATED:
|
||||
case FAILED: {
|
||||
String string = String.valueOf(String.valueOf((Object)previous));
|
||||
throw new AssertionError((Object)new StringBuilder(45 + string.length()).append("isStoppable is incorrectly implemented, saw: ").append(string).toString());
|
||||
}
|
||||
default: {
|
||||
String string = String.valueOf(String.valueOf((Object)previous));
|
||||
throw new AssertionError((Object)new StringBuilder(18 + string.length()).append("Unexpected state: ").append(string).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable shutdownFailure) {
|
||||
this.notifyFailed(shutdownFailure);
|
||||
return this;
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
this.executeListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public final void awaitRunning() {
|
||||
this.monitor.enterWhenUninterruptibly(this.hasReachedRunning);
|
||||
try {
|
||||
this.checkCurrentState(Service.State.RUNNING);
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
if (this.monitor.enterWhenUninterruptibly(this.hasReachedRunning, timeout, unit)) {
|
||||
try {
|
||||
this.checkCurrentState(Service.State.RUNNING);
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
} else {
|
||||
String string = String.valueOf(String.valueOf(this));
|
||||
String string2 = String.valueOf(String.valueOf((Object)this.state()));
|
||||
throw new TimeoutException(new StringBuilder(66 + string.length() + string2.length()).append("Timed out waiting for ").append(string).append(" to reach the RUNNING state. ").append("Current state: ").append(string2).toString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public final void awaitTerminated() {
|
||||
this.monitor.enterWhenUninterruptibly(this.isStopped);
|
||||
try {
|
||||
this.checkCurrentState(Service.State.TERMINATED);
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
if (this.monitor.enterWhenUninterruptibly(this.isStopped, timeout, unit)) {
|
||||
try {
|
||||
this.checkCurrentState(Service.State.TERMINATED);
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
} else {
|
||||
String string = String.valueOf(String.valueOf(this));
|
||||
String string2 = String.valueOf(String.valueOf((Object)this.state()));
|
||||
throw new TimeoutException(new StringBuilder(65 + string.length() + string2.length()).append("Timed out waiting for ").append(string).append(" to reach a terminal state. ").append("Current state: ").append(string2).toString());
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="monitor")
|
||||
private void checkCurrentState(Service.State expected) {
|
||||
Service.State actual = this.state();
|
||||
if (actual != expected) {
|
||||
if (actual == Service.State.FAILED) {
|
||||
String string = String.valueOf(String.valueOf((Object)expected));
|
||||
throw new IllegalStateException(new StringBuilder(55 + string.length()).append("Expected the service to be ").append(string).append(", but the service has FAILED").toString(), this.failureCause());
|
||||
}
|
||||
String string = String.valueOf(String.valueOf((Object)expected));
|
||||
String string2 = String.valueOf(String.valueOf((Object)actual));
|
||||
throw new IllegalStateException(new StringBuilder(37 + string.length() + string2.length()).append("Expected the service to be ").append(string).append(", but was ").append(string2).toString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
protected final void notifyStarted() {
|
||||
this.monitor.enter();
|
||||
try {
|
||||
if (this.snapshot.state != Service.State.STARTING) {
|
||||
String string = String.valueOf(String.valueOf((Object)this.snapshot.state));
|
||||
IllegalStateException failure = new IllegalStateException(new StringBuilder(43 + string.length()).append("Cannot notifyStarted() when the service is ").append(string).toString());
|
||||
this.notifyFailed(failure);
|
||||
throw failure;
|
||||
}
|
||||
if (this.snapshot.shutdownWhenStartupFinishes) {
|
||||
this.snapshot = new StateSnapshot(Service.State.STOPPING);
|
||||
this.doStop();
|
||||
} else {
|
||||
this.snapshot = new StateSnapshot(Service.State.RUNNING);
|
||||
this.running();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
this.executeListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
protected final void notifyStopped() {
|
||||
this.monitor.enter();
|
||||
try {
|
||||
Service.State previous = this.snapshot.state;
|
||||
if (previous != Service.State.STOPPING && previous != Service.State.RUNNING) {
|
||||
String string = String.valueOf(String.valueOf((Object)previous));
|
||||
IllegalStateException failure = new IllegalStateException(new StringBuilder(43 + string.length()).append("Cannot notifyStopped() when the service is ").append(string).toString());
|
||||
this.notifyFailed(failure);
|
||||
throw failure;
|
||||
}
|
||||
this.snapshot = new StateSnapshot(Service.State.TERMINATED);
|
||||
this.terminated(previous);
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
this.executeListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
* Enabled force condition propagation
|
||||
* Lifted jumps to return sites
|
||||
*/
|
||||
protected final void notifyFailed(Throwable cause) {
|
||||
Preconditions.checkNotNull(cause);
|
||||
this.monitor.enter();
|
||||
try {
|
||||
Service.State previous = this.state();
|
||||
switch (previous) {
|
||||
case NEW:
|
||||
case TERMINATED: {
|
||||
String string = String.valueOf(String.valueOf((Object)previous));
|
||||
throw new IllegalStateException(new StringBuilder(22 + string.length()).append("Failed while in state:").append(string).toString(), cause);
|
||||
}
|
||||
case STARTING:
|
||||
case RUNNING:
|
||||
case STOPPING: {
|
||||
this.snapshot = new StateSnapshot(Service.State.FAILED, false, cause);
|
||||
this.failed(previous, cause);
|
||||
return;
|
||||
}
|
||||
case FAILED: {
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
String string = String.valueOf(String.valueOf((Object)previous));
|
||||
throw new AssertionError((Object)new StringBuilder(18 + string.length()).append("Unexpected state: ").append(string).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
this.executeListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isRunning() {
|
||||
return this.state() == Service.State.RUNNING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Service.State state() {
|
||||
return this.snapshot.externalState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Throwable failureCause() {
|
||||
return this.snapshot.failureCause();
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public final void addListener(Service.Listener listener, Executor executor) {
|
||||
Preconditions.checkNotNull(listener, "listener");
|
||||
Preconditions.checkNotNull(executor, "executor");
|
||||
this.monitor.enter();
|
||||
try {
|
||||
if (!this.state().isTerminal()) {
|
||||
this.listeners.add(new ListenerCallQueue<Service.Listener>(listener, executor));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String string = String.valueOf(String.valueOf(this.getClass().getSimpleName()));
|
||||
String string2 = String.valueOf(String.valueOf((Object)this.state()));
|
||||
return new StringBuilder(3 + string.length() + string2.length()).append(string).append(" [").append(string2).append("]").toString();
|
||||
}
|
||||
|
||||
private void executeListeners() {
|
||||
if (!this.monitor.isOccupiedByCurrentThread()) {
|
||||
for (int i = 0; i < this.listeners.size(); ++i) {
|
||||
this.listeners.get(i).execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="monitor")
|
||||
private void starting() {
|
||||
STARTING_CALLBACK.enqueueOn(this.listeners);
|
||||
}
|
||||
|
||||
@GuardedBy(value="monitor")
|
||||
private void running() {
|
||||
RUNNING_CALLBACK.enqueueOn(this.listeners);
|
||||
}
|
||||
|
||||
@GuardedBy(value="monitor")
|
||||
private void stopping(Service.State from) {
|
||||
if (from == Service.State.STARTING) {
|
||||
STOPPING_FROM_STARTING_CALLBACK.enqueueOn(this.listeners);
|
||||
} else if (from == Service.State.RUNNING) {
|
||||
STOPPING_FROM_RUNNING_CALLBACK.enqueueOn(this.listeners);
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="monitor")
|
||||
private void terminated(Service.State from) {
|
||||
switch (from) {
|
||||
case NEW: {
|
||||
TERMINATED_FROM_NEW_CALLBACK.enqueueOn(this.listeners);
|
||||
break;
|
||||
}
|
||||
case RUNNING: {
|
||||
TERMINATED_FROM_RUNNING_CALLBACK.enqueueOn(this.listeners);
|
||||
break;
|
||||
}
|
||||
case STOPPING: {
|
||||
TERMINATED_FROM_STOPPING_CALLBACK.enqueueOn(this.listeners);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="monitor")
|
||||
private void failed(final Service.State from, final Throwable cause) {
|
||||
String string = String.valueOf(String.valueOf((Object)from));
|
||||
String string2 = String.valueOf(String.valueOf(cause));
|
||||
new ListenerCallQueue.Callback<Service.Listener>(new StringBuilder(27 + string.length() + string2.length()).append("failed({from = ").append(string).append(", cause = ").append(string2).append("})").toString()){
|
||||
|
||||
@Override
|
||||
void call(Service.Listener listener) {
|
||||
listener.failed(from, cause);
|
||||
}
|
||||
}.enqueueOn(this.listeners);
|
||||
}
|
||||
|
||||
@Immutable
|
||||
private static final class StateSnapshot {
|
||||
final Service.State state;
|
||||
final boolean shutdownWhenStartupFinishes;
|
||||
@Nullable
|
||||
final Throwable failure;
|
||||
|
||||
StateSnapshot(Service.State internalState) {
|
||||
this(internalState, false, null);
|
||||
}
|
||||
|
||||
StateSnapshot(Service.State internalState, boolean shutdownWhenStartupFinishes, @Nullable Throwable failure) {
|
||||
Preconditions.checkArgument(!shutdownWhenStartupFinishes || internalState == Service.State.STARTING, "shudownWhenStartupFinishes can only be set if state is STARTING. Got %s instead.", new Object[]{internalState});
|
||||
Preconditions.checkArgument(!(failure != null ^ internalState == Service.State.FAILED), "A failure cause should be set if and only if the state is failed. Got %s and %s instead.", new Object[]{internalState, failure});
|
||||
this.state = internalState;
|
||||
this.shutdownWhenStartupFinishes = shutdownWhenStartupFinishes;
|
||||
this.failure = failure;
|
||||
}
|
||||
|
||||
Service.State externalState() {
|
||||
if (this.shutdownWhenStartupFinishes && this.state == Service.State.STARTING) {
|
||||
return Service.State.STOPPING;
|
||||
}
|
||||
return this.state;
|
||||
}
|
||||
|
||||
Throwable failureCause() {
|
||||
Preconditions.checkState(this.state == Service.State.FAILED, "failureCause() is only valid if the service has failed, service is %s", new Object[]{this.state});
|
||||
return this.failure;
|
||||
}
|
||||
}
|
||||
}
|
10
src/com/google/common/util/concurrent/AsyncFunction.java
Normal file
10
src/com/google/common/util/concurrent/AsyncFunction.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
public interface AsyncFunction<I, O> {
|
||||
public ListenableFuture<O> apply(I var1) throws Exception;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.util.concurrent.AbstractFuture;
|
||||
import com.google.common.util.concurrent.ForwardingListenableFuture;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
final class AsyncSettableFuture<V>
|
||||
extends ForwardingListenableFuture<V> {
|
||||
private final NestedFuture<V> nested = new NestedFuture();
|
||||
private final ListenableFuture<V> dereferenced = Futures.dereference(this.nested);
|
||||
|
||||
public static <V> AsyncSettableFuture<V> create() {
|
||||
return new AsyncSettableFuture<V>();
|
||||
}
|
||||
|
||||
private AsyncSettableFuture() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListenableFuture<V> delegate() {
|
||||
return this.dereferenced;
|
||||
}
|
||||
|
||||
public boolean setFuture(ListenableFuture<? extends V> future) {
|
||||
return this.nested.setFuture(Preconditions.checkNotNull(future));
|
||||
}
|
||||
|
||||
public boolean setValue(@Nullable V value) {
|
||||
return this.setFuture(Futures.immediateFuture(value));
|
||||
}
|
||||
|
||||
public boolean setException(Throwable exception) {
|
||||
return this.setFuture(Futures.immediateFailedFuture(exception));
|
||||
}
|
||||
|
||||
public boolean isSet() {
|
||||
return this.nested.isDone();
|
||||
}
|
||||
|
||||
private static final class NestedFuture<V>
|
||||
extends AbstractFuture<ListenableFuture<? extends V>> {
|
||||
private NestedFuture() {
|
||||
}
|
||||
|
||||
boolean setFuture(ListenableFuture<? extends V> value) {
|
||||
boolean result = this.set(value);
|
||||
if (this.isCancelled()) {
|
||||
value.cancel(this.wasInterrupted());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
105
src/com/google/common/util/concurrent/AtomicDouble.java
Normal file
105
src/com/google/common/util/concurrent/AtomicDouble.java
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
|
||||
public class AtomicDouble
|
||||
extends Number
|
||||
implements Serializable {
|
||||
private static final long serialVersionUID = 0L;
|
||||
private volatile transient long value;
|
||||
private static final AtomicLongFieldUpdater<AtomicDouble> updater = AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value");
|
||||
|
||||
public AtomicDouble(double initialValue) {
|
||||
this.value = Double.doubleToRawLongBits(initialValue);
|
||||
}
|
||||
|
||||
public AtomicDouble() {
|
||||
}
|
||||
|
||||
public final double get() {
|
||||
return Double.longBitsToDouble(this.value);
|
||||
}
|
||||
|
||||
public final void set(double newValue) {
|
||||
long next;
|
||||
this.value = next = Double.doubleToRawLongBits(newValue);
|
||||
}
|
||||
|
||||
public final void lazySet(double newValue) {
|
||||
this.set(newValue);
|
||||
}
|
||||
|
||||
public final double getAndSet(double newValue) {
|
||||
long next = Double.doubleToRawLongBits(newValue);
|
||||
return Double.longBitsToDouble(updater.getAndSet(this, next));
|
||||
}
|
||||
|
||||
public final boolean compareAndSet(double expect, double update) {
|
||||
return updater.compareAndSet(this, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update));
|
||||
}
|
||||
|
||||
public final boolean weakCompareAndSet(double expect, double update) {
|
||||
return updater.weakCompareAndSet(this, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update));
|
||||
}
|
||||
|
||||
public final double getAndAdd(double delta) {
|
||||
double currentVal;
|
||||
double nextVal;
|
||||
long next;
|
||||
long current;
|
||||
while (!updater.compareAndSet(this, current = this.value, next = Double.doubleToRawLongBits(nextVal = (currentVal = Double.longBitsToDouble(current)) + delta))) {
|
||||
}
|
||||
return currentVal;
|
||||
}
|
||||
|
||||
public final double addAndGet(double delta) {
|
||||
double currentVal;
|
||||
double nextVal;
|
||||
long next;
|
||||
long current;
|
||||
while (!updater.compareAndSet(this, current = this.value, next = Double.doubleToRawLongBits(nextVal = (currentVal = Double.longBitsToDouble(current)) + delta))) {
|
||||
}
|
||||
return nextVal;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Double.toString(this.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue() {
|
||||
return (int)this.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long longValue() {
|
||||
return (long)this.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float floatValue() {
|
||||
return (float)this.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double doubleValue() {
|
||||
return this.get();
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream s) throws IOException {
|
||||
s.defaultWriteObject();
|
||||
s.writeDouble(this.get());
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
|
||||
s.defaultReadObject();
|
||||
this.set(s.readDouble());
|
||||
}
|
||||
}
|
115
src/com/google/common/util/concurrent/AtomicDoubleArray.java
Normal file
115
src/com/google/common/util/concurrent/AtomicDoubleArray.java
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.atomic.AtomicLongArray;
|
||||
|
||||
public class AtomicDoubleArray
|
||||
implements Serializable {
|
||||
private static final long serialVersionUID = 0L;
|
||||
private transient AtomicLongArray longs;
|
||||
|
||||
public AtomicDoubleArray(int length) {
|
||||
this.longs = new AtomicLongArray(length);
|
||||
}
|
||||
|
||||
public AtomicDoubleArray(double[] array) {
|
||||
int len = array.length;
|
||||
long[] longArray = new long[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
longArray[i] = Double.doubleToRawLongBits(array[i]);
|
||||
}
|
||||
this.longs = new AtomicLongArray(longArray);
|
||||
}
|
||||
|
||||
public final int length() {
|
||||
return this.longs.length();
|
||||
}
|
||||
|
||||
public final double get(int i) {
|
||||
return Double.longBitsToDouble(this.longs.get(i));
|
||||
}
|
||||
|
||||
public final void set(int i, double newValue) {
|
||||
long next = Double.doubleToRawLongBits(newValue);
|
||||
this.longs.set(i, next);
|
||||
}
|
||||
|
||||
public final void lazySet(int i, double newValue) {
|
||||
this.set(i, newValue);
|
||||
}
|
||||
|
||||
public final double getAndSet(int i, double newValue) {
|
||||
long next = Double.doubleToRawLongBits(newValue);
|
||||
return Double.longBitsToDouble(this.longs.getAndSet(i, next));
|
||||
}
|
||||
|
||||
public final boolean compareAndSet(int i, double expect, double update) {
|
||||
return this.longs.compareAndSet(i, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update));
|
||||
}
|
||||
|
||||
public final boolean weakCompareAndSet(int i, double expect, double update) {
|
||||
return this.longs.weakCompareAndSet(i, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update));
|
||||
}
|
||||
|
||||
public final double getAndAdd(int i, double delta) {
|
||||
double currentVal;
|
||||
double nextVal;
|
||||
long next;
|
||||
long current;
|
||||
while (!this.longs.compareAndSet(i, current = this.longs.get(i), next = Double.doubleToRawLongBits(nextVal = (currentVal = Double.longBitsToDouble(current)) + delta))) {
|
||||
}
|
||||
return currentVal;
|
||||
}
|
||||
|
||||
public double addAndGet(int i, double delta) {
|
||||
double currentVal;
|
||||
double nextVal;
|
||||
long next;
|
||||
long current;
|
||||
while (!this.longs.compareAndSet(i, current = this.longs.get(i), next = Double.doubleToRawLongBits(nextVal = (currentVal = Double.longBitsToDouble(current)) + delta))) {
|
||||
}
|
||||
return nextVal;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
int iMax = this.length() - 1;
|
||||
if (iMax == -1) {
|
||||
return "[]";
|
||||
}
|
||||
StringBuilder b = new StringBuilder(19 * (iMax + 1));
|
||||
b.append('[');
|
||||
int i = 0;
|
||||
while (true) {
|
||||
b.append(Double.longBitsToDouble(this.longs.get(i)));
|
||||
if (i == iMax) {
|
||||
return b.append(']').toString();
|
||||
}
|
||||
b.append(',').append(' ');
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream s) throws IOException {
|
||||
s.defaultWriteObject();
|
||||
int length = this.length();
|
||||
s.writeInt(length);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
s.writeDouble(this.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
|
||||
s.defaultReadObject();
|
||||
int length = s.readInt();
|
||||
this.longs = new AtomicLongArray(length);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
this.set(i, s.readDouble());
|
||||
}
|
||||
}
|
||||
}
|
216
src/com/google/common/util/concurrent/AtomicLongMap.java
Normal file
216
src/com/google/common/util/concurrent/AtomicLongMap.java
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Preconditions;
|
||||
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;
|
||||
|
||||
@GwtCompatible
|
||||
public final class AtomicLongMap<K> {
|
||||
private final ConcurrentHashMap<K, AtomicLong> map;
|
||||
private transient Map<K, Long> asMap;
|
||||
|
||||
private AtomicLongMap(ConcurrentHashMap<K, AtomicLong> map) {
|
||||
this.map = Preconditions.checkNotNull(map);
|
||||
}
|
||||
|
||||
public static <K> AtomicLongMap<K> create() {
|
||||
return new AtomicLongMap(new ConcurrentHashMap());
|
||||
}
|
||||
|
||||
public static <K> AtomicLongMap<K> create(Map<? extends K, ? extends Long> m) {
|
||||
AtomicLongMap<? extends K> result = AtomicLongMap.create();
|
||||
result.putAll(m);
|
||||
return result;
|
||||
}
|
||||
|
||||
public long get(K key) {
|
||||
AtomicLong atomic = this.map.get(key);
|
||||
return atomic == null ? 0L : atomic.get();
|
||||
}
|
||||
|
||||
public long incrementAndGet(K key) {
|
||||
return this.addAndGet(key, 1L);
|
||||
}
|
||||
|
||||
public long decrementAndGet(K key) {
|
||||
return this.addAndGet(key, -1L);
|
||||
}
|
||||
|
||||
public long addAndGet(K key, long delta) {
|
||||
long newValue;
|
||||
block0: while (true) {
|
||||
long oldValue;
|
||||
AtomicLong atomic;
|
||||
if ((atomic = this.map.get(key)) == null && (atomic = this.map.putIfAbsent(key, new AtomicLong(delta))) == null) {
|
||||
return delta;
|
||||
}
|
||||
do {
|
||||
if ((oldValue = atomic.get()) != 0L) continue;
|
||||
if (!this.map.replace(key, atomic, new AtomicLong(delta))) continue block0;
|
||||
return delta;
|
||||
} while (!atomic.compareAndSet(oldValue, newValue = oldValue + delta));
|
||||
break;
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
|
||||
public long getAndIncrement(K key) {
|
||||
return this.getAndAdd(key, 1L);
|
||||
}
|
||||
|
||||
public long getAndDecrement(K key) {
|
||||
return this.getAndAdd(key, -1L);
|
||||
}
|
||||
|
||||
public long getAndAdd(K key, long delta) {
|
||||
long oldValue;
|
||||
block0: while (true) {
|
||||
long newValue;
|
||||
AtomicLong atomic;
|
||||
if ((atomic = this.map.get(key)) == null && (atomic = this.map.putIfAbsent(key, new AtomicLong(delta))) == null) {
|
||||
return 0L;
|
||||
}
|
||||
do {
|
||||
if ((oldValue = atomic.get()) != 0L) continue;
|
||||
if (!this.map.replace(key, atomic, new AtomicLong(delta))) continue block0;
|
||||
return 0L;
|
||||
} while (!atomic.compareAndSet(oldValue, newValue = oldValue + delta));
|
||||
break;
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public long put(K key, long newValue) {
|
||||
long oldValue;
|
||||
block0: while (true) {
|
||||
AtomicLong atomic;
|
||||
if ((atomic = this.map.get(key)) == null && (atomic = this.map.putIfAbsent(key, new AtomicLong(newValue))) == null) {
|
||||
return 0L;
|
||||
}
|
||||
do {
|
||||
if ((oldValue = atomic.get()) != 0L) continue;
|
||||
if (!this.map.replace(key, atomic, new AtomicLong(newValue))) continue block0;
|
||||
return 0L;
|
||||
} while (!atomic.compareAndSet(oldValue, newValue));
|
||||
break;
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends Long> m) {
|
||||
for (Map.Entry<K, Long> entry : m.entrySet()) {
|
||||
this.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public long remove(K key) {
|
||||
long oldValue;
|
||||
AtomicLong atomic = this.map.get(key);
|
||||
if (atomic == null) {
|
||||
return 0L;
|
||||
}
|
||||
while ((oldValue = atomic.get()) != 0L && !atomic.compareAndSet(oldValue, 0L)) {
|
||||
}
|
||||
this.map.remove(key, atomic);
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public void removeAllZeros() {
|
||||
for (Object key : this.map.keySet()) {
|
||||
AtomicLong atomic = this.map.get(key);
|
||||
if (atomic == null || atomic.get() != 0L) continue;
|
||||
this.map.remove(key, atomic);
|
||||
}
|
||||
}
|
||||
|
||||
public long sum() {
|
||||
long sum = 0L;
|
||||
for (AtomicLong value : this.map.values()) {
|
||||
sum += value.get();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public Map<K, Long> asMap() {
|
||||
Map<K, Long> result = this.asMap;
|
||||
return result == null ? (this.asMap = this.createAsMap()) : result;
|
||||
}
|
||||
|
||||
private Map<K, Long> createAsMap() {
|
||||
return Collections.unmodifiableMap(Maps.transformValues(this.map, new Function<AtomicLong, Long>(){
|
||||
|
||||
@Override
|
||||
public Long apply(AtomicLong atomic) {
|
||||
return atomic.get();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return this.map.containsKey(key);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.map.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.map.isEmpty();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.map.clear();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.map.toString();
|
||||
}
|
||||
|
||||
long putIfAbsent(K key, long newValue) {
|
||||
long oldValue;
|
||||
block2: {
|
||||
AtomicLong atomic;
|
||||
do {
|
||||
if ((atomic = this.map.get(key)) == null && (atomic = this.map.putIfAbsent(key, new AtomicLong(newValue))) == null) {
|
||||
return 0L;
|
||||
}
|
||||
oldValue = atomic.get();
|
||||
if (oldValue != 0L) break block2;
|
||||
} while (!this.map.replace(key, atomic, new AtomicLong(newValue)));
|
||||
return 0L;
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
boolean replace(K key, long expectedOldValue, long newValue) {
|
||||
if (expectedOldValue == 0L) {
|
||||
return this.putIfAbsent(key, newValue) == 0L;
|
||||
}
|
||||
AtomicLong atomic = this.map.get(key);
|
||||
return atomic == null ? false : atomic.compareAndSet(expectedOldValue, newValue);
|
||||
}
|
||||
|
||||
boolean remove(K key, long value) {
|
||||
AtomicLong atomic = this.map.get(key);
|
||||
if (atomic == null) {
|
||||
return false;
|
||||
}
|
||||
long oldValue = atomic.get();
|
||||
if (oldValue != value) {
|
||||
return false;
|
||||
}
|
||||
if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {
|
||||
this.map.remove(key, atomic);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
29
src/com/google/common/util/concurrent/Atomics.java
Normal file
29
src/com/google/common/util/concurrent/Atomics.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class Atomics {
|
||||
private Atomics() {
|
||||
}
|
||||
|
||||
public static <V> AtomicReference<V> newReference() {
|
||||
return new AtomicReference();
|
||||
}
|
||||
|
||||
public static <V> AtomicReference<V> newReference(@Nullable V initialValue) {
|
||||
return new AtomicReference<V>(initialValue);
|
||||
}
|
||||
|
||||
public static <E> AtomicReferenceArray<E> newReferenceArray(int length) {
|
||||
return new AtomicReferenceArray(length);
|
||||
}
|
||||
|
||||
public static <E> AtomicReferenceArray<E> newReferenceArray(E[] array) {
|
||||
return new AtomicReferenceArray<E>(array);
|
||||
}
|
||||
}
|
85
src/com/google/common/util/concurrent/Callables.java
Normal file
85
src/com/google/common/util/concurrent/Callables.java
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Supplier;
|
||||
import java.util.concurrent.Callable;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class Callables {
|
||||
private Callables() {
|
||||
}
|
||||
|
||||
public static <T> Callable<T> returning(final @Nullable T value) {
|
||||
return new Callable<T>(){
|
||||
|
||||
@Override
|
||||
public T call() {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static <T> Callable<T> threadRenaming(final Callable<T> callable, final Supplier<String> nameSupplier) {
|
||||
Preconditions.checkNotNull(nameSupplier);
|
||||
Preconditions.checkNotNull(callable);
|
||||
return new Callable<T>(){
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public T call() throws Exception {
|
||||
Thread currentThread = Thread.currentThread();
|
||||
String oldName = currentThread.getName();
|
||||
boolean restoreName = Callables.trySetName((String)nameSupplier.get(), currentThread);
|
||||
try {
|
||||
Object v = callable.call();
|
||||
return v;
|
||||
}
|
||||
finally {
|
||||
if (restoreName) {
|
||||
Callables.trySetName(oldName, currentThread);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Runnable threadRenaming(final Runnable task, final Supplier<String> nameSupplier) {
|
||||
Preconditions.checkNotNull(nameSupplier);
|
||||
Preconditions.checkNotNull(task);
|
||||
return new Runnable(){
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
Thread currentThread = Thread.currentThread();
|
||||
String oldName = currentThread.getName();
|
||||
boolean restoreName = Callables.trySetName((String)nameSupplier.get(), currentThread);
|
||||
try {
|
||||
task.run();
|
||||
}
|
||||
finally {
|
||||
if (restoreName) {
|
||||
Callables.trySetName(oldName, currentThread);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean trySetName(String threadName, Thread currentThread) {
|
||||
try {
|
||||
currentThread.setName(threadName);
|
||||
return true;
|
||||
}
|
||||
catch (SecurityException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
17
src/com/google/common/util/concurrent/CheckedFuture.java
Normal file
17
src/com/google/common/util/concurrent/CheckedFuture.java
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Beta
|
||||
public interface CheckedFuture<V, X extends Exception>
|
||||
extends ListenableFuture<V> {
|
||||
public V checkedGet() throws X;
|
||||
|
||||
public V checkedGet(long var1, TimeUnit var3) throws TimeoutException, X;
|
||||
}
|
|
@ -0,0 +1,603 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.MoreObjects;
|
||||
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.ConcurrentMap;
|
||||
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;
|
||||
|
||||
@Beta
|
||||
@ThreadSafe
|
||||
public class CycleDetectingLockFactory {
|
||||
private static final ConcurrentMap<Class<? extends Enum>, Map<? extends Enum, LockGraphNode>> lockGraphNodesPerType = new MapMaker().weakKeys().makeMap();
|
||||
private static final Logger logger = Logger.getLogger(CycleDetectingLockFactory.class.getName());
|
||||
final Policy policy;
|
||||
private static final ThreadLocal<ArrayList<LockGraphNode>> acquiredLocks = new ThreadLocal<ArrayList<LockGraphNode>>(){
|
||||
|
||||
@Override
|
||||
protected ArrayList<LockGraphNode> initialValue() {
|
||||
return Lists.newArrayListWithCapacity(3);
|
||||
}
|
||||
};
|
||||
|
||||
public static CycleDetectingLockFactory newInstance(Policy policy) {
|
||||
return new CycleDetectingLockFactory(policy);
|
||||
}
|
||||
|
||||
public ReentrantLock newReentrantLock(String lockName) {
|
||||
return this.newReentrantLock(lockName, false);
|
||||
}
|
||||
|
||||
public ReentrantLock newReentrantLock(String lockName, boolean fair) {
|
||||
return this.policy == Policies.DISABLED ? new ReentrantLock(fair) : new CycleDetectingReentrantLock(new LockGraphNode(lockName), fair);
|
||||
}
|
||||
|
||||
public ReentrantReadWriteLock newReentrantReadWriteLock(String lockName) {
|
||||
return this.newReentrantReadWriteLock(lockName, false);
|
||||
}
|
||||
|
||||
public ReentrantReadWriteLock newReentrantReadWriteLock(String lockName, boolean fair) {
|
||||
return this.policy == Policies.DISABLED ? new ReentrantReadWriteLock(fair) : new CycleDetectingReentrantReadWriteLock(new LockGraphNode(lockName), fair);
|
||||
}
|
||||
|
||||
public static <E extends Enum<E>> WithExplicitOrdering<E> newInstanceWithExplicitOrdering(Class<E> enumClass, Policy policy) {
|
||||
Preconditions.checkNotNull(enumClass);
|
||||
Preconditions.checkNotNull(policy);
|
||||
Map<? extends Enum, LockGraphNode> lockGraphNodes = CycleDetectingLockFactory.getOrCreateNodes(enumClass);
|
||||
return new WithExplicitOrdering<Enum>(policy, lockGraphNodes);
|
||||
}
|
||||
|
||||
private static Map<? extends Enum, LockGraphNode> getOrCreateNodes(Class<? extends Enum> clazz) {
|
||||
Map<? extends Enum, LockGraphNode> existing = (Map<? extends Enum, LockGraphNode>)lockGraphNodesPerType.get(clazz);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
Map<? extends Enum, LockGraphNode> created = CycleDetectingLockFactory.createNodes(clazz);
|
||||
existing = lockGraphNodesPerType.putIfAbsent(clazz, created);
|
||||
return MoreObjects.firstNonNull(existing, created);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static <E extends Enum<E>> Map<E, LockGraphNode> createNodes(Class<E> clazz) {
|
||||
int i;
|
||||
EnumMap<E, LockGraphNode> map = Maps.newEnumMap(clazz);
|
||||
Enum[] keys = (Enum[])clazz.getEnumConstants();
|
||||
int numKeys = keys.length;
|
||||
ArrayList<LockGraphNode> nodes = Lists.newArrayListWithCapacity(numKeys);
|
||||
for (Enum key : keys) {
|
||||
LockGraphNode node = new LockGraphNode(CycleDetectingLockFactory.getLockName(key));
|
||||
nodes.add(node);
|
||||
map.put(key, node);
|
||||
}
|
||||
for (i = 1; i < numKeys; ++i) {
|
||||
((LockGraphNode)nodes.get(i)).checkAcquiredLocks(Policies.THROW, nodes.subList(0, i));
|
||||
}
|
||||
for (i = 0; i < numKeys - 1; ++i) {
|
||||
((LockGraphNode)nodes.get(i)).checkAcquiredLocks(Policies.DISABLED, nodes.subList(i + 1, numKeys));
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
private static String getLockName(Enum<?> rank) {
|
||||
String string = String.valueOf(String.valueOf(rank.getDeclaringClass().getSimpleName()));
|
||||
String string2 = String.valueOf(String.valueOf(rank.name()));
|
||||
return new StringBuilder(1 + string.length() + string2.length()).append(string).append(".").append(string2).toString();
|
||||
}
|
||||
|
||||
private CycleDetectingLockFactory(Policy policy) {
|
||||
this.policy = Preconditions.checkNotNull(policy);
|
||||
}
|
||||
|
||||
private void aboutToAcquire(CycleDetectingLock lock) {
|
||||
if (!lock.isAcquiredByCurrentThread()) {
|
||||
ArrayList<LockGraphNode> acquiredLockList = acquiredLocks.get();
|
||||
LockGraphNode node = lock.getLockGraphNode();
|
||||
node.checkAcquiredLocks(this.policy, acquiredLockList);
|
||||
acquiredLockList.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void lockStateChanged(CycleDetectingLock lock) {
|
||||
if (!lock.isAcquiredByCurrentThread()) {
|
||||
ArrayList<LockGraphNode> acquiredLockList = acquiredLocks.get();
|
||||
LockGraphNode node = lock.getLockGraphNode();
|
||||
for (int i = acquiredLockList.size() - 1; i >= 0; --i) {
|
||||
if (acquiredLockList.get(i) != node) continue;
|
||||
acquiredLockList.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class CycleDetectingReentrantWriteLock
|
||||
extends ReentrantReadWriteLock.WriteLock {
|
||||
final CycleDetectingReentrantReadWriteLock readWriteLock;
|
||||
|
||||
CycleDetectingReentrantWriteLock(CycleDetectingReentrantReadWriteLock readWriteLock) {
|
||||
super(readWriteLock);
|
||||
this.readWriteLock = readWriteLock;
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void lock() {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock);
|
||||
try {
|
||||
super.lock();
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void lockInterruptibly() throws InterruptedException {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock);
|
||||
try {
|
||||
super.lockInterruptibly();
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock);
|
||||
try {
|
||||
boolean bl = super.tryLock();
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock);
|
||||
try {
|
||||
boolean bl = super.tryLock(timeout, unit);
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void unlock() {
|
||||
try {
|
||||
super.unlock();
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class CycleDetectingReentrantReadLock
|
||||
extends ReentrantReadWriteLock.ReadLock {
|
||||
final CycleDetectingReentrantReadWriteLock readWriteLock;
|
||||
|
||||
CycleDetectingReentrantReadLock(CycleDetectingReentrantReadWriteLock readWriteLock) {
|
||||
super(readWriteLock);
|
||||
this.readWriteLock = readWriteLock;
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void lock() {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock);
|
||||
try {
|
||||
super.lock();
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void lockInterruptibly() throws InterruptedException {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock);
|
||||
try {
|
||||
super.lockInterruptibly();
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock);
|
||||
try {
|
||||
boolean bl = super.tryLock();
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this.readWriteLock);
|
||||
try {
|
||||
boolean bl = super.tryLock(timeout, unit);
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void unlock() {
|
||||
try {
|
||||
super.unlock();
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this.readWriteLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class CycleDetectingReentrantReadWriteLock
|
||||
extends ReentrantReadWriteLock
|
||||
implements CycleDetectingLock {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReentrantReadWriteLock.ReadLock readLock() {
|
||||
return this.readLock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReentrantReadWriteLock.WriteLock writeLock() {
|
||||
return this.writeLock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockGraphNode getLockGraphNode() {
|
||||
return this.lockGraphNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAcquiredByCurrentThread() {
|
||||
return this.isWriteLockedByCurrentThread() || this.getReadHoldCount() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
final class CycleDetectingReentrantLock
|
||||
extends ReentrantLock
|
||||
implements CycleDetectingLock {
|
||||
private final LockGraphNode lockGraphNode;
|
||||
|
||||
private CycleDetectingReentrantLock(LockGraphNode lockGraphNode, boolean fair) {
|
||||
super(fair);
|
||||
this.lockGraphNode = Preconditions.checkNotNull(lockGraphNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockGraphNode getLockGraphNode() {
|
||||
return this.lockGraphNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAcquiredByCurrentThread() {
|
||||
return this.isHeldByCurrentThread();
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void lock() {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this);
|
||||
try {
|
||||
super.lock();
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void lockInterruptibly() throws InterruptedException {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this);
|
||||
try {
|
||||
super.lockInterruptibly();
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this);
|
||||
try {
|
||||
boolean bl = super.tryLock();
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
CycleDetectingLockFactory.this.aboutToAcquire(this);
|
||||
try {
|
||||
boolean bl = super.tryLock(timeout, unit);
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void unlock() {
|
||||
try {
|
||||
super.unlock();
|
||||
}
|
||||
finally {
|
||||
CycleDetectingLockFactory.this.lockStateChanged(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class LockGraphNode {
|
||||
final Map<LockGraphNode, ExampleStackTrace> allowedPriorLocks = new MapMaker().weakKeys().makeMap();
|
||||
final Map<LockGraphNode, PotentialDeadlockException> disallowedPriorLocks = new MapMaker().weakKeys().makeMap();
|
||||
final String lockName;
|
||||
|
||||
LockGraphNode(String lockName) {
|
||||
this.lockName = Preconditions.checkNotNull(lockName);
|
||||
}
|
||||
|
||||
String getLockName() {
|
||||
return this.lockName;
|
||||
}
|
||||
|
||||
void checkAcquiredLocks(Policy policy, List<LockGraphNode> acquiredLocks) {
|
||||
int size = acquiredLocks.size();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
this.checkAcquiredLock(policy, acquiredLocks.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
void checkAcquiredLock(Policy policy, LockGraphNode acquiredLock) {
|
||||
String string = String.valueOf(acquiredLock.getLockName());
|
||||
Preconditions.checkState(this != acquiredLock, string.length() != 0 ? "Attempted to acquire multiple locks with the same rank ".concat(string) : new String("Attempted to acquire multiple locks with the same rank "));
|
||||
if (this.allowedPriorLocks.containsKey(acquiredLock)) {
|
||||
return;
|
||||
}
|
||||
PotentialDeadlockException previousDeadlockException = this.disallowedPriorLocks.get(acquiredLock);
|
||||
if (previousDeadlockException != null) {
|
||||
PotentialDeadlockException exception = new PotentialDeadlockException(acquiredLock, this, previousDeadlockException.getConflictingStackTrace());
|
||||
policy.handlePotentialDeadlock(exception);
|
||||
return;
|
||||
}
|
||||
Set<LockGraphNode> seen = Sets.newIdentityHashSet();
|
||||
ExampleStackTrace path = acquiredLock.findPathTo(this, seen);
|
||||
if (path == null) {
|
||||
this.allowedPriorLocks.put(acquiredLock, new ExampleStackTrace(acquiredLock, this));
|
||||
} else {
|
||||
PotentialDeadlockException exception = new PotentialDeadlockException(acquiredLock, this, path);
|
||||
this.disallowedPriorLocks.put(acquiredLock, exception);
|
||||
policy.handlePotentialDeadlock(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ExampleStackTrace findPathTo(LockGraphNode node, Set<LockGraphNode> seen) {
|
||||
if (!seen.add(this)) {
|
||||
return null;
|
||||
}
|
||||
ExampleStackTrace found = this.allowedPriorLocks.get(node);
|
||||
if (found != null) {
|
||||
return found;
|
||||
}
|
||||
for (Map.Entry<LockGraphNode, ExampleStackTrace> entry : this.allowedPriorLocks.entrySet()) {
|
||||
LockGraphNode preAcquiredLock = entry.getKey();
|
||||
found = preAcquiredLock.findPathTo(node, seen);
|
||||
if (found == null) continue;
|
||||
ExampleStackTrace path = new ExampleStackTrace(preAcquiredLock, this);
|
||||
path.setStackTrace(entry.getValue().getStackTrace());
|
||||
path.initCause(found);
|
||||
return path;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static interface CycleDetectingLock {
|
||||
public LockGraphNode getLockGraphNode();
|
||||
|
||||
public boolean isAcquiredByCurrentThread();
|
||||
}
|
||||
|
||||
@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;
|
||||
this.initCause(conflictingStackTrace);
|
||||
}
|
||||
|
||||
public ExampleStackTrace getConflictingStackTrace() {
|
||||
return this.conflictingStackTrace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
StringBuilder message = new StringBuilder(super.getMessage());
|
||||
for (Throwable t = this.conflictingStackTrace; t != null; t = t.getCause()) {
|
||||
message.append(", ").append(t.getMessage());
|
||||
}
|
||||
return message.toString();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
String string = String.valueOf(String.valueOf(node1.getLockName()));
|
||||
String string2 = String.valueOf(String.valueOf(node2.getLockName()));
|
||||
super(new StringBuilder(4 + string.length() + string2.length()).append(string).append(" -> ").append(string2).toString());
|
||||
StackTraceElement[] origStackTrace = this.getStackTrace();
|
||||
int n = origStackTrace.length;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (WithExplicitOrdering.class.getName().equals(origStackTrace[i].getClassName())) {
|
||||
this.setStackTrace(EMPTY_STACK_TRACE);
|
||||
break;
|
||||
}
|
||||
if (EXCLUDED_CLASS_NAMES.contains(origStackTrace[i].getClassName())) continue;
|
||||
this.setStackTrace(Arrays.copyOfRange(origStackTrace, i, n));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
public ReentrantLock newReentrantLock(E rank) {
|
||||
return this.newReentrantLock(rank, false);
|
||||
}
|
||||
|
||||
public ReentrantLock newReentrantLock(E rank, boolean fair) {
|
||||
return this.policy == Policies.DISABLED ? new ReentrantLock(fair) : new CycleDetectingReentrantLock(this.lockGraphNodes.get(rank), fair);
|
||||
}
|
||||
|
||||
public ReentrantReadWriteLock newReentrantReadWriteLock(E rank) {
|
||||
return this.newReentrantReadWriteLock(rank, false);
|
||||
}
|
||||
|
||||
public ReentrantReadWriteLock newReentrantReadWriteLock(E rank, boolean fair) {
|
||||
return this.policy == Policies.DISABLED ? new ReentrantReadWriteLock(fair) : new CycleDetectingReentrantReadWriteLock(this.lockGraphNodes.get(rank), fair);
|
||||
}
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static enum Policies implements Policy
|
||||
{
|
||||
THROW{
|
||||
|
||||
@Override
|
||||
public void handlePotentialDeadlock(PotentialDeadlockException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
,
|
||||
WARN{
|
||||
|
||||
@Override
|
||||
public void handlePotentialDeadlock(PotentialDeadlockException e) {
|
||||
logger.log(Level.SEVERE, "Detected potential deadlock", e);
|
||||
}
|
||||
}
|
||||
,
|
||||
DISABLED{
|
||||
|
||||
@Override
|
||||
public void handlePotentialDeadlock(PotentialDeadlockException e) {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@Beta
|
||||
@ThreadSafe
|
||||
public static interface Policy {
|
||||
public void handlePotentialDeadlock(PotentialDeadlockException var1);
|
||||
}
|
||||
}
|
28
src/com/google/common/util/concurrent/ExecutionError.java
Normal file
28
src/com/google/common/util/concurrent/ExecutionError.java
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public class ExecutionError
|
||||
extends Error {
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
protected ExecutionError() {
|
||||
}
|
||||
|
||||
protected ExecutionError(@Nullable String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ExecutionError(@Nullable String message, @Nullable Error cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ExecutionError(@Nullable Error cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
88
src/com/google/common/util/concurrent/ExecutionList.java
Normal file
88
src/com/google/common/util/concurrent/ExecutionList.java
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
|
||||
public final class ExecutionList {
|
||||
@VisibleForTesting
|
||||
static final Logger log = Logger.getLogger(ExecutionList.class.getName());
|
||||
@GuardedBy(value="this")
|
||||
private RunnableExecutorPair runnables;
|
||||
@GuardedBy(value="this")
|
||||
private boolean executed;
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public void add(Runnable runnable, Executor executor) {
|
||||
Preconditions.checkNotNull(runnable, "Runnable was null.");
|
||||
Preconditions.checkNotNull(executor, "Executor was null.");
|
||||
ExecutionList executionList = this;
|
||||
synchronized (executionList) {
|
||||
if (!this.executed) {
|
||||
this.runnables = new RunnableExecutorPair(runnable, executor, this.runnables);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ExecutionList.executeListener(runnable, executor);
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public void execute() {
|
||||
RunnableExecutorPair list;
|
||||
ExecutionList executionList = this;
|
||||
synchronized (executionList) {
|
||||
if (this.executed) {
|
||||
return;
|
||||
}
|
||||
this.executed = true;
|
||||
list = this.runnables;
|
||||
this.runnables = null;
|
||||
}
|
||||
RunnableExecutorPair reversedList = null;
|
||||
while (list != null) {
|
||||
RunnableExecutorPair tmp = list;
|
||||
list = list.next;
|
||||
tmp.next = reversedList;
|
||||
reversedList = tmp;
|
||||
}
|
||||
while (reversedList != null) {
|
||||
ExecutionList.executeListener(reversedList.runnable, reversedList.executor);
|
||||
reversedList = reversedList.next;
|
||||
}
|
||||
}
|
||||
|
||||
private static void executeListener(Runnable runnable, Executor executor) {
|
||||
try {
|
||||
executor.execute(runnable);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
String string = String.valueOf(String.valueOf(runnable));
|
||||
String string2 = String.valueOf(String.valueOf(executor));
|
||||
log.log(Level.SEVERE, new StringBuilder(57 + string.length() + string2.length()).append("RuntimeException while executing runnable ").append(string).append(" with executor ").append(string2).toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class RunnableExecutorPair {
|
||||
final Runnable runnable;
|
||||
final Executor executor;
|
||||
@Nullable
|
||||
RunnableExecutorPair next;
|
||||
|
||||
RunnableExecutorPair(Runnable runnable, Executor executor, RunnableExecutorPair next) {
|
||||
this.runnable = runnable;
|
||||
this.executor = executor;
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
}
|
28
src/com/google/common/util/concurrent/FakeTimeLimiter.java
Normal file
28
src/com/google/common/util/concurrent/FakeTimeLimiter.java
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.util.concurrent.TimeLimiter;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Beta
|
||||
public final class FakeTimeLimiter
|
||||
implements TimeLimiter {
|
||||
@Override
|
||||
public <T> T newProxy(T target, Class<T> interfaceType, long timeoutDuration, TimeUnit timeoutUnit) {
|
||||
Preconditions.checkNotNull(target);
|
||||
Preconditions.checkNotNull(interfaceType);
|
||||
Preconditions.checkNotNull(timeoutUnit);
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T callWithTimeout(Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit, boolean amInterruptible) throws Exception {
|
||||
Preconditions.checkNotNull(timeoutUnit);
|
||||
return callable.call();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
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;
|
||||
|
||||
public abstract class ForwardingBlockingQueue<E>
|
||||
extends ForwardingQueue<E>
|
||||
implements BlockingQueue<E> {
|
||||
protected ForwardingBlockingQueue() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract BlockingQueue<E> delegate();
|
||||
|
||||
@Override
|
||||
public int drainTo(Collection<? super E> c, int maxElements) {
|
||||
return this.delegate().drainTo(c, maxElements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int drainTo(Collection<? super E> c) {
|
||||
return this.delegate().drainTo(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return this.delegate().offer(e, timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return this.delegate().poll(timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(E e) throws InterruptedException {
|
||||
this.delegate().put(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int remainingCapacity() {
|
||||
return this.delegate().remainingCapacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E take() throws InterruptedException {
|
||||
return this.delegate().take();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.util.concurrent.CheckedFuture;
|
||||
import com.google.common.util.concurrent.ForwardingListenableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Beta
|
||||
public abstract class ForwardingCheckedFuture<V, X extends Exception>
|
||||
extends ForwardingListenableFuture<V>
|
||||
implements CheckedFuture<V, X> {
|
||||
@Override
|
||||
public V checkedGet() throws X {
|
||||
return this.delegate().checkedGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V checkedGet(long timeout, TimeUnit unit) throws TimeoutException, X {
|
||||
return this.delegate().checkedGet(timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract CheckedFuture<V, X> delegate();
|
||||
|
||||
@Beta
|
||||
public static abstract 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 this.delegate;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
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;
|
||||
|
||||
public abstract class ForwardingExecutorService
|
||||
extends ForwardingObject
|
||||
implements ExecutorService {
|
||||
protected ForwardingExecutorService() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract ExecutorService delegate();
|
||||
|
||||
@Override
|
||||
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return this.delegate().awaitTermination(timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
|
||||
return this.delegate().invokeAll(tasks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return this.delegate().invokeAll(tasks, timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
|
||||
return this.delegate().invokeAny(tasks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
return this.delegate().invokeAny(tasks, timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
return this.delegate().isShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
return this.delegate().isTerminated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
this.delegate().shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
return this.delegate().shutdownNow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
this.delegate().execute(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
return this.delegate().submit(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<?> submit(Runnable task) {
|
||||
return this.delegate().submit(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Runnable task, T result) {
|
||||
return this.delegate().submit(task, result);
|
||||
}
|
||||
}
|
60
src/com/google/common/util/concurrent/ForwardingFuture.java
Normal file
60
src/com/google/common/util/concurrent/ForwardingFuture.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
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;
|
||||
|
||||
public abstract class ForwardingFuture<V>
|
||||
extends ForwardingObject
|
||||
implements Future<V> {
|
||||
protected ForwardingFuture() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract Future<V> delegate();
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return this.delegate().cancel(mayInterruptIfRunning);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.delegate().isCancelled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return this.delegate().isDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get() throws InterruptedException, ExecutionException {
|
||||
return this.delegate().get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
return this.delegate().get(timeout, unit);
|
||||
}
|
||||
|
||||
public static abstract 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 this.delegate;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.util.concurrent.ForwardingFuture;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public abstract class ForwardingListenableFuture<V>
|
||||
extends ForwardingFuture<V>
|
||||
implements ListenableFuture<V> {
|
||||
protected ForwardingListenableFuture() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract ListenableFuture<V> delegate();
|
||||
|
||||
@Override
|
||||
public void addListener(Runnable listener, Executor exec) {
|
||||
this.delegate().addListener(listener, exec);
|
||||
}
|
||||
|
||||
public static abstract 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 this.delegate;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.util.concurrent.ForwardingExecutorService;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public abstract class ForwardingListeningExecutorService
|
||||
extends ForwardingExecutorService
|
||||
implements ListeningExecutorService {
|
||||
protected ForwardingListeningExecutorService() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract ListeningExecutorService delegate();
|
||||
|
||||
@Override
|
||||
public <T> ListenableFuture<T> submit(Callable<T> task) {
|
||||
return this.delegate().submit(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<?> submit(Runnable task) {
|
||||
return this.delegate().submit(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ListenableFuture<T> submit(Runnable task, T result) {
|
||||
return this.delegate().submit(task, result);
|
||||
}
|
||||
}
|
12
src/com/google/common/util/concurrent/FutureCallback.java
Normal file
12
src/com/google/common/util/concurrent/FutureCallback.java
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface FutureCallback<V> {
|
||||
public void onSuccess(@Nullable V var1);
|
||||
|
||||
public void onFailure(Throwable var1);
|
||||
}
|
12
src/com/google/common/util/concurrent/FutureFallback.java
Normal file
12
src/com/google/common/util/concurrent/FutureFallback.java
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
@Beta
|
||||
public interface FutureFallback<V> {
|
||||
public ListenableFuture<V> create(Throwable var1) throws Exception;
|
||||
}
|
931
src/com/google/common/util/concurrent/Futures.java
Normal file
931
src/com/google/common/util/concurrent/Futures.java
Normal file
|
@ -0,0 +1,931 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Queues;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.AbstractCheckedFuture;
|
||||
import com.google.common.util.concurrent.AbstractFuture;
|
||||
import com.google.common.util.concurrent.AsyncFunction;
|
||||
import com.google.common.util.concurrent.AsyncSettableFuture;
|
||||
import com.google.common.util.concurrent.CheckedFuture;
|
||||
import com.google.common.util.concurrent.ExecutionError;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.FutureFallback;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListenableFutureTask;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.google.common.util.concurrent.SerializingExecutor;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Beta
|
||||
public final class Futures {
|
||||
private static final AsyncFunction<ListenableFuture<Object>, Object> DEREFERENCER = new AsyncFunction<ListenableFuture<Object>, Object>(){
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Object> apply(ListenableFuture<Object> input) {
|
||||
return input;
|
||||
}
|
||||
};
|
||||
private static final Ordering<Constructor<?>> WITH_STRING_PARAM_FIRST = Ordering.natural().onResultOf(new Function<Constructor<?>, Boolean>(){
|
||||
|
||||
@Override
|
||||
public Boolean apply(Constructor<?> input) {
|
||||
return Arrays.asList(input.getParameterTypes()).contains(String.class);
|
||||
}
|
||||
}).reverse();
|
||||
|
||||
private Futures() {
|
||||
}
|
||||
|
||||
public static <V, X extends Exception> CheckedFuture<V, X> makeChecked(ListenableFuture<V> future, Function<? super Exception, X> mapper) {
|
||||
return new MappingCheckedFuture<V, X>(Preconditions.checkNotNull(future), mapper);
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> immediateFuture(@Nullable V value) {
|
||||
return new ImmediateSuccessfulFuture<V>(value);
|
||||
}
|
||||
|
||||
public static <V, X extends Exception> CheckedFuture<V, X> immediateCheckedFuture(@Nullable V value) {
|
||||
return new ImmediateSuccessfulCheckedFuture(value);
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> immediateFailedFuture(Throwable throwable) {
|
||||
Preconditions.checkNotNull(throwable);
|
||||
return new ImmediateFailedFuture(throwable);
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> immediateCancelledFuture() {
|
||||
return new ImmediateCancelledFuture();
|
||||
}
|
||||
|
||||
public static <V, X extends Exception> CheckedFuture<V, X> immediateFailedCheckedFuture(X exception) {
|
||||
Preconditions.checkNotNull(exception);
|
||||
return new ImmediateFailedCheckedFuture(exception);
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> withFallback(ListenableFuture<? extends V> input, FutureFallback<? extends V> fallback) {
|
||||
return Futures.withFallback(input, fallback, MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> withFallback(ListenableFuture<? extends V> input, FutureFallback<? extends V> fallback, Executor executor) {
|
||||
Preconditions.checkNotNull(fallback);
|
||||
return new FallbackFuture<V>(input, fallback, executor);
|
||||
}
|
||||
|
||||
public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input, AsyncFunction<? super I, ? extends O> function) {
|
||||
ChainingListenableFuture output = new ChainingListenableFuture(function, input);
|
||||
input.addListener(output, MoreExecutors.directExecutor());
|
||||
return output;
|
||||
}
|
||||
|
||||
public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input, AsyncFunction<? super I, ? extends O> function, Executor executor) {
|
||||
Preconditions.checkNotNull(executor);
|
||||
ChainingListenableFuture output = new ChainingListenableFuture(function, input);
|
||||
input.addListener(Futures.rejectionPropagatingRunnable(output, output, executor), MoreExecutors.directExecutor());
|
||||
return output;
|
||||
}
|
||||
|
||||
private static Runnable rejectionPropagatingRunnable(final AbstractFuture<?> outputFuture, final Runnable delegateTask, final Executor delegateExecutor) {
|
||||
return new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
block2: {
|
||||
final AtomicBoolean thrownFromDelegate = new AtomicBoolean(true);
|
||||
try {
|
||||
delegateExecutor.execute(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
thrownFromDelegate.set(false);
|
||||
delegateTask.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (RejectedExecutionException e) {
|
||||
if (!thrownFromDelegate.get()) break block2;
|
||||
outputFuture.setException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input, Function<? super I, ? extends O> function) {
|
||||
Preconditions.checkNotNull(function);
|
||||
ChainingListenableFuture output = new ChainingListenableFuture(Futures.asAsyncFunction(function), input);
|
||||
input.addListener(output, MoreExecutors.directExecutor());
|
||||
return output;
|
||||
}
|
||||
|
||||
public static <I, O> ListenableFuture<O> transform(ListenableFuture<I> input, Function<? super I, ? extends O> function, Executor executor) {
|
||||
Preconditions.checkNotNull(function);
|
||||
return Futures.transform(input, Futures.asAsyncFunction(function), executor);
|
||||
}
|
||||
|
||||
private static <I, O> AsyncFunction<I, O> asAsyncFunction(final Function<? super I, ? extends O> function) {
|
||||
return new AsyncFunction<I, O>(){
|
||||
|
||||
@Override
|
||||
public ListenableFuture<O> apply(I input) {
|
||||
Object output = function.apply(input);
|
||||
return Futures.immediateFuture(output);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static <I, O> Future<O> lazyTransform(final Future<I> input, final Function<? super I, ? extends O> function) {
|
||||
Preconditions.checkNotNull(input);
|
||||
Preconditions.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 this.applyTransformation(input.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public O get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
return this.applyTransformation(input.get(timeout, unit));
|
||||
}
|
||||
|
||||
private O applyTransformation(I input2) throws ExecutionException {
|
||||
try {
|
||||
return function.apply(input2);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
throw new ExecutionException(t);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> dereference(ListenableFuture<? extends ListenableFuture<? extends V>> nested) {
|
||||
return Futures.transform(nested, DEREFERENCER);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static <V> ListenableFuture<List<V>> allAsList(ListenableFuture<? extends V> ... futures) {
|
||||
return Futures.listFuture(ImmutableList.copyOf(futures), true, MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static <V> ListenableFuture<List<V>> allAsList(Iterable<? extends ListenableFuture<? extends V>> futures) {
|
||||
return Futures.listFuture(ImmutableList.copyOf(futures), true, MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> nonCancellationPropagating(ListenableFuture<V> future) {
|
||||
return new NonCancellationPropagatingFuture<V>(future);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static <V> ListenableFuture<List<V>> successfulAsList(ListenableFuture<? extends V> ... futures) {
|
||||
return Futures.listFuture(ImmutableList.copyOf(futures), false, MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static <V> ListenableFuture<List<V>> successfulAsList(Iterable<? extends ListenableFuture<? extends V>> futures) {
|
||||
return Futures.listFuture(ImmutableList.copyOf(futures), false, MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static <T> ImmutableList<ListenableFuture<T>> inCompletionOrder(Iterable<? extends ListenableFuture<? extends T>> futures) {
|
||||
final ConcurrentLinkedQueue delegates = Queues.newConcurrentLinkedQueue();
|
||||
ImmutableList.Builder listBuilder = ImmutableList.builder();
|
||||
SerializingExecutor executor = new SerializingExecutor(MoreExecutors.directExecutor());
|
||||
for (final ListenableFuture<T> future : futures) {
|
||||
AsyncSettableFuture delegate = AsyncSettableFuture.create();
|
||||
delegates.add(delegate);
|
||||
future.addListener(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
((AsyncSettableFuture)delegates.remove()).setFuture(future);
|
||||
}
|
||||
}, executor);
|
||||
listBuilder.add(delegate);
|
||||
}
|
||||
return listBuilder.build();
|
||||
}
|
||||
|
||||
public static <V> void addCallback(ListenableFuture<V> future, FutureCallback<? super V> callback) {
|
||||
Futures.addCallback(future, callback, MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
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() {
|
||||
Object value;
|
||||
try {
|
||||
value = Uninterruptibles.getUninterruptibly(future);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
callback.onFailure(e.getCause());
|
||||
return;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
callback.onFailure(e);
|
||||
return;
|
||||
}
|
||||
catch (Error e) {
|
||||
callback.onFailure(e);
|
||||
return;
|
||||
}
|
||||
callback.onSuccess(value);
|
||||
}
|
||||
};
|
||||
future.addListener(callbackListener, executor);
|
||||
}
|
||||
|
||||
public static <V, X extends Exception> V get(Future<V> future, Class<X> exceptionClass) throws X {
|
||||
Preconditions.checkNotNull(future);
|
||||
Preconditions.checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass), "Futures.get exception type (%s) must not be a RuntimeException", exceptionClass);
|
||||
try {
|
||||
return future.get();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw Futures.newWithCause(exceptionClass, e);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
Futures.wrapAndThrowExceptionOrError(e.getCause(), exceptionClass);
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
public static <V, X extends Exception> V get(Future<V> future, long timeout, TimeUnit unit, Class<X> exceptionClass) throws X {
|
||||
Preconditions.checkNotNull(future);
|
||||
Preconditions.checkNotNull(unit);
|
||||
Preconditions.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) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw Futures.newWithCause(exceptionClass, e);
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
throw Futures.newWithCause(exceptionClass, e);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
Futures.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 Futures.newWithCause(exceptionClass, cause);
|
||||
}
|
||||
|
||||
public static <V> V getUnchecked(Future<V> future) {
|
||||
Preconditions.checkNotNull(future);
|
||||
try {
|
||||
return Uninterruptibles.getUninterruptibly(future);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
Futures.wrapAndThrowUnchecked(e.getCause());
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
private static void wrapAndThrowUnchecked(Throwable cause) {
|
||||
if (cause instanceof Error) {
|
||||
throw new ExecutionError((Error)cause);
|
||||
}
|
||||
throw new UncheckedExecutionException(cause);
|
||||
}
|
||||
|
||||
private static <X extends Exception> X newWithCause(Class<X> exceptionClass, Throwable cause) {
|
||||
List<Constructor<X>> constructors = Arrays.asList(exceptionClass.getConstructors());
|
||||
for (Constructor<X> constructor : Futures.preferringStrings(constructors)) {
|
||||
Exception instance = (Exception)Futures.newFromConstructor(constructor, cause);
|
||||
if (instance == null) continue;
|
||||
if (instance.getCause() == null) {
|
||||
instance.initCause(cause);
|
||||
}
|
||||
return (X)instance;
|
||||
}
|
||||
String string = String.valueOf(String.valueOf(exceptionClass));
|
||||
throw new IllegalArgumentException(new StringBuilder(82 + string.length()).append("No appropriate constructor for exception of type ").append(string).append(" in response to chained exception").toString(), cause);
|
||||
}
|
||||
|
||||
private static <X extends Exception> List<Constructor<X>> preferringStrings(List<Constructor<X>> constructors) {
|
||||
return WITH_STRING_PARAM_FIRST.sortedCopy(constructors);
|
||||
}
|
||||
|
||||
@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();
|
||||
continue;
|
||||
}
|
||||
if (paramType.equals(Throwable.class)) {
|
||||
params[i] = cause;
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private static <V> ListenableFuture<List<V>> listFuture(ImmutableList<ListenableFuture<? extends V>> futures, boolean allMustSucceed, Executor listenerExecutor) {
|
||||
return new CombinedFuture(futures, allMustSucceed, listenerExecutor, new FutureCombiner<V, List<V>>(){
|
||||
|
||||
@Override
|
||||
public List<V> combine(List<Optional<V>> values) {
|
||||
ArrayList<Object> result = Lists.newArrayList();
|
||||
for (Optional element : values) {
|
||||
result.add(element != null ? (Object)element.orNull() : null);
|
||||
}
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class MappingCheckedFuture<V, X extends Exception>
|
||||
extends AbstractCheckedFuture<V, X> {
|
||||
final Function<? super Exception, X> mapper;
|
||||
|
||||
MappingCheckedFuture(ListenableFuture<V> delegate, Function<? super Exception, X> mapper) {
|
||||
super(delegate);
|
||||
this.mapper = Preconditions.checkNotNull(mapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X mapException(Exception e) {
|
||||
return (X)((Exception)this.mapper.apply(e));
|
||||
}
|
||||
}
|
||||
|
||||
private static class CombinedFuture<V, C>
|
||||
extends AbstractFuture<C> {
|
||||
private static final Logger logger = Logger.getLogger(CombinedFuture.class.getName());
|
||||
ImmutableCollection<? extends ListenableFuture<? extends V>> futures;
|
||||
final boolean allMustSucceed;
|
||||
final AtomicInteger remaining;
|
||||
FutureCombiner<V, C> combiner;
|
||||
List<Optional<V>> values;
|
||||
final Object seenExceptionsLock = new Object();
|
||||
Set<Throwable> seenExceptions;
|
||||
|
||||
CombinedFuture(ImmutableCollection<? extends ListenableFuture<? extends V>> futures, boolean allMustSucceed, Executor listenerExecutor, FutureCombiner<V, C> combiner) {
|
||||
this.futures = futures;
|
||||
this.allMustSucceed = allMustSucceed;
|
||||
this.remaining = new AtomicInteger(futures.size());
|
||||
this.combiner = combiner;
|
||||
this.values = Lists.newArrayListWithCapacity(futures.size());
|
||||
this.init(listenerExecutor);
|
||||
}
|
||||
|
||||
protected void init(Executor listenerExecutor) {
|
||||
int i;
|
||||
this.addListener(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (CombinedFuture.this.isCancelled()) {
|
||||
for (ListenableFuture listenableFuture : CombinedFuture.this.futures) {
|
||||
listenableFuture.cancel(CombinedFuture.this.wasInterrupted());
|
||||
}
|
||||
}
|
||||
CombinedFuture.this.futures = null;
|
||||
CombinedFuture.this.values = null;
|
||||
CombinedFuture.this.combiner = null;
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
if (this.futures.isEmpty()) {
|
||||
this.set(this.combiner.combine(ImmutableList.of()));
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < this.futures.size(); ++i) {
|
||||
this.values.add(null);
|
||||
}
|
||||
i = 0;
|
||||
for (final ListenableFuture listenableFuture : this.futures) {
|
||||
final int index = i++;
|
||||
listenableFuture.addListener(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
CombinedFuture.this.setOneValue(index, listenableFuture);
|
||||
}
|
||||
}, listenerExecutor);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
private void setExceptionAndMaybeLog(Throwable throwable) {
|
||||
boolean visibleFromOutputFuture = false;
|
||||
boolean firstTimeSeeingThisException = true;
|
||||
if (this.allMustSucceed) {
|
||||
visibleFromOutputFuture = super.setException(throwable);
|
||||
Object object = this.seenExceptionsLock;
|
||||
synchronized (object) {
|
||||
if (this.seenExceptions == null) {
|
||||
this.seenExceptions = Sets.newHashSet();
|
||||
}
|
||||
firstTimeSeeingThisException = this.seenExceptions.add(throwable);
|
||||
}
|
||||
}
|
||||
if (throwable instanceof Error || this.allMustSucceed && !visibleFromOutputFuture && firstTimeSeeingThisException) {
|
||||
logger.log(Level.SEVERE, "input future failed.", throwable);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Exception decompiling
|
||||
*/
|
||||
private void setOneValue(int index, Future<? extends V> future) {
|
||||
/*
|
||||
* This method has failed to decompile. When submitting a bug report, please provide this stack trace, and (if you hold appropriate legal rights) the relevant class file.
|
||||
*
|
||||
* org.benf.cfr.reader.util.ConfusedCFRException: Started 2 blocks at once
|
||||
* at org.benf.cfr.reader.bytecode.analysis.opgraph.Op04StructuredStatement.getStartingBlocks(Op04StructuredStatement.java:412)
|
||||
* at org.benf.cfr.reader.bytecode.analysis.opgraph.Op04StructuredStatement.buildNestedBlocks(Op04StructuredStatement.java:487)
|
||||
* at org.benf.cfr.reader.bytecode.analysis.opgraph.Op03SimpleStatement.createInitialStructuredBlock(Op03SimpleStatement.java:736)
|
||||
* at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisInner(CodeAnalyser.java:850)
|
||||
* at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisOrWrapFail(CodeAnalyser.java:278)
|
||||
* at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysis(CodeAnalyser.java:201)
|
||||
* at org.benf.cfr.reader.entities.attributes.AttributeCode.analyse(AttributeCode.java:94)
|
||||
* at org.benf.cfr.reader.entities.Method.analyse(Method.java:531)
|
||||
* at org.benf.cfr.reader.entities.ClassFile.analyseMid(ClassFile.java:1055)
|
||||
* at org.benf.cfr.reader.entities.ClassFile.analyseInnerClassesPass1(ClassFile.java:923)
|
||||
* at org.benf.cfr.reader.entities.ClassFile.analyseMid(ClassFile.java:1035)
|
||||
* at org.benf.cfr.reader.entities.ClassFile.analyseTop(ClassFile.java:942)
|
||||
* at org.benf.cfr.reader.Driver.doClass(Driver.java:84)
|
||||
* at org.benf.cfr.reader.CfrDriverImpl.analyse(CfrDriverImpl.java:78)
|
||||
* at org.benf.cfr.reader.Main.main(Main.java:54)
|
||||
*/
|
||||
throw new IllegalStateException("Decompilation failed");
|
||||
}
|
||||
}
|
||||
|
||||
private static interface FutureCombiner<V, C> {
|
||||
public C combine(List<Optional<V>> var1);
|
||||
}
|
||||
|
||||
private static class NonCancellationPropagatingFuture<V>
|
||||
extends AbstractFuture<V> {
|
||||
NonCancellationPropagatingFuture(final ListenableFuture<V> delegate) {
|
||||
Preconditions.checkNotNull(delegate);
|
||||
Futures.addCallback(delegate, new FutureCallback<V>(){
|
||||
|
||||
@Override
|
||||
public void onSuccess(V result) {
|
||||
NonCancellationPropagatingFuture.this.set(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
if (delegate.isCancelled()) {
|
||||
NonCancellationPropagatingFuture.this.cancel(false);
|
||||
} else {
|
||||
NonCancellationPropagatingFuture.this.setException(t);
|
||||
}
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CombinerFuture<V>
|
||||
extends ListenableFutureTask<V> {
|
||||
ImmutableList<ListenableFuture<?>> futures;
|
||||
|
||||
CombinerFuture(Callable<V> callable, ImmutableList<ListenableFuture<?>> futures) {
|
||||
super(callable);
|
||||
this.futures = futures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
ImmutableList<ListenableFuture<?>> futures = this.futures;
|
||||
if (super.cancel(mayInterruptIfRunning)) {
|
||||
for (ListenableFuture listenableFuture : futures) {
|
||||
listenableFuture.cancel(mayInterruptIfRunning);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
super.done();
|
||||
this.futures = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setException(Throwable t) {
|
||||
super.setException(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class WrappedCombiner<T>
|
||||
implements Callable<T> {
|
||||
final Callable<T> delegate;
|
||||
CombinerFuture<T> outputFuture;
|
||||
|
||||
WrappedCombiner(Callable<T> delegate) {
|
||||
this.delegate = Preconditions.checkNotNull(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T call() throws Exception {
|
||||
try {
|
||||
return this.delegate.call();
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
this.outputFuture.setException(e.getCause());
|
||||
}
|
||||
catch (CancellationException e) {
|
||||
this.outputFuture.cancel(false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
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 ChainingListenableFuture(AsyncFunction<? super I, ? extends O> function, ListenableFuture<? extends I> inputFuture) {
|
||||
this.function = Preconditions.checkNotNull(function);
|
||||
this.inputFuture = Preconditions.checkNotNull(inputFuture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
if (super.cancel(mayInterruptIfRunning)) {
|
||||
this.cancel(this.inputFuture, mayInterruptIfRunning);
|
||||
this.cancel(this.outputFuture, mayInterruptIfRunning);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void cancel(@Nullable Future<?> future, boolean mayInterruptIfRunning) {
|
||||
if (future != null) {
|
||||
future.cancel(mayInterruptIfRunning);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
* Loose catch block
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
block14: {
|
||||
try {
|
||||
I sourceResult;
|
||||
try {
|
||||
sourceResult = Uninterruptibles.getUninterruptibly(this.inputFuture);
|
||||
}
|
||||
catch (CancellationException e) {
|
||||
this.cancel(false);
|
||||
this.function = null;
|
||||
this.inputFuture = null;
|
||||
return;
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
this.setException(e.getCause());
|
||||
this.function = null;
|
||||
this.inputFuture = null;
|
||||
return;
|
||||
}
|
||||
this.outputFuture = Preconditions.checkNotNull(this.function.apply(sourceResult), "AsyncFunction may not return null.");
|
||||
final ListenableFuture<O> outputFuture = this.outputFuture;
|
||||
if (this.isCancelled()) {
|
||||
outputFuture.cancel(this.wasInterrupted());
|
||||
this.outputFuture = null;
|
||||
return;
|
||||
}
|
||||
outputFuture.addListener(new Runnable(){
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ChainingListenableFuture.this.set(Uninterruptibles.getUninterruptibly(outputFuture));
|
||||
}
|
||||
catch (CancellationException e) {
|
||||
ChainingListenableFuture.this.cancel(false);
|
||||
return;
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
ChainingListenableFuture.this.setException(e.getCause());
|
||||
}
|
||||
finally {
|
||||
ChainingListenableFuture.this.outputFuture = null;
|
||||
}
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
break block14;
|
||||
{
|
||||
catch (UndeclaredThrowableException e) {
|
||||
this.setException(e.getCause());
|
||||
break block14;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.setException(t);
|
||||
break block14;
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
throw throwable;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.function = null;
|
||||
this.inputFuture = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class FallbackFuture<V>
|
||||
extends AbstractFuture<V> {
|
||||
private volatile ListenableFuture<? extends V> running;
|
||||
|
||||
FallbackFuture(ListenableFuture<? extends V> input, final FutureFallback<? extends V> fallback, Executor executor) {
|
||||
this.running = input;
|
||||
Futures.addCallback(this.running, new FutureCallback<V>(){
|
||||
|
||||
@Override
|
||||
public void onSuccess(V value) {
|
||||
FallbackFuture.this.set(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
if (FallbackFuture.this.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
FallbackFuture.this.running = fallback.create(t);
|
||||
if (FallbackFuture.this.isCancelled()) {
|
||||
FallbackFuture.this.running.cancel(FallbackFuture.this.wasInterrupted());
|
||||
return;
|
||||
}
|
||||
Futures.addCallback(FallbackFuture.this.running, new FutureCallback<V>(){
|
||||
|
||||
@Override
|
||||
public void onSuccess(V value) {
|
||||
FallbackFuture.this.set(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
if (FallbackFuture.this.running.isCancelled()) {
|
||||
FallbackFuture.this.cancel(false);
|
||||
} else {
|
||||
FallbackFuture.this.setException(t);
|
||||
}
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
}
|
||||
catch (Throwable e) {
|
||||
FallbackFuture.this.setException(e);
|
||||
}
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
if (super.cancel(mayInterruptIfRunning)) {
|
||||
this.running.cancel(mayInterruptIfRunning);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImmediateFailedCheckedFuture<V, X extends Exception>
|
||||
extends ImmediateFuture<V>
|
||||
implements CheckedFuture<V, X> {
|
||||
private final X thrown;
|
||||
|
||||
ImmediateFailedCheckedFuture(X thrown) {
|
||||
this.thrown = thrown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get() throws ExecutionException {
|
||||
throw new ExecutionException((Throwable)this.thrown);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V checkedGet() throws X {
|
||||
throw this.thrown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V checkedGet(long timeout, TimeUnit unit) throws X {
|
||||
Preconditions.checkNotNull(unit);
|
||||
throw this.thrown;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImmediateCancelledFuture<V>
|
||||
extends ImmediateFuture<V> {
|
||||
private final CancellationException thrown = new CancellationException("Immediate cancelled future.");
|
||||
|
||||
ImmediateCancelledFuture() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get() {
|
||||
throw AbstractFuture.cancellationExceptionWithCause("Task was cancelled.", this.thrown);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImmediateFailedFuture<V>
|
||||
extends ImmediateFuture<V> {
|
||||
private final Throwable thrown;
|
||||
|
||||
ImmediateFailedFuture(Throwable thrown) {
|
||||
this.thrown = thrown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get() throws ExecutionException {
|
||||
throw new ExecutionException(this.thrown);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImmediateSuccessfulCheckedFuture<V, X extends Exception>
|
||||
extends ImmediateFuture<V>
|
||||
implements CheckedFuture<V, X> {
|
||||
@Nullable
|
||||
private final V value;
|
||||
|
||||
ImmediateSuccessfulCheckedFuture(@Nullable V value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V checkedGet() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V checkedGet(long timeout, TimeUnit unit) {
|
||||
Preconditions.checkNotNull(unit);
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImmediateSuccessfulFuture<V>
|
||||
extends ImmediateFuture<V> {
|
||||
@Nullable
|
||||
private final V value;
|
||||
|
||||
ImmediateSuccessfulFuture(@Nullable V value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class ImmediateFuture<V>
|
||||
implements ListenableFuture<V> {
|
||||
private static final Logger log = Logger.getLogger(ImmediateFuture.class.getName());
|
||||
|
||||
private ImmediateFuture() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(Runnable listener, Executor executor) {
|
||||
Preconditions.checkNotNull(listener, "Runnable was null.");
|
||||
Preconditions.checkNotNull(executor, "Executor was null.");
|
||||
try {
|
||||
executor.execute(listener);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
String string = String.valueOf(String.valueOf(listener));
|
||||
String string2 = String.valueOf(String.valueOf(executor));
|
||||
log.log(Level.SEVERE, new StringBuilder(57 + string.length() + string2.length()).append("RuntimeException while executing runnable ").append(string).append(" with executor ").append(string2).toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract V get() throws ExecutionException;
|
||||
|
||||
@Override
|
||||
public V get(long timeout, TimeUnit unit) throws ExecutionException {
|
||||
Preconditions.checkNotNull(unit);
|
||||
return this.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
90
src/com/google/common/util/concurrent/JdkFutureAdapters.java
Normal file
90
src/com/google/common/util/concurrent/JdkFutureAdapters.java
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.util.concurrent.ExecutionList;
|
||||
import com.google.common.util.concurrent.ForwardingFuture;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
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;
|
||||
|
||||
@Beta
|
||||
public final class JdkFutureAdapters {
|
||||
public static <V> ListenableFuture<V> listenInPoolThread(Future<V> future) {
|
||||
if (future instanceof ListenableFuture) {
|
||||
return (ListenableFuture)future;
|
||||
}
|
||||
return new ListenableFutureAdapter<V>(future);
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> listenInPoolThread(Future<V> future, Executor executor) {
|
||||
Preconditions.checkNotNull(executor);
|
||||
if (future instanceof ListenableFuture) {
|
||||
return (ListenableFuture)future;
|
||||
}
|
||||
return new ListenableFutureAdapter<V>(future, executor);
|
||||
}
|
||||
|
||||
private JdkFutureAdapters() {
|
||||
}
|
||||
|
||||
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;
|
||||
private final ExecutionList executionList = new ExecutionList();
|
||||
private final AtomicBoolean hasListeners = new AtomicBoolean(false);
|
||||
private final Future<V> delegate;
|
||||
|
||||
ListenableFutureAdapter(Future<V> delegate) {
|
||||
this(delegate, defaultAdapterExecutor);
|
||||
}
|
||||
|
||||
ListenableFutureAdapter(Future<V> delegate, Executor adapterExecutor) {
|
||||
this.delegate = Preconditions.checkNotNull(delegate);
|
||||
this.adapterExecutor = Preconditions.checkNotNull(adapterExecutor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Future<V> delegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(Runnable listener, Executor exec) {
|
||||
this.executionList.add(listener, exec);
|
||||
if (this.hasListeners.compareAndSet(false, true)) {
|
||||
if (this.delegate.isDone()) {
|
||||
this.executionList.execute();
|
||||
return;
|
||||
}
|
||||
this.adapterExecutor.execute(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Uninterruptibles.getUninterruptibly(ListenableFutureAdapter.this.delegate);
|
||||
}
|
||||
catch (Error e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
// empty catch block
|
||||
}
|
||||
ListenableFutureAdapter.this.executionList.execute();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
src/com/google/common/util/concurrent/ListenableFuture.java
Normal file
12
src/com/google/common/util/concurrent/ListenableFuture.java
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public interface ListenableFuture<V>
|
||||
extends Future<V> {
|
||||
public void addListener(Runnable var1, Executor var2);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.util.concurrent.ExecutionList;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ListenableFutureTask<V>
|
||||
extends FutureTask<V>
|
||||
implements ListenableFuture<V> {
|
||||
private final ExecutionList executionList = new ExecutionList();
|
||||
|
||||
public static <V> ListenableFutureTask<V> create(Callable<V> callable) {
|
||||
return new ListenableFutureTask<V>(callable);
|
||||
}
|
||||
|
||||
public static <V> ListenableFutureTask<V> create(Runnable runnable, @Nullable V result) {
|
||||
return new ListenableFutureTask<V>(runnable, result);
|
||||
}
|
||||
|
||||
ListenableFutureTask(Callable<V> callable) {
|
||||
super(callable);
|
||||
}
|
||||
|
||||
ListenableFutureTask(Runnable runnable, @Nullable V result) {
|
||||
super(runnable, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(Runnable listener, Executor exec) {
|
||||
this.executionList.add(listener, exec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
this.executionList.execute();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
@Beta
|
||||
public interface ListenableScheduledFuture<V>
|
||||
extends ScheduledFuture<V>,
|
||||
ListenableFuture<V> {
|
||||
}
|
121
src/com/google/common/util/concurrent/ListenerCallQueue.java
Normal file
121
src/com/google/common/util/concurrent/ListenerCallQueue.java
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Queues;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
|
||||
final class ListenerCallQueue<L>
|
||||
implements Runnable {
|
||||
private static final Logger logger = Logger.getLogger(ListenerCallQueue.class.getName());
|
||||
private final L listener;
|
||||
private final Executor executor;
|
||||
@GuardedBy(value="this")
|
||||
private final Queue<Callback<L>> waitQueue = Queues.newArrayDeque();
|
||||
@GuardedBy(value="this")
|
||||
private boolean isThreadScheduled;
|
||||
|
||||
ListenerCallQueue(L listener, Executor executor) {
|
||||
this.listener = Preconditions.checkNotNull(listener);
|
||||
this.executor = Preconditions.checkNotNull(executor);
|
||||
}
|
||||
|
||||
synchronized void add(Callback<L> callback) {
|
||||
this.waitQueue.add(callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
void execute() {
|
||||
boolean scheduleTaskRunner = false;
|
||||
ListenerCallQueue listenerCallQueue = this;
|
||||
synchronized (listenerCallQueue) {
|
||||
if (!this.isThreadScheduled) {
|
||||
this.isThreadScheduled = true;
|
||||
scheduleTaskRunner = true;
|
||||
}
|
||||
}
|
||||
if (scheduleTaskRunner) {
|
||||
try {
|
||||
this.executor.execute(this);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
Object object = this;
|
||||
synchronized (object) {
|
||||
this.isThreadScheduled = false;
|
||||
}
|
||||
object = String.valueOf(String.valueOf(this.listener));
|
||||
String string = String.valueOf(String.valueOf(this.executor));
|
||||
logger.log(Level.SEVERE, new StringBuilder(42 + ((String)object).length() + string.length()).append("Exception while running callbacks for ").append((String)object).append(" on ").append(string).toString(), e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
block18: {
|
||||
boolean stillRunning = true;
|
||||
block14: while (true) {
|
||||
while (true) {
|
||||
Callback<L> nextToRun;
|
||||
ListenerCallQueue listenerCallQueue = this;
|
||||
synchronized (listenerCallQueue) {
|
||||
Preconditions.checkState(this.isThreadScheduled);
|
||||
nextToRun = this.waitQueue.poll();
|
||||
if (nextToRun == null) {
|
||||
this.isThreadScheduled = false;
|
||||
stillRunning = false;
|
||||
break block18;
|
||||
}
|
||||
}
|
||||
try {
|
||||
nextToRun.call(this.listener);
|
||||
continue block14;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
String string = String.valueOf(String.valueOf(this.listener));
|
||||
String string2 = String.valueOf(String.valueOf(((Callback)nextToRun).methodCall));
|
||||
logger.log(Level.SEVERE, new StringBuilder(37 + string.length() + string2.length()).append("Exception while executing callback: ").append(string).append(".").append(string2).toString(), e);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (stillRunning) {
|
||||
ListenerCallQueue listenerCallQueue = this;
|
||||
synchronized (listenerCallQueue) {
|
||||
this.isThreadScheduled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class Callback<L> {
|
||||
private final String methodCall;
|
||||
|
||||
Callback(String methodCall) {
|
||||
this.methodCall = methodCall;
|
||||
}
|
||||
|
||||
abstract void call(L var1);
|
||||
|
||||
void enqueueOn(Iterable<ListenerCallQueue<L>> queues) {
|
||||
for (ListenerCallQueue<L> queue : queues) {
|
||||
queue.add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
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.TimeUnit;
|
||||
|
||||
public interface ListeningExecutorService
|
||||
extends ExecutorService {
|
||||
public <T> ListenableFuture<T> submit(Callable<T> var1);
|
||||
|
||||
public ListenableFuture<?> submit(Runnable var1);
|
||||
|
||||
public <T> ListenableFuture<T> submit(Runnable var1, T var2);
|
||||
|
||||
@Override
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> var1) throws InterruptedException;
|
||||
|
||||
@Override
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> var1, long var2, TimeUnit var4) throws InterruptedException;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.util.concurrent.ListenableScheduledFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Beta
|
||||
public interface ListeningScheduledExecutorService
|
||||
extends ScheduledExecutorService,
|
||||
ListeningExecutorService {
|
||||
public ListenableScheduledFuture<?> schedule(Runnable var1, long var2, TimeUnit var4);
|
||||
|
||||
public <V> ListenableScheduledFuture<V> schedule(Callable<V> var1, long var2, TimeUnit var4);
|
||||
|
||||
public ListenableScheduledFuture<?> scheduleAtFixedRate(Runnable var1, long var2, long var4, TimeUnit var6);
|
||||
|
||||
public ListenableScheduledFuture<?> scheduleWithFixedDelay(Runnable var1, long var2, long var4, TimeUnit var6);
|
||||
}
|
599
src/com/google/common/util/concurrent/Monitor.java
Normal file
599
src/com/google/common/util/concurrent/Monitor.java
Normal file
|
@ -0,0 +1,599 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
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.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
|
||||
@Beta
|
||||
public final class Monitor {
|
||||
private final boolean fair;
|
||||
private final ReentrantLock lock;
|
||||
@GuardedBy(value="lock")
|
||||
private Guard activeGuards = null;
|
||||
|
||||
public Monitor() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public Monitor(boolean fair) {
|
||||
this.fair = fair;
|
||||
this.lock = new ReentrantLock(fair);
|
||||
}
|
||||
|
||||
public void enter() {
|
||||
this.lock.lock();
|
||||
}
|
||||
|
||||
public void enterInterruptibly() throws InterruptedException {
|
||||
this.lock.lockInterruptibly();
|
||||
}
|
||||
|
||||
public boolean enter(long time, TimeUnit unit) {
|
||||
long timeoutNanos = unit.toNanos(time);
|
||||
ReentrantLock lock = this.lock;
|
||||
if (!this.fair && lock.tryLock()) {
|
||||
return true;
|
||||
}
|
||||
long deadline = System.nanoTime() + timeoutNanos;
|
||||
boolean interrupted = Thread.interrupted();
|
||||
while (true) {
|
||||
try {
|
||||
boolean bl = lock.tryLock(timeoutNanos, TimeUnit.NANOSECONDS);
|
||||
return bl;
|
||||
}
|
||||
catch (InterruptedException interrupt) {
|
||||
interrupted = true;
|
||||
timeoutNanos = deadline - System.nanoTime();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean enterInterruptibly(long time, TimeUnit unit) throws InterruptedException {
|
||||
return this.lock.tryLock(time, unit);
|
||||
}
|
||||
|
||||
public boolean tryEnter() {
|
||||
return this.lock.tryLock();
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public void enterWhen(Guard guard) throws InterruptedException {
|
||||
if (guard.monitor != this) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
ReentrantLock lock = this.lock;
|
||||
boolean signalBeforeWaiting = lock.isHeldByCurrentThread();
|
||||
lock.lockInterruptibly();
|
||||
boolean satisfied = false;
|
||||
try {
|
||||
if (!guard.isSatisfied()) {
|
||||
this.await(guard, signalBeforeWaiting);
|
||||
}
|
||||
satisfied = true;
|
||||
}
|
||||
finally {
|
||||
if (!satisfied) {
|
||||
this.leave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public void enterWhenUninterruptibly(Guard guard) {
|
||||
if (guard.monitor != this) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
ReentrantLock lock = this.lock;
|
||||
boolean signalBeforeWaiting = lock.isHeldByCurrentThread();
|
||||
lock.lock();
|
||||
boolean satisfied = false;
|
||||
try {
|
||||
if (!guard.isSatisfied()) {
|
||||
this.awaitUninterruptibly(guard, signalBeforeWaiting);
|
||||
}
|
||||
satisfied = true;
|
||||
}
|
||||
finally {
|
||||
if (!satisfied) {
|
||||
this.leave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public boolean enterWhen(Guard guard, long time, TimeUnit unit) throws InterruptedException {
|
||||
long timeoutNanos = unit.toNanos(time);
|
||||
if (guard.monitor != this) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
ReentrantLock lock = this.lock;
|
||||
boolean reentrant = lock.isHeldByCurrentThread();
|
||||
if (this.fair || !lock.tryLock()) {
|
||||
long deadline = System.nanoTime() + timeoutNanos;
|
||||
if (!lock.tryLock(time, unit)) {
|
||||
return false;
|
||||
}
|
||||
timeoutNanos = deadline - System.nanoTime();
|
||||
}
|
||||
boolean satisfied = false;
|
||||
boolean threw = true;
|
||||
try {
|
||||
satisfied = guard.isSatisfied() || this.awaitNanos(guard, timeoutNanos, reentrant);
|
||||
threw = false;
|
||||
boolean bl = satisfied;
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
if (!satisfied) {
|
||||
try {
|
||||
if (threw && !reentrant) {
|
||||
this.signalNextWaiter();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Loose catch block
|
||||
*/
|
||||
public boolean enterWhenUninterruptibly(Guard guard, long time, TimeUnit unit) {
|
||||
long timeoutNanos = unit.toNanos(time);
|
||||
if (guard.monitor != this) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
ReentrantLock lock = this.lock;
|
||||
long deadline = System.nanoTime() + timeoutNanos;
|
||||
boolean signalBeforeWaiting = lock.isHeldByCurrentThread();
|
||||
boolean interrupted = Thread.interrupted();
|
||||
try {
|
||||
if (this.fair || !lock.tryLock()) {
|
||||
boolean locked = false;
|
||||
do {
|
||||
try {
|
||||
locked = lock.tryLock(timeoutNanos, TimeUnit.NANOSECONDS);
|
||||
if (!locked) {
|
||||
boolean bl = false;
|
||||
return bl;
|
||||
}
|
||||
}
|
||||
catch (InterruptedException interrupt) {
|
||||
interrupted = true;
|
||||
}
|
||||
timeoutNanos = deadline - System.nanoTime();
|
||||
} while (!locked);
|
||||
}
|
||||
boolean satisfied = false;
|
||||
while (true) {
|
||||
try {
|
||||
satisfied = guard.isSatisfied() || this.awaitNanos(guard, timeoutNanos, signalBeforeWaiting);
|
||||
boolean interrupt = satisfied;
|
||||
return interrupt;
|
||||
}
|
||||
catch (InterruptedException interrupt) {
|
||||
interrupted = true;
|
||||
signalBeforeWaiting = false;
|
||||
timeoutNanos = deadline - System.nanoTime();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
finally {
|
||||
if (!satisfied) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
{
|
||||
catch (Throwable throwable) {
|
||||
throw throwable;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public boolean enterIf(Guard guard) {
|
||||
if (guard.monitor != this) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
boolean satisfied = false;
|
||||
try {
|
||||
boolean bl = satisfied = guard.isSatisfied();
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
if (!satisfied) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public boolean enterIfInterruptibly(Guard guard) throws InterruptedException {
|
||||
if (guard.monitor != this) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
ReentrantLock lock = this.lock;
|
||||
lock.lockInterruptibly();
|
||||
boolean satisfied = false;
|
||||
try {
|
||||
boolean bl = satisfied = guard.isSatisfied();
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
if (!satisfied) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public boolean enterIf(Guard guard, long time, TimeUnit unit) {
|
||||
if (guard.monitor != this) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
if (!this.enter(time, unit)) {
|
||||
return false;
|
||||
}
|
||||
boolean satisfied = false;
|
||||
try {
|
||||
boolean bl = satisfied = guard.isSatisfied();
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
if (!satisfied) {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public boolean enterIfInterruptibly(Guard guard, long time, TimeUnit unit) throws InterruptedException {
|
||||
if (guard.monitor != this) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
ReentrantLock lock = this.lock;
|
||||
if (!lock.tryLock(time, unit)) {
|
||||
return false;
|
||||
}
|
||||
boolean satisfied = false;
|
||||
try {
|
||||
boolean bl = satisfied = guard.isSatisfied();
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
if (!satisfied) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public boolean tryEnterIf(Guard guard) {
|
||||
if (guard.monitor != this) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
ReentrantLock lock = this.lock;
|
||||
if (!lock.tryLock()) {
|
||||
return false;
|
||||
}
|
||||
boolean satisfied = false;
|
||||
try {
|
||||
boolean bl = satisfied = guard.isSatisfied();
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
if (!satisfied) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void waitFor(Guard guard) throws InterruptedException {
|
||||
if (!(guard.monitor == this & this.lock.isHeldByCurrentThread())) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
if (!guard.isSatisfied()) {
|
||||
this.await(guard, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void waitForUninterruptibly(Guard guard) {
|
||||
if (!(guard.monitor == this & this.lock.isHeldByCurrentThread())) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
if (!guard.isSatisfied()) {
|
||||
this.awaitUninterruptibly(guard, true);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean waitFor(Guard guard, long time, TimeUnit unit) throws InterruptedException {
|
||||
long timeoutNanos = unit.toNanos(time);
|
||||
if (!(guard.monitor == this & this.lock.isHeldByCurrentThread())) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
return guard.isSatisfied() || this.awaitNanos(guard, timeoutNanos, true);
|
||||
}
|
||||
|
||||
public boolean waitForUninterruptibly(Guard guard, long time, TimeUnit unit) {
|
||||
long timeoutNanos = unit.toNanos(time);
|
||||
if (!(guard.monitor == this & this.lock.isHeldByCurrentThread())) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
if (guard.isSatisfied()) {
|
||||
return true;
|
||||
}
|
||||
boolean signalBeforeWaiting = true;
|
||||
long deadline = System.nanoTime() + timeoutNanos;
|
||||
boolean interrupted = Thread.interrupted();
|
||||
while (true) {
|
||||
try {
|
||||
boolean bl = this.awaitNanos(guard, timeoutNanos, signalBeforeWaiting);
|
||||
return bl;
|
||||
}
|
||||
catch (InterruptedException interrupt) {
|
||||
interrupted = true;
|
||||
if (guard.isSatisfied()) {
|
||||
boolean bl = true;
|
||||
return bl;
|
||||
}
|
||||
signalBeforeWaiting = false;
|
||||
timeoutNanos = deadline - System.nanoTime();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public void leave() {
|
||||
ReentrantLock lock = this.lock;
|
||||
try {
|
||||
if (lock.getHoldCount() == 1) {
|
||||
this.signalNextWaiter();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFair() {
|
||||
return this.fair;
|
||||
}
|
||||
|
||||
public boolean isOccupied() {
|
||||
return this.lock.isLocked();
|
||||
}
|
||||
|
||||
public boolean isOccupiedByCurrentThread() {
|
||||
return this.lock.isHeldByCurrentThread();
|
||||
}
|
||||
|
||||
public int getOccupiedDepth() {
|
||||
return this.lock.getHoldCount();
|
||||
}
|
||||
|
||||
public int getQueueLength() {
|
||||
return this.lock.getQueueLength();
|
||||
}
|
||||
|
||||
public boolean hasQueuedThreads() {
|
||||
return this.lock.hasQueuedThreads();
|
||||
}
|
||||
|
||||
public boolean hasQueuedThread(Thread thread) {
|
||||
return this.lock.hasQueuedThread(thread);
|
||||
}
|
||||
|
||||
public boolean hasWaiters(Guard guard) {
|
||||
return this.getWaitQueueLength(guard) > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public int getWaitQueueLength(Guard guard) {
|
||||
if (guard.monitor != this) {
|
||||
throw new IllegalMonitorStateException();
|
||||
}
|
||||
this.lock.lock();
|
||||
try {
|
||||
int n = guard.waiterCount;
|
||||
return n;
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="lock")
|
||||
private void signalNextWaiter() {
|
||||
Guard guard = this.activeGuards;
|
||||
while (guard != null) {
|
||||
if (this.isSatisfied(guard)) {
|
||||
guard.condition.signal();
|
||||
break;
|
||||
}
|
||||
guard = guard.next;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="lock")
|
||||
private boolean isSatisfied(Guard guard) {
|
||||
try {
|
||||
return guard.isSatisfied();
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
this.signalAllWaiters();
|
||||
throw Throwables.propagate(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="lock")
|
||||
private void signalAllWaiters() {
|
||||
Guard guard = this.activeGuards;
|
||||
while (guard != null) {
|
||||
guard.condition.signalAll();
|
||||
guard = guard.next;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="lock")
|
||||
private void beginWaitingFor(Guard guard) {
|
||||
int waiters;
|
||||
if ((waiters = guard.waiterCount++) == 0) {
|
||||
guard.next = this.activeGuards;
|
||||
this.activeGuards = guard;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="lock")
|
||||
private void endWaitingFor(Guard guard) {
|
||||
int waiters;
|
||||
if ((waiters = --guard.waiterCount) == 0) {
|
||||
Guard p = this.activeGuards;
|
||||
Guard pred = null;
|
||||
while (true) {
|
||||
if (p == guard) {
|
||||
if (pred == null) {
|
||||
this.activeGuards = p.next;
|
||||
} else {
|
||||
pred.next = p.next;
|
||||
}
|
||||
p.next = null;
|
||||
break;
|
||||
}
|
||||
pred = p;
|
||||
p = p.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@GuardedBy(value="lock")
|
||||
private void await(Guard guard, boolean signalBeforeWaiting) throws InterruptedException {
|
||||
if (signalBeforeWaiting) {
|
||||
this.signalNextWaiter();
|
||||
}
|
||||
this.beginWaitingFor(guard);
|
||||
try {
|
||||
do {
|
||||
guard.condition.await();
|
||||
} while (!guard.isSatisfied());
|
||||
}
|
||||
finally {
|
||||
this.endWaitingFor(guard);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@GuardedBy(value="lock")
|
||||
private void awaitUninterruptibly(Guard guard, boolean signalBeforeWaiting) {
|
||||
if (signalBeforeWaiting) {
|
||||
this.signalNextWaiter();
|
||||
}
|
||||
this.beginWaitingFor(guard);
|
||||
try {
|
||||
do {
|
||||
guard.condition.awaitUninterruptibly();
|
||||
} while (!guard.isSatisfied());
|
||||
}
|
||||
finally {
|
||||
this.endWaitingFor(guard);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@GuardedBy(value="lock")
|
||||
private boolean awaitNanos(Guard guard, long nanos, boolean signalBeforeWaiting) throws InterruptedException {
|
||||
if (signalBeforeWaiting) {
|
||||
this.signalNextWaiter();
|
||||
}
|
||||
this.beginWaitingFor(guard);
|
||||
try {
|
||||
do {
|
||||
if (nanos < 0L) {
|
||||
boolean bl = false;
|
||||
return bl;
|
||||
}
|
||||
nanos = guard.condition.awaitNanos(nanos);
|
||||
} while (!guard.isSatisfied());
|
||||
boolean bl = true;
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
this.endWaitingFor(guard);
|
||||
}
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static abstract class Guard {
|
||||
final Monitor monitor;
|
||||
final Condition condition;
|
||||
@GuardedBy(value="monitor.lock")
|
||||
int waiterCount = 0;
|
||||
@GuardedBy(value="monitor.lock")
|
||||
Guard next;
|
||||
|
||||
protected Guard(Monitor monitor) {
|
||||
this.monitor = Preconditions.checkNotNull(monitor, "monitor");
|
||||
this.condition = monitor.lock.newCondition();
|
||||
}
|
||||
|
||||
public abstract boolean isSatisfied();
|
||||
}
|
||||
}
|
632
src/com/google/common/util/concurrent/MoreExecutors.java
Normal file
632
src/com/google/common/util/concurrent/MoreExecutors.java
Normal file
|
@ -0,0 +1,632 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
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.Supplier;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Queues;
|
||||
import com.google.common.util.concurrent.AbstractFuture;
|
||||
import com.google.common.util.concurrent.AbstractListeningExecutorService;
|
||||
import com.google.common.util.concurrent.Callables;
|
||||
import com.google.common.util.concurrent.ForwardingListenableFuture;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListenableFutureTask;
|
||||
import com.google.common.util.concurrent.ListenableScheduledFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.google.common.util.concurrent.WrappingExecutorService;
|
||||
import com.google.common.util.concurrent.WrappingScheduledExecutorService;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
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.Delayed;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
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.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public final class MoreExecutors {
|
||||
private MoreExecutors() {
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
|
||||
return new Application().getExitingExecutorService(executor, terminationTimeout, timeUnit);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
|
||||
return new Application().getExitingScheduledExecutorService(executor, terminationTimeout, timeUnit);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static void addDelayedShutdownHook(ExecutorService service, long terminationTimeout, TimeUnit timeUnit) {
|
||||
new Application().addDelayedShutdownHook(service, terminationTimeout, timeUnit);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor) {
|
||||
return new Application().getExitingExecutorService(executor);
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor) {
|
||||
return new Application().getExitingScheduledExecutorService(executor);
|
||||
}
|
||||
|
||||
private static void useDaemonThreadFactory(ThreadPoolExecutor executor) {
|
||||
executor.setThreadFactory(new ThreadFactoryBuilder().setDaemon(true).setThreadFactory(executor.getThreadFactory()).build());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ListeningExecutorService sameThreadExecutor() {
|
||||
return new DirectExecutorService();
|
||||
}
|
||||
|
||||
public static ListeningExecutorService newDirectExecutorService() {
|
||||
return new DirectExecutorService();
|
||||
}
|
||||
|
||||
public static Executor directExecutor() {
|
||||
return DirectExecutor.INSTANCE;
|
||||
}
|
||||
|
||||
public static ListeningExecutorService listeningDecorator(ExecutorService delegate) {
|
||||
return delegate instanceof ListeningExecutorService ? (ListeningExecutorService)delegate : (delegate instanceof ScheduledExecutorService ? new ScheduledListeningDecorator((ScheduledExecutorService)delegate) : new ListeningDecorator(delegate));
|
||||
}
|
||||
|
||||
public static ListeningScheduledExecutorService listeningDecorator(ScheduledExecutorService delegate) {
|
||||
return delegate instanceof ListeningScheduledExecutorService ? (ListeningScheduledExecutorService)delegate : new ScheduledListeningDecorator(delegate);
|
||||
}
|
||||
|
||||
static <T> T invokeAnyImpl(ListeningExecutorService executorService, Collection<? extends Callable<T>> tasks, boolean timed, long nanos) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
ExecutionException ee;
|
||||
ArrayList<ListenableFuture<T>> futures;
|
||||
block15: {
|
||||
Preconditions.checkNotNull(executorService);
|
||||
int ntasks = tasks.size();
|
||||
Preconditions.checkArgument(ntasks > 0);
|
||||
futures = Lists.newArrayListWithCapacity(ntasks);
|
||||
LinkedBlockingQueue<Future<T>> futureQueue = Queues.newLinkedBlockingQueue();
|
||||
ee = null;
|
||||
long lastTime = timed ? System.nanoTime() : 0L;
|
||||
Iterator<Callable<T>> it = tasks.iterator();
|
||||
futures.add(MoreExecutors.submitAndAddQueueListener(executorService, it.next(), futureQueue));
|
||||
--ntasks;
|
||||
int active = 1;
|
||||
while (true) {
|
||||
Object now22;
|
||||
Future f;
|
||||
if ((f = (Future)futureQueue.poll()) == null) {
|
||||
if (ntasks > 0) {
|
||||
--ntasks;
|
||||
futures.add(MoreExecutors.submitAndAddQueueListener(executorService, it.next(), futureQueue));
|
||||
++active;
|
||||
} else {
|
||||
if (active == 0) break;
|
||||
if (timed) {
|
||||
f = (Future)futureQueue.poll(nanos, TimeUnit.NANOSECONDS);
|
||||
if (f == null) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
long now22 = System.nanoTime();
|
||||
nanos -= now22 - lastTime;
|
||||
lastTime = now22;
|
||||
} else {
|
||||
f = (Future)futureQueue.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f == null) continue;
|
||||
--active;
|
||||
try {
|
||||
now22 = f.get();
|
||||
}
|
||||
catch (ExecutionException eex) {
|
||||
ee = eex;
|
||||
continue;
|
||||
}
|
||||
catch (RuntimeException rex) {
|
||||
ee = new ExecutionException(rex);
|
||||
continue;
|
||||
}
|
||||
return (T)now22;
|
||||
break;
|
||||
}
|
||||
if (ee != null) break block15;
|
||||
ee = new ExecutionException(null);
|
||||
}
|
||||
throw ee;
|
||||
finally {
|
||||
for (Future future : futures) {
|
||||
future.cancel(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.directExecutor());
|
||||
return future;
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static ThreadFactory platformThreadFactory() {
|
||||
if (!MoreExecutors.isAppEngine()) {
|
||||
return Executors.defaultThreadFactory();
|
||||
}
|
||||
try {
|
||||
return (ThreadFactory)Class.forName("com.google.appengine.api.ThreadManager").getMethod("currentRequestThreadFactory", new Class[0]).invoke(null, new Object[0]);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw Throwables.propagate(e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isAppEngine() {
|
||||
if (System.getProperty("com.google.appengine.runtime.environment") == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return Class.forName("com.google.apphosting.api.ApiProxy").getMethod("getCurrentEnvironment", new Class[0]).invoke(null, new Object[0]) != null;
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
return false;
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
return false;
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Thread newThread(String name, Runnable runnable) {
|
||||
Preconditions.checkNotNull(name);
|
||||
Preconditions.checkNotNull(runnable);
|
||||
Thread result = MoreExecutors.platformThreadFactory().newThread(runnable);
|
||||
try {
|
||||
result.setName(name);
|
||||
}
|
||||
catch (SecurityException securityException) {
|
||||
// empty catch block
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static Executor renamingDecorator(final Executor executor, final Supplier<String> nameSupplier) {
|
||||
Preconditions.checkNotNull(executor);
|
||||
Preconditions.checkNotNull(nameSupplier);
|
||||
if (MoreExecutors.isAppEngine()) {
|
||||
return executor;
|
||||
}
|
||||
return new Executor(){
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
executor.execute(Callables.threadRenaming(command, (Supplier<String>)nameSupplier));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static ExecutorService renamingDecorator(ExecutorService service, final Supplier<String> nameSupplier) {
|
||||
Preconditions.checkNotNull(service);
|
||||
Preconditions.checkNotNull(nameSupplier);
|
||||
if (MoreExecutors.isAppEngine()) {
|
||||
return service;
|
||||
}
|
||||
return new WrappingExecutorService(service){
|
||||
|
||||
@Override
|
||||
protected <T> Callable<T> wrapTask(Callable<T> callable) {
|
||||
return Callables.threadRenaming(callable, (Supplier<String>)nameSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Runnable wrapTask(Runnable command) {
|
||||
return Callables.threadRenaming(command, (Supplier<String>)nameSupplier);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static ScheduledExecutorService renamingDecorator(ScheduledExecutorService service, final Supplier<String> nameSupplier) {
|
||||
Preconditions.checkNotNull(service);
|
||||
Preconditions.checkNotNull(nameSupplier);
|
||||
if (MoreExecutors.isAppEngine()) {
|
||||
return service;
|
||||
}
|
||||
return new WrappingScheduledExecutorService(service){
|
||||
|
||||
@Override
|
||||
protected <T> Callable<T> wrapTask(Callable<T> callable) {
|
||||
return Callables.threadRenaming(callable, (Supplier<String>)nameSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Runnable wrapTask(Runnable command) {
|
||||
return Callables.threadRenaming(command, (Supplier<String>)nameSupplier);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static boolean shutdownAndAwaitTermination(ExecutorService service, long timeout, TimeUnit unit) {
|
||||
Preconditions.checkNotNull(unit);
|
||||
service.shutdown();
|
||||
try {
|
||||
long halfTimeoutNanos = TimeUnit.NANOSECONDS.convert(timeout, unit) / 2L;
|
||||
if (!service.awaitTermination(halfTimeoutNanos, TimeUnit.NANOSECONDS)) {
|
||||
service.shutdownNow();
|
||||
service.awaitTermination(halfTimeoutNanos, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
service.shutdownNow();
|
||||
}
|
||||
return service.isTerminated();
|
||||
}
|
||||
|
||||
private static class ScheduledListeningDecorator
|
||||
extends ListeningDecorator
|
||||
implements ListeningScheduledExecutorService {
|
||||
final ScheduledExecutorService delegate;
|
||||
|
||||
ScheduledListeningDecorator(ScheduledExecutorService delegate) {
|
||||
super(delegate);
|
||||
this.delegate = Preconditions.checkNotNull(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
|
||||
ListenableFutureTask<Object> task = ListenableFutureTask.create(command, null);
|
||||
ScheduledFuture<?> scheduled = this.delegate.schedule(task, delay, unit);
|
||||
return new ListenableScheduledTask<Object>(task, scheduled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> ListenableScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
|
||||
ListenableFutureTask<V> task = ListenableFutureTask.create(callable);
|
||||
ScheduledFuture<?> scheduled = this.delegate.schedule(task, delay, unit);
|
||||
return new ListenableScheduledTask<V>(task, scheduled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
|
||||
NeverSuccessfulListenableFutureTask task = new NeverSuccessfulListenableFutureTask(command);
|
||||
ScheduledFuture<?> scheduled = this.delegate.scheduleAtFixedRate(task, initialDelay, period, unit);
|
||||
return new ListenableScheduledTask<Void>(task, scheduled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
|
||||
NeverSuccessfulListenableFutureTask task = new NeverSuccessfulListenableFutureTask(command);
|
||||
ScheduledFuture<?> scheduled = this.delegate.scheduleWithFixedDelay(task, initialDelay, delay, unit);
|
||||
return new ListenableScheduledTask<Void>(task, scheduled);
|
||||
}
|
||||
|
||||
private static final class NeverSuccessfulListenableFutureTask
|
||||
extends AbstractFuture<Void>
|
||||
implements Runnable {
|
||||
private final Runnable delegate;
|
||||
|
||||
public NeverSuccessfulListenableFutureTask(Runnable delegate) {
|
||||
this.delegate = Preconditions.checkNotNull(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
this.delegate.run();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.setException(t);
|
||||
throw Throwables.propagate(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ListenableScheduledTask<V>
|
||||
extends ForwardingListenableFuture.SimpleForwardingListenableFuture<V>
|
||||
implements ListenableScheduledFuture<V> {
|
||||
private final ScheduledFuture<?> scheduledDelegate;
|
||||
|
||||
public ListenableScheduledTask(ListenableFuture<V> listenableDelegate, ScheduledFuture<?> scheduledDelegate) {
|
||||
super(listenableDelegate);
|
||||
this.scheduledDelegate = scheduledDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
boolean cancelled = super.cancel(mayInterruptIfRunning);
|
||||
if (cancelled) {
|
||||
this.scheduledDelegate.cancel(mayInterruptIfRunning);
|
||||
}
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDelay(TimeUnit unit) {
|
||||
return this.scheduledDelegate.getDelay(unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Delayed other) {
|
||||
return this.scheduledDelegate.compareTo(other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ListeningDecorator
|
||||
extends AbstractListeningExecutorService {
|
||||
private final ExecutorService delegate;
|
||||
|
||||
ListeningDecorator(ExecutorService delegate) {
|
||||
this.delegate = Preconditions.checkNotNull(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return this.delegate.awaitTermination(timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
return this.delegate.isShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
return this.delegate.isTerminated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
this.delegate.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
return this.delegate.shutdownNow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
this.delegate.execute(command);
|
||||
}
|
||||
}
|
||||
|
||||
private static enum DirectExecutor implements Executor
|
||||
{
|
||||
INSTANCE;
|
||||
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
command.run();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DirectExecutorService
|
||||
extends AbstractListeningExecutorService {
|
||||
private final Lock lock = new ReentrantLock();
|
||||
private final Condition termination = this.lock.newCondition();
|
||||
private int runningTasks = 0;
|
||||
private boolean shutdown = false;
|
||||
|
||||
private DirectExecutorService() {
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
this.startTask();
|
||||
try {
|
||||
command.run();
|
||||
}
|
||||
finally {
|
||||
this.endTask();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
this.lock.lock();
|
||||
try {
|
||||
boolean bl = this.shutdown;
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void shutdown() {
|
||||
this.lock.lock();
|
||||
try {
|
||||
this.shutdown = true;
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Runnable> shutdownNow() {
|
||||
this.shutdown();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
this.lock.lock();
|
||||
try {
|
||||
boolean bl = this.shutdown && this.runningTasks == 0;
|
||||
return bl;
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
long nanos = unit.toNanos(timeout);
|
||||
this.lock.lock();
|
||||
try {
|
||||
while (true) {
|
||||
if (this.isTerminated()) {
|
||||
boolean bl = true;
|
||||
return bl;
|
||||
}
|
||||
if (nanos <= 0L) {
|
||||
boolean bl = false;
|
||||
return bl;
|
||||
}
|
||||
nanos = this.termination.awaitNanos(nanos);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
private void startTask() {
|
||||
this.lock.lock();
|
||||
try {
|
||||
if (this.isShutdown()) {
|
||||
throw new RejectedExecutionException("Executor already shutdown");
|
||||
}
|
||||
++this.runningTasks;
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
private void endTask() {
|
||||
this.lock.lock();
|
||||
try {
|
||||
--this.runningTasks;
|
||||
if (this.isTerminated()) {
|
||||
this.termination.signalAll();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class Application {
|
||||
Application() {
|
||||
}
|
||||
|
||||
final ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
|
||||
MoreExecutors.useDaemonThreadFactory(executor);
|
||||
ExecutorService service = Executors.unconfigurableExecutorService(executor);
|
||||
this.addDelayedShutdownHook(service, terminationTimeout, timeUnit);
|
||||
return service;
|
||||
}
|
||||
|
||||
final ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) {
|
||||
MoreExecutors.useDaemonThreadFactory(executor);
|
||||
ScheduledExecutorService service = Executors.unconfigurableScheduledExecutorService(executor);
|
||||
this.addDelayedShutdownHook(service, terminationTimeout, timeUnit);
|
||||
return service;
|
||||
}
|
||||
|
||||
final void addDelayedShutdownHook(final ExecutorService service, final long terminationTimeout, final TimeUnit timeUnit) {
|
||||
Preconditions.checkNotNull(service);
|
||||
Preconditions.checkNotNull(timeUnit);
|
||||
String string = String.valueOf(String.valueOf(service));
|
||||
this.addShutdownHook(MoreExecutors.newThread(new StringBuilder(24 + string.length()).append("DelayedShutdownHook-for-").append(string).toString(), new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
service.shutdown();
|
||||
service.awaitTermination(terminationTimeout, timeUnit);
|
||||
}
|
||||
catch (InterruptedException interruptedException) {
|
||||
// empty catch block
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
final ExecutorService getExitingExecutorService(ThreadPoolExecutor executor) {
|
||||
return this.getExitingExecutorService(executor, 120L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor) {
|
||||
return this.getExitingScheduledExecutorService(executor, 120L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void addShutdownHook(Thread hook) {
|
||||
Runtime.getRuntime().addShutdownHook(hook);
|
||||
}
|
||||
}
|
||||
}
|
191
src/com/google/common/util/concurrent/RateLimiter.java
Normal file
191
src/com/google/common/util/concurrent/RateLimiter.java
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
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.Stopwatch;
|
||||
import com.google.common.util.concurrent.SmoothRateLimiter;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
@ThreadSafe
|
||||
@Beta
|
||||
public abstract class RateLimiter {
|
||||
private final SleepingStopwatch stopwatch;
|
||||
private volatile Object mutexDoNotUseDirectly;
|
||||
|
||||
public static RateLimiter create(double permitsPerSecond) {
|
||||
return RateLimiter.create(SleepingStopwatch.createFromSystemTimer(), permitsPerSecond);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static RateLimiter create(SleepingStopwatch stopwatch, double permitsPerSecond) {
|
||||
SmoothRateLimiter.SmoothBursty rateLimiter = new SmoothRateLimiter.SmoothBursty(stopwatch, 1.0);
|
||||
rateLimiter.setRate(permitsPerSecond);
|
||||
return rateLimiter;
|
||||
}
|
||||
|
||||
public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) {
|
||||
Preconditions.checkArgument(warmupPeriod >= 0L, "warmupPeriod must not be negative: %s", warmupPeriod);
|
||||
return RateLimiter.create(SleepingStopwatch.createFromSystemTimer(), permitsPerSecond, warmupPeriod, unit);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static RateLimiter create(SleepingStopwatch stopwatch, double permitsPerSecond, long warmupPeriod, TimeUnit unit) {
|
||||
SmoothRateLimiter.SmoothWarmingUp rateLimiter = new SmoothRateLimiter.SmoothWarmingUp(stopwatch, warmupPeriod, unit);
|
||||
rateLimiter.setRate(permitsPerSecond);
|
||||
return rateLimiter;
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
private Object mutex() {
|
||||
Object mutex = this.mutexDoNotUseDirectly;
|
||||
if (mutex == null) {
|
||||
RateLimiter rateLimiter = this;
|
||||
synchronized (rateLimiter) {
|
||||
mutex = this.mutexDoNotUseDirectly;
|
||||
if (mutex == null) {
|
||||
this.mutexDoNotUseDirectly = mutex = new Object();
|
||||
}
|
||||
}
|
||||
}
|
||||
return mutex;
|
||||
}
|
||||
|
||||
RateLimiter(SleepingStopwatch stopwatch) {
|
||||
this.stopwatch = Preconditions.checkNotNull(stopwatch);
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public final void setRate(double permitsPerSecond) {
|
||||
Preconditions.checkArgument(permitsPerSecond > 0.0 && !Double.isNaN(permitsPerSecond), "rate must be positive");
|
||||
Object object = this.mutex();
|
||||
synchronized (object) {
|
||||
this.doSetRate(permitsPerSecond, this.stopwatch.readMicros());
|
||||
}
|
||||
}
|
||||
|
||||
abstract void doSetRate(double var1, long var3);
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public final double getRate() {
|
||||
Object object = this.mutex();
|
||||
synchronized (object) {
|
||||
return this.doGetRate();
|
||||
}
|
||||
}
|
||||
|
||||
abstract double doGetRate();
|
||||
|
||||
public double acquire() {
|
||||
return this.acquire(1);
|
||||
}
|
||||
|
||||
public double acquire(int permits) {
|
||||
long microsToWait = this.reserve(permits);
|
||||
this.stopwatch.sleepMicrosUninterruptibly(microsToWait);
|
||||
return 1.0 * (double)microsToWait / (double)TimeUnit.SECONDS.toMicros(1L);
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
final long reserve(int permits) {
|
||||
RateLimiter.checkPermits(permits);
|
||||
Object object = this.mutex();
|
||||
synchronized (object) {
|
||||
return this.reserveAndGetWaitLength(permits, this.stopwatch.readMicros());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tryAcquire(long timeout, TimeUnit unit) {
|
||||
return this.tryAcquire(1, timeout, unit);
|
||||
}
|
||||
|
||||
public boolean tryAcquire(int permits) {
|
||||
return this.tryAcquire(permits, 0L, TimeUnit.MICROSECONDS);
|
||||
}
|
||||
|
||||
public boolean tryAcquire() {
|
||||
return this.tryAcquire(1, 0L, TimeUnit.MICROSECONDS);
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) {
|
||||
long microsToWait;
|
||||
long timeoutMicros = Math.max(unit.toMicros(timeout), 0L);
|
||||
RateLimiter.checkPermits(permits);
|
||||
Object object = this.mutex();
|
||||
synchronized (object) {
|
||||
long nowMicros = this.stopwatch.readMicros();
|
||||
if (!this.canAcquire(nowMicros, timeoutMicros)) {
|
||||
return false;
|
||||
}
|
||||
microsToWait = this.reserveAndGetWaitLength(permits, nowMicros);
|
||||
}
|
||||
this.stopwatch.sleepMicrosUninterruptibly(microsToWait);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean canAcquire(long nowMicros, long timeoutMicros) {
|
||||
return this.queryEarliestAvailable(nowMicros) - timeoutMicros <= nowMicros;
|
||||
}
|
||||
|
||||
final long reserveAndGetWaitLength(int permits, long nowMicros) {
|
||||
long momentAvailable = this.reserveEarliestAvailable(permits, nowMicros);
|
||||
return Math.max(momentAvailable - nowMicros, 0L);
|
||||
}
|
||||
|
||||
abstract long queryEarliestAvailable(long var1);
|
||||
|
||||
abstract long reserveEarliestAvailable(int var1, long var2);
|
||||
|
||||
public String toString() {
|
||||
return String.format("RateLimiter[stableRate=%3.1fqps]", this.getRate());
|
||||
}
|
||||
|
||||
private static int checkPermits(int permits) {
|
||||
Preconditions.checkArgument(permits > 0, "Requested permits (%s) must be positive", permits);
|
||||
return permits;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static abstract class SleepingStopwatch {
|
||||
SleepingStopwatch() {
|
||||
}
|
||||
|
||||
abstract long readMicros();
|
||||
|
||||
abstract void sleepMicrosUninterruptibly(long var1);
|
||||
|
||||
static final SleepingStopwatch createFromSystemTimer() {
|
||||
return new SleepingStopwatch(){
|
||||
final Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
|
||||
@Override
|
||||
long readMicros() {
|
||||
return this.stopwatch.elapsed(TimeUnit.MICROSECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
void sleepMicrosUninterruptibly(long micros) {
|
||||
if (micros > 0L) {
|
||||
Uninterruptibles.sleepUninterruptibly(micros, TimeUnit.MICROSECONDS);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
25
src/com/google/common/util/concurrent/Runnables.java
Normal file
25
src/com/google/common/util/concurrent/Runnables.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
|
||||
@Beta
|
||||
@GwtCompatible
|
||||
public final class Runnables {
|
||||
private static final Runnable EMPTY_RUNNABLE = new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
}
|
||||
};
|
||||
|
||||
public static Runnable doNothing() {
|
||||
return EMPTY_RUNNABLE;
|
||||
}
|
||||
|
||||
private Runnables() {
|
||||
}
|
||||
}
|
116
src/com/google/common/util/concurrent/SerializingExecutor.java
Normal file
116
src/com/google/common/util/concurrent/SerializingExecutor.java
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
|
||||
final class SerializingExecutor
|
||||
implements Executor {
|
||||
private static final Logger log = Logger.getLogger(SerializingExecutor.class.getName());
|
||||
private final Executor executor;
|
||||
@GuardedBy(value="internalLock")
|
||||
private final Queue<Runnable> waitQueue = new ArrayDeque<Runnable>();
|
||||
@GuardedBy(value="internalLock")
|
||||
private boolean isThreadScheduled = false;
|
||||
private final TaskRunner taskRunner = new TaskRunner();
|
||||
private final Object internalLock = new Object(){
|
||||
|
||||
public String toString() {
|
||||
String string = String.valueOf(super.toString());
|
||||
return string.length() != 0 ? "SerializingExecutor lock: ".concat(string) : new String("SerializingExecutor lock: ");
|
||||
}
|
||||
};
|
||||
|
||||
public SerializingExecutor(Executor executor) {
|
||||
Preconditions.checkNotNull(executor, "'executor' must not be null.");
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void execute(Runnable r) {
|
||||
Preconditions.checkNotNull(r, "'r' must not be null.");
|
||||
boolean scheduleTaskRunner = false;
|
||||
Object object = this.internalLock;
|
||||
synchronized (object) {
|
||||
this.waitQueue.add(r);
|
||||
if (!this.isThreadScheduled) {
|
||||
this.isThreadScheduled = true;
|
||||
scheduleTaskRunner = true;
|
||||
}
|
||||
}
|
||||
if (scheduleTaskRunner) {
|
||||
boolean threw = true;
|
||||
try {
|
||||
this.executor.execute(this.taskRunner);
|
||||
threw = false;
|
||||
}
|
||||
finally {
|
||||
if (threw) {
|
||||
Object object2 = this.internalLock;
|
||||
synchronized (object2) {
|
||||
this.isThreadScheduled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TaskRunner
|
||||
implements Runnable {
|
||||
private TaskRunner() {
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
block18: {
|
||||
boolean stillRunning = true;
|
||||
block14: while (true) {
|
||||
while (true) {
|
||||
Runnable nextToRun;
|
||||
Preconditions.checkState(SerializingExecutor.this.isThreadScheduled);
|
||||
Object object = SerializingExecutor.this.internalLock;
|
||||
synchronized (object) {
|
||||
nextToRun = (Runnable)SerializingExecutor.this.waitQueue.poll();
|
||||
if (nextToRun == null) {
|
||||
SerializingExecutor.this.isThreadScheduled = false;
|
||||
stillRunning = false;
|
||||
break block18;
|
||||
}
|
||||
}
|
||||
try {
|
||||
nextToRun.run();
|
||||
continue block14;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
String string = String.valueOf(String.valueOf(nextToRun));
|
||||
log.log(Level.SEVERE, new StringBuilder(35 + string.length()).append("Exception while executing runnable ").append(string).toString(), e);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (stillRunning) {
|
||||
Object object = SerializingExecutor.this.internalLock;
|
||||
synchronized (object) {
|
||||
SerializingExecutor.this.isThreadScheduled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
104
src/com/google/common/util/concurrent/Service.java
Normal file
104
src/com/google/common/util/concurrent/Service.java
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Beta
|
||||
public interface Service {
|
||||
public Service startAsync();
|
||||
|
||||
public boolean isRunning();
|
||||
|
||||
public State state();
|
||||
|
||||
public Service stopAsync();
|
||||
|
||||
public void awaitRunning();
|
||||
|
||||
public void awaitRunning(long var1, TimeUnit var3) throws TimeoutException;
|
||||
|
||||
public void awaitTerminated();
|
||||
|
||||
public void awaitTerminated(long var1, TimeUnit var3) throws TimeoutException;
|
||||
|
||||
public Throwable failureCause();
|
||||
|
||||
public void addListener(Listener var1, Executor var2);
|
||||
|
||||
@Beta
|
||||
public static abstract class Listener {
|
||||
public void starting() {
|
||||
}
|
||||
|
||||
public void running() {
|
||||
}
|
||||
|
||||
public void stopping(State from) {
|
||||
}
|
||||
|
||||
public void terminated(State from) {
|
||||
}
|
||||
|
||||
public void failed(State from, Throwable failure) {
|
||||
}
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static enum State {
|
||||
NEW{
|
||||
|
||||
@Override
|
||||
boolean isTerminal() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
,
|
||||
STARTING{
|
||||
|
||||
@Override
|
||||
boolean isTerminal() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
,
|
||||
RUNNING{
|
||||
|
||||
@Override
|
||||
boolean isTerminal() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
,
|
||||
STOPPING{
|
||||
|
||||
@Override
|
||||
boolean isTerminal() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
,
|
||||
TERMINATED{
|
||||
|
||||
@Override
|
||||
boolean isTerminal() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
,
|
||||
FAILED{
|
||||
|
||||
@Override
|
||||
boolean isTerminal() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
abstract boolean isTerminal();
|
||||
}
|
||||
}
|
528
src/com/google/common/util/concurrent/ServiceManager.java
Normal file
528
src/com/google/common/util/concurrent/ServiceManager.java
Normal file
|
@ -0,0 +1,528 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.AbstractService;
|
||||
import com.google.common.util.concurrent.ListenerCallQueue;
|
||||
import com.google.common.util.concurrent.Monitor;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.google.common.util.concurrent.Service;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
|
||||
@Beta
|
||||
public final class ServiceManager {
|
||||
private static final Logger logger = Logger.getLogger(ServiceManager.class.getName());
|
||||
private static final ListenerCallQueue.Callback<Listener> HEALTHY_CALLBACK = new ListenerCallQueue.Callback<Listener>("healthy()"){
|
||||
|
||||
@Override
|
||||
void call(Listener listener) {
|
||||
listener.healthy();
|
||||
}
|
||||
};
|
||||
private static final ListenerCallQueue.Callback<Listener> STOPPED_CALLBACK = new ListenerCallQueue.Callback<Listener>("stopped()"){
|
||||
|
||||
@Override
|
||||
void call(Listener listener) {
|
||||
listener.stopped();
|
||||
}
|
||||
};
|
||||
private final ServiceManagerState state;
|
||||
private final ImmutableList<Service> services;
|
||||
|
||||
public ServiceManager(Iterable<? extends Service> services) {
|
||||
ImmutableList<Service> copy = ImmutableList.copyOf(services);
|
||||
if (copy.isEmpty()) {
|
||||
logger.log(Level.WARNING, "ServiceManager configured with no services. Is your application configured properly?", new EmptyServiceManagerWarning());
|
||||
copy = ImmutableList.of(new NoOpService());
|
||||
}
|
||||
this.state = new ServiceManagerState(copy);
|
||||
this.services = copy;
|
||||
WeakReference<ServiceManagerState> stateReference = new WeakReference<ServiceManagerState>(this.state);
|
||||
for (Service service : copy) {
|
||||
service.addListener(new ServiceListener(service, stateReference), MoreExecutors.directExecutor());
|
||||
Preconditions.checkArgument(service.state() == Service.State.NEW, "Can only manage NEW services, %s", service);
|
||||
}
|
||||
this.state.markReady();
|
||||
}
|
||||
|
||||
public void addListener(Listener listener, Executor executor) {
|
||||
this.state.addListener(listener, executor);
|
||||
}
|
||||
|
||||
public void addListener(Listener listener) {
|
||||
this.state.addListener(listener, MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
public ServiceManager startAsync() {
|
||||
for (Service service : this.services) {
|
||||
Service.State state = service.state();
|
||||
Preconditions.checkState(state == Service.State.NEW, "Service %s is %s, cannot start it.", new Object[]{service, state});
|
||||
}
|
||||
for (Service service : this.services) {
|
||||
try {
|
||||
this.state.tryStartTiming(service);
|
||||
service.startAsync();
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
String string = String.valueOf(String.valueOf(service));
|
||||
logger.log(Level.WARNING, new StringBuilder(24 + string.length()).append("Unable to start Service ").append(string).toString(), e);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public void awaitHealthy() {
|
||||
this.state.awaitHealthy();
|
||||
}
|
||||
|
||||
public void awaitHealthy(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
this.state.awaitHealthy(timeout, unit);
|
||||
}
|
||||
|
||||
public ServiceManager stopAsync() {
|
||||
for (Service service : this.services) {
|
||||
service.stopAsync();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public void awaitStopped() {
|
||||
this.state.awaitStopped();
|
||||
}
|
||||
|
||||
public void awaitStopped(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
this.state.awaitStopped(timeout, unit);
|
||||
}
|
||||
|
||||
public boolean isHealthy() {
|
||||
for (Service service : this.services) {
|
||||
if (service.isRunning()) continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public ImmutableMultimap<Service.State, Service> servicesByState() {
|
||||
return this.state.servicesByState();
|
||||
}
|
||||
|
||||
public ImmutableMap<Service, Long> startupTimes() {
|
||||
return this.state.startupTimes();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(ServiceManager.class).add("services", Collections2.filter(this.services, Predicates.not(Predicates.instanceOf(NoOpService.class)))).toString();
|
||||
}
|
||||
|
||||
private static final class EmptyServiceManagerWarning
|
||||
extends Throwable {
|
||||
private EmptyServiceManagerWarning() {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class NoOpService
|
||||
extends AbstractService {
|
||||
private NoOpService() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() {
|
||||
this.notifyStarted();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
this.notifyStopped();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ServiceListener
|
||||
extends Service.Listener {
|
||||
final Service service;
|
||||
final WeakReference<ServiceManagerState> state;
|
||||
|
||||
ServiceListener(Service service, WeakReference<ServiceManagerState> state) {
|
||||
this.service = service;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void starting() {
|
||||
ServiceManagerState state = (ServiceManagerState)this.state.get();
|
||||
if (state != null) {
|
||||
state.transitionService(this.service, Service.State.NEW, Service.State.STARTING);
|
||||
if (!(this.service instanceof NoOpService)) {
|
||||
logger.log(Level.FINE, "Starting {0}.", this.service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void running() {
|
||||
ServiceManagerState state = (ServiceManagerState)this.state.get();
|
||||
if (state != null) {
|
||||
state.transitionService(this.service, Service.State.STARTING, Service.State.RUNNING);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopping(Service.State from) {
|
||||
ServiceManagerState state = (ServiceManagerState)this.state.get();
|
||||
if (state != null) {
|
||||
state.transitionService(this.service, from, Service.State.STOPPING);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void terminated(Service.State from) {
|
||||
ServiceManagerState state = (ServiceManagerState)this.state.get();
|
||||
if (state != null) {
|
||||
if (!(this.service instanceof NoOpService)) {
|
||||
logger.log(Level.FINE, "Service {0} has terminated. Previous state was: {1}", new Object[]{this.service, from});
|
||||
}
|
||||
state.transitionService(this.service, from, Service.State.TERMINATED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Service.State from, Throwable failure) {
|
||||
ServiceManagerState state = (ServiceManagerState)this.state.get();
|
||||
if (state != null) {
|
||||
if (!(this.service instanceof NoOpService)) {
|
||||
String string = String.valueOf(String.valueOf(this.service));
|
||||
String string2 = String.valueOf(String.valueOf((Object)from));
|
||||
logger.log(Level.SEVERE, new StringBuilder(34 + string.length() + string2.length()).append("Service ").append(string).append(" has failed in the ").append(string2).append(" state.").toString(), failure);
|
||||
}
|
||||
state.transitionService(this.service, from, Service.State.FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ServiceManagerState {
|
||||
final Monitor monitor = new Monitor();
|
||||
@GuardedBy(value="monitor")
|
||||
final SetMultimap<Service.State, Service> servicesByState = Multimaps.newSetMultimap(new EnumMap(Service.State.class), new Supplier<Set<Service>>(){
|
||||
|
||||
@Override
|
||||
public Set<Service> get() {
|
||||
return Sets.newLinkedHashSet();
|
||||
}
|
||||
});
|
||||
@GuardedBy(value="monitor")
|
||||
final Multiset<Service.State> states = this.servicesByState.keys();
|
||||
@GuardedBy(value="monitor")
|
||||
final Map<Service, Stopwatch> startupTimers = Maps.newIdentityHashMap();
|
||||
@GuardedBy(value="monitor")
|
||||
boolean ready;
|
||||
@GuardedBy(value="monitor")
|
||||
boolean transitioned;
|
||||
final int numberOfServices;
|
||||
final Monitor.Guard awaitHealthGuard = new Monitor.Guard(this.monitor){
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return ServiceManagerState.this.states.count((Object)Service.State.RUNNING) == ServiceManagerState.this.numberOfServices || ServiceManagerState.this.states.contains((Object)Service.State.STOPPING) || ServiceManagerState.this.states.contains((Object)Service.State.TERMINATED) || ServiceManagerState.this.states.contains((Object)Service.State.FAILED);
|
||||
}
|
||||
};
|
||||
final Monitor.Guard stoppedGuard = new Monitor.Guard(this.monitor){
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return ServiceManagerState.this.states.count((Object)Service.State.TERMINATED) + ServiceManagerState.this.states.count((Object)Service.State.FAILED) == ServiceManagerState.this.numberOfServices;
|
||||
}
|
||||
};
|
||||
@GuardedBy(value="monitor")
|
||||
final List<ListenerCallQueue<Listener>> listeners = Collections.synchronizedList(new ArrayList());
|
||||
|
||||
ServiceManagerState(ImmutableCollection<Service> services) {
|
||||
this.numberOfServices = services.size();
|
||||
this.servicesByState.putAll(Service.State.NEW, services);
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
void tryStartTiming(Service service) {
|
||||
this.monitor.enter();
|
||||
try {
|
||||
Stopwatch stopwatch = this.startupTimers.get(service);
|
||||
if (stopwatch == null) {
|
||||
this.startupTimers.put(service, Stopwatch.createStarted());
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
void markReady() {
|
||||
block5: {
|
||||
this.monitor.enter();
|
||||
try {
|
||||
if (!this.transitioned) {
|
||||
this.ready = true;
|
||||
break block5;
|
||||
}
|
||||
ArrayList<Service> servicesInBadStates = Lists.newArrayList();
|
||||
for (Service service : this.servicesByState().values()) {
|
||||
if (service.state() == Service.State.NEW) continue;
|
||||
servicesInBadStates.add(service);
|
||||
}
|
||||
String string = String.valueOf(String.valueOf("Services started transitioning asynchronously before the ServiceManager was constructed: "));
|
||||
String string2 = String.valueOf(String.valueOf(servicesInBadStates));
|
||||
throw new IllegalArgumentException(new StringBuilder(0 + string.length() + string2.length()).append(string).append(string2).toString());
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
void addListener(Listener listener, Executor executor) {
|
||||
Preconditions.checkNotNull(listener, "listener");
|
||||
Preconditions.checkNotNull(executor, "executor");
|
||||
this.monitor.enter();
|
||||
try {
|
||||
if (!this.stoppedGuard.isSatisfied()) {
|
||||
this.listeners.add(new ListenerCallQueue<Listener>(listener, executor));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
void awaitHealthy() {
|
||||
this.monitor.enterWhenUninterruptibly(this.awaitHealthGuard);
|
||||
try {
|
||||
this.checkHealthy();
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
void awaitHealthy(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
this.monitor.enter();
|
||||
try {
|
||||
if (!this.monitor.waitForUninterruptibly(this.awaitHealthGuard, timeout, unit)) {
|
||||
String string = String.valueOf(String.valueOf("Timeout waiting for the services to become healthy. The following services have not started: "));
|
||||
String string2 = String.valueOf(String.valueOf(Multimaps.filterKeys(this.servicesByState, Predicates.in(ImmutableSet.of(Service.State.NEW, Service.State.STARTING)))));
|
||||
throw new TimeoutException(new StringBuilder(0 + string.length() + string2.length()).append(string).append(string2).toString());
|
||||
}
|
||||
this.checkHealthy();
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
}
|
||||
|
||||
void awaitStopped() {
|
||||
this.monitor.enterWhenUninterruptibly(this.stoppedGuard);
|
||||
this.monitor.leave();
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
void awaitStopped(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
this.monitor.enter();
|
||||
try {
|
||||
if (!this.monitor.waitForUninterruptibly(this.stoppedGuard, timeout, unit)) {
|
||||
String string = String.valueOf(String.valueOf("Timeout waiting for the services to stop. The following services have not stopped: "));
|
||||
String string2 = String.valueOf(String.valueOf(Multimaps.filterKeys(this.servicesByState, Predicates.not(Predicates.in(ImmutableSet.of(Service.State.TERMINATED, Service.State.FAILED))))));
|
||||
throw new TimeoutException(new StringBuilder(0 + string.length() + string2.length()).append(string).append(string2).toString());
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
ImmutableMultimap<Service.State, Service> servicesByState() {
|
||||
ImmutableSetMultimap.Builder builder = ImmutableSetMultimap.builder();
|
||||
this.monitor.enter();
|
||||
try {
|
||||
for (Map.Entry<Service.State, Service> entry : this.servicesByState.entries()) {
|
||||
if (entry.getValue() instanceof NoOpService) continue;
|
||||
builder.put((Object)entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
ImmutableMap<Service, Long> startupTimes() {
|
||||
ArrayList<Map.Entry<Service, Long>> loadTimes;
|
||||
this.monitor.enter();
|
||||
try {
|
||||
loadTimes = Lists.newArrayListWithCapacity(this.startupTimers.size());
|
||||
for (Map.Entry<Service, Stopwatch> entry : this.startupTimers.entrySet()) {
|
||||
Service service = entry.getKey();
|
||||
Stopwatch stopWatch = entry.getValue();
|
||||
if (stopWatch.isRunning() || service instanceof NoOpService) continue;
|
||||
loadTimes.add(Maps.immutableEntry(service, stopWatch.elapsed(TimeUnit.MILLISECONDS)));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
}
|
||||
Collections.sort(loadTimes, Ordering.natural().onResultOf(new Function<Map.Entry<Service, Long>, Long>(){
|
||||
|
||||
@Override
|
||||
public Long apply(Map.Entry<Service, Long> input) {
|
||||
return input.getValue();
|
||||
}
|
||||
}));
|
||||
ImmutableMap.Builder builder = ImmutableMap.builder();
|
||||
for (Map.Entry entry : loadTimes) {
|
||||
builder.put(entry);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
void transitionService(Service service, Service.State from, Service.State to) {
|
||||
Preconditions.checkNotNull(service);
|
||||
Preconditions.checkArgument(from != to);
|
||||
this.monitor.enter();
|
||||
try {
|
||||
this.transitioned = true;
|
||||
if (!this.ready) {
|
||||
return;
|
||||
}
|
||||
Preconditions.checkState(this.servicesByState.remove((Object)from, service), "Service %s not at the expected location in the state map %s", new Object[]{service, from});
|
||||
Preconditions.checkState(this.servicesByState.put(to, service), "Service %s in the state map unexpectedly at %s", new Object[]{service, to});
|
||||
Stopwatch stopwatch = this.startupTimers.get(service);
|
||||
if (stopwatch == null) {
|
||||
stopwatch = Stopwatch.createStarted();
|
||||
this.startupTimers.put(service, stopwatch);
|
||||
}
|
||||
if (to.compareTo(Service.State.RUNNING) >= 0 && stopwatch.isRunning()) {
|
||||
stopwatch.stop();
|
||||
if (!(service instanceof NoOpService)) {
|
||||
logger.log(Level.FINE, "Started {0} in {1}.", new Object[]{service, stopwatch});
|
||||
}
|
||||
}
|
||||
if (to == Service.State.FAILED) {
|
||||
this.fireFailedListeners(service);
|
||||
}
|
||||
if (this.states.count((Object)Service.State.RUNNING) == this.numberOfServices) {
|
||||
this.fireHealthyListeners();
|
||||
} else if (this.states.count((Object)Service.State.TERMINATED) + this.states.count((Object)Service.State.FAILED) == this.numberOfServices) {
|
||||
this.fireStoppedListeners();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.monitor.leave();
|
||||
this.executeListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="monitor")
|
||||
void fireStoppedListeners() {
|
||||
STOPPED_CALLBACK.enqueueOn(this.listeners);
|
||||
}
|
||||
|
||||
@GuardedBy(value="monitor")
|
||||
void fireHealthyListeners() {
|
||||
HEALTHY_CALLBACK.enqueueOn(this.listeners);
|
||||
}
|
||||
|
||||
@GuardedBy(value="monitor")
|
||||
void fireFailedListeners(final Service service) {
|
||||
String string = String.valueOf(String.valueOf(service));
|
||||
new ListenerCallQueue.Callback<Listener>(new StringBuilder(18 + string.length()).append("failed({service=").append(string).append("})").toString()){
|
||||
|
||||
@Override
|
||||
void call(Listener listener) {
|
||||
listener.failure(service);
|
||||
}
|
||||
}.enqueueOn(this.listeners);
|
||||
}
|
||||
|
||||
void executeListeners() {
|
||||
Preconditions.checkState(!this.monitor.isOccupiedByCurrentThread(), "It is incorrect to execute listeners with the monitor held.");
|
||||
for (int i = 0; i < this.listeners.size(); ++i) {
|
||||
this.listeners.get(i).execute();
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy(value="monitor")
|
||||
void checkHealthy() {
|
||||
if (this.states.count((Object)Service.State.RUNNING) != this.numberOfServices) {
|
||||
String string = String.valueOf(String.valueOf(Multimaps.filterKeys(this.servicesByState, Predicates.not(Predicates.equalTo(Service.State.RUNNING)))));
|
||||
IllegalStateException exception = new IllegalStateException(new StringBuilder(79 + string.length()).append("Expected to be healthy after starting. The following services are not running: ").append(string).toString());
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Beta
|
||||
public static abstract class Listener {
|
||||
public void healthy() {
|
||||
}
|
||||
|
||||
public void stopped() {
|
||||
}
|
||||
|
||||
public void failure(Service service) {
|
||||
}
|
||||
}
|
||||
}
|
27
src/com/google/common/util/concurrent/SettableFuture.java
Normal file
27
src/com/google/common/util/concurrent/SettableFuture.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.util.concurrent.AbstractFuture;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class SettableFuture<V>
|
||||
extends AbstractFuture<V> {
|
||||
public static <V> SettableFuture<V> create() {
|
||||
return new SettableFuture<V>();
|
||||
}
|
||||
|
||||
private SettableFuture() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean set(@Nullable V value) {
|
||||
return super.set(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setException(Throwable throwable) {
|
||||
return super.setException(throwable);
|
||||
}
|
||||
}
|
137
src/com/google/common/util/concurrent/SimpleTimeLimiter.java
Normal file
137
src/com/google/common/util/concurrent/SimpleTimeLimiter.java
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.TimeLimiter;
|
||||
import com.google.common.util.concurrent.UncheckedTimeoutException;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.HashSet;
|
||||
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;
|
||||
|
||||
@Beta
|
||||
public final class SimpleTimeLimiter
|
||||
implements TimeLimiter {
|
||||
private final ExecutorService executor;
|
||||
|
||||
public SimpleTimeLimiter(ExecutorService executor) {
|
||||
this.executor = Preconditions.checkNotNull(executor);
|
||||
}
|
||||
|
||||
public SimpleTimeLimiter() {
|
||||
this(Executors.newCachedThreadPool());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T newProxy(final T target, Class<T> interfaceType, final long timeoutDuration, final TimeUnit timeoutUnit) {
|
||||
Preconditions.checkNotNull(target);
|
||||
Preconditions.checkNotNull(interfaceType);
|
||||
Preconditions.checkNotNull(timeoutUnit);
|
||||
Preconditions.checkArgument(timeoutDuration > 0L, "bad timeout: %s", timeoutDuration);
|
||||
Preconditions.checkArgument(interfaceType.isInterface(), "interfaceType must be an interface type");
|
||||
final Set<Method> interruptibleMethods = SimpleTimeLimiter.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) {
|
||||
SimpleTimeLimiter.throwCause(e, false);
|
||||
throw new AssertionError((Object)"can't get here");
|
||||
}
|
||||
}
|
||||
};
|
||||
return SimpleTimeLimiter.this.callWithTimeout(callable, timeoutDuration, timeoutUnit, interruptibleMethods.contains(method));
|
||||
}
|
||||
};
|
||||
return SimpleTimeLimiter.newProxy(interfaceType, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T callWithTimeout(Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit, boolean amInterruptible) throws Exception {
|
||||
Preconditions.checkNotNull(callable);
|
||||
Preconditions.checkNotNull(timeoutUnit);
|
||||
Preconditions.checkArgument(timeoutDuration > 0L, "timeout must be positive: %s", timeoutDuration);
|
||||
Future<T> future = this.executor.submit(callable);
|
||||
try {
|
||||
if (amInterruptible) {
|
||||
try {
|
||||
return future.get(timeoutDuration, timeoutUnit);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
future.cancel(true);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return Uninterruptibles.getUninterruptibly(future, timeoutDuration, timeoutUnit);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
throw SimpleTimeLimiter.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;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
private static Set<Method> findInterruptibleMethods(Class<?> interfaceType) {
|
||||
HashSet<Method> set = Sets.newHashSet();
|
||||
for (Method m : interfaceType.getMethods()) {
|
||||
if (!SimpleTimeLimiter.declaresInterruptedEx(m)) continue;
|
||||
set.add(m);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
private static boolean declaresInterruptedEx(Method method) {
|
||||
for (Class<?> exType : method.getExceptionTypes()) {
|
||||
if (exType != InterruptedException.class) continue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static <T> T newProxy(Class<T> interfaceType, InvocationHandler handler) {
|
||||
Object object = Proxy.newProxyInstance(interfaceType.getClassLoader(), new Class[]{interfaceType}, handler);
|
||||
return interfaceType.cast(object);
|
||||
}
|
||||
}
|
121
src/com/google/common/util/concurrent/SmoothRateLimiter.java
Normal file
121
src/com/google/common/util/concurrent/SmoothRateLimiter.java
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.util.concurrent.RateLimiter;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
abstract class SmoothRateLimiter
|
||||
extends RateLimiter {
|
||||
double storedPermits;
|
||||
double maxPermits;
|
||||
double stableIntervalMicros;
|
||||
private long nextFreeTicketMicros = 0L;
|
||||
|
||||
private SmoothRateLimiter(RateLimiter.SleepingStopwatch stopwatch) {
|
||||
super(stopwatch);
|
||||
}
|
||||
|
||||
@Override
|
||||
final void doSetRate(double permitsPerSecond, long nowMicros) {
|
||||
double stableIntervalMicros;
|
||||
this.resync(nowMicros);
|
||||
this.stableIntervalMicros = stableIntervalMicros = (double)TimeUnit.SECONDS.toMicros(1L) / permitsPerSecond;
|
||||
this.doSetRate(permitsPerSecond, stableIntervalMicros);
|
||||
}
|
||||
|
||||
abstract void doSetRate(double var1, double var3);
|
||||
|
||||
@Override
|
||||
final double doGetRate() {
|
||||
return (double)TimeUnit.SECONDS.toMicros(1L) / this.stableIntervalMicros;
|
||||
}
|
||||
|
||||
@Override
|
||||
final long queryEarliestAvailable(long nowMicros) {
|
||||
return this.nextFreeTicketMicros;
|
||||
}
|
||||
|
||||
@Override
|
||||
final long reserveEarliestAvailable(int requiredPermits, long nowMicros) {
|
||||
this.resync(nowMicros);
|
||||
long returnValue = this.nextFreeTicketMicros;
|
||||
double storedPermitsToSpend = Math.min((double)requiredPermits, this.storedPermits);
|
||||
double freshPermits = (double)requiredPermits - storedPermitsToSpend;
|
||||
long waitMicros = this.storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend) + (long)(freshPermits * this.stableIntervalMicros);
|
||||
this.nextFreeTicketMicros += waitMicros;
|
||||
this.storedPermits -= storedPermitsToSpend;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
abstract long storedPermitsToWaitTime(double var1, double var3);
|
||||
|
||||
private void resync(long nowMicros) {
|
||||
if (nowMicros > this.nextFreeTicketMicros) {
|
||||
this.storedPermits = Math.min(this.maxPermits, this.storedPermits + (double)(nowMicros - this.nextFreeTicketMicros) / this.stableIntervalMicros);
|
||||
this.nextFreeTicketMicros = nowMicros;
|
||||
}
|
||||
}
|
||||
|
||||
static final class SmoothBursty
|
||||
extends SmoothRateLimiter {
|
||||
final double maxBurstSeconds;
|
||||
|
||||
SmoothBursty(RateLimiter.SleepingStopwatch stopwatch, double maxBurstSeconds) {
|
||||
super(stopwatch);
|
||||
this.maxBurstSeconds = maxBurstSeconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetRate(double permitsPerSecond, double stableIntervalMicros) {
|
||||
double oldMaxPermits = this.maxPermits;
|
||||
this.maxPermits = this.maxBurstSeconds * permitsPerSecond;
|
||||
this.storedPermits = oldMaxPermits == Double.POSITIVE_INFINITY ? this.maxPermits : (oldMaxPermits == 0.0 ? 0.0 : this.storedPermits * this.maxPermits / oldMaxPermits);
|
||||
}
|
||||
|
||||
@Override
|
||||
long storedPermitsToWaitTime(double storedPermits, double permitsToTake) {
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
static final class SmoothWarmingUp
|
||||
extends SmoothRateLimiter {
|
||||
private final long warmupPeriodMicros;
|
||||
private double slope;
|
||||
private double halfPermits;
|
||||
|
||||
SmoothWarmingUp(RateLimiter.SleepingStopwatch stopwatch, long warmupPeriod, TimeUnit timeUnit) {
|
||||
super(stopwatch);
|
||||
this.warmupPeriodMicros = timeUnit.toMicros(warmupPeriod);
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetRate(double permitsPerSecond, double stableIntervalMicros) {
|
||||
double oldMaxPermits = this.maxPermits;
|
||||
this.maxPermits = (double)this.warmupPeriodMicros / stableIntervalMicros;
|
||||
this.halfPermits = this.maxPermits / 2.0;
|
||||
double coldIntervalMicros = stableIntervalMicros * 3.0;
|
||||
this.slope = (coldIntervalMicros - stableIntervalMicros) / this.halfPermits;
|
||||
this.storedPermits = oldMaxPermits == Double.POSITIVE_INFINITY ? 0.0 : (oldMaxPermits == 0.0 ? this.maxPermits : this.storedPermits * this.maxPermits / oldMaxPermits);
|
||||
}
|
||||
|
||||
@Override
|
||||
long storedPermitsToWaitTime(double storedPermits, double permitsToTake) {
|
||||
double availablePermitsAboveHalf = storedPermits - this.halfPermits;
|
||||
long micros = 0L;
|
||||
if (availablePermitsAboveHalf > 0.0) {
|
||||
double permitsAboveHalfToTake = Math.min(availablePermitsAboveHalf, permitsToTake);
|
||||
micros = (long)(permitsAboveHalfToTake * (this.permitsToTime(availablePermitsAboveHalf) + this.permitsToTime(availablePermitsAboveHalf - permitsAboveHalfToTake)) / 2.0);
|
||||
permitsToTake -= permitsAboveHalfToTake;
|
||||
}
|
||||
micros = (long)((double)micros + this.stableIntervalMicros * permitsToTake);
|
||||
return micros;
|
||||
}
|
||||
|
||||
private double permitsToTime(double permits) {
|
||||
return this.stableIntervalMicros + permits * this.slope;
|
||||
}
|
||||
}
|
||||
}
|
301
src/com/google/common/util/concurrent/Striped.java
Normal file
301
src/com/google/common/util/concurrent/Striped.java
Normal file
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.common.math.IntMath;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
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.atomic.AtomicReferenceArray;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
@Beta
|
||||
public abstract class Striped<L> {
|
||||
private static final int LARGE_LAZY_CUTOFF = 1024;
|
||||
private static final Supplier<ReadWriteLock> READ_WRITE_LOCK_SUPPLIER = new Supplier<ReadWriteLock>(){
|
||||
|
||||
@Override
|
||||
public ReadWriteLock get() {
|
||||
return new ReentrantReadWriteLock();
|
||||
}
|
||||
};
|
||||
private static final int ALL_SET = -1;
|
||||
|
||||
private Striped() {
|
||||
}
|
||||
|
||||
public abstract L get(Object var1);
|
||||
|
||||
public abstract L getAt(int var1);
|
||||
|
||||
abstract int indexFor(Object var1);
|
||||
|
||||
public abstract int size();
|
||||
|
||||
public Iterable<L> bulkGet(Iterable<?> keys) {
|
||||
Object[] array = Iterables.toArray(keys, Object.class);
|
||||
if (array.length == 0) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
int[] stripes = new int[array.length];
|
||||
for (int i = 0; i < array.length; ++i) {
|
||||
stripes[i] = this.indexFor(array[i]);
|
||||
}
|
||||
Arrays.sort(stripes);
|
||||
int previousStripe = stripes[0];
|
||||
array[0] = this.getAt(previousStripe);
|
||||
for (int i = 1; i < array.length; ++i) {
|
||||
int currentStripe = stripes[i];
|
||||
if (currentStripe == previousStripe) {
|
||||
array[i] = array[i - 1];
|
||||
continue;
|
||||
}
|
||||
array[i] = this.getAt(currentStripe);
|
||||
previousStripe = currentStripe;
|
||||
}
|
||||
List<Object> asList = Arrays.asList(array);
|
||||
return Collections.unmodifiableList(asList);
|
||||
}
|
||||
|
||||
public static Striped<Lock> lock(int stripes) {
|
||||
return new CompactStriped<Lock>(stripes, new Supplier<Lock>(){
|
||||
|
||||
@Override
|
||||
public Lock get() {
|
||||
return new PaddedLock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Striped<Lock> lazyWeakLock(int stripes) {
|
||||
return Striped.lazy(stripes, new Supplier<Lock>(){
|
||||
|
||||
@Override
|
||||
public Lock get() {
|
||||
return new ReentrantLock(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static <L> Striped<L> lazy(int stripes, Supplier<L> supplier) {
|
||||
return stripes < 1024 ? new SmallLazyStriped<L>(stripes, supplier) : new LargeLazyStriped<L>(stripes, supplier);
|
||||
}
|
||||
|
||||
public static Striped<Semaphore> semaphore(int stripes, final int permits) {
|
||||
return new CompactStriped<Semaphore>(stripes, new Supplier<Semaphore>(){
|
||||
|
||||
@Override
|
||||
public Semaphore get() {
|
||||
return new PaddedSemaphore(permits);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Striped<Semaphore> lazyWeakSemaphore(int stripes, final int permits) {
|
||||
return Striped.lazy(stripes, new Supplier<Semaphore>(){
|
||||
|
||||
@Override
|
||||
public Semaphore get() {
|
||||
return new Semaphore(permits, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Striped<ReadWriteLock> readWriteLock(int stripes) {
|
||||
return new CompactStriped<ReadWriteLock>(stripes, READ_WRITE_LOCK_SUPPLIER);
|
||||
}
|
||||
|
||||
public static Striped<ReadWriteLock> lazyWeakReadWriteLock(int stripes) {
|
||||
return Striped.lazy(stripes, READ_WRITE_LOCK_SUPPLIER);
|
||||
}
|
||||
|
||||
private static int ceilToPowerOfTwo(int x) {
|
||||
return 1 << IntMath.log2(x, RoundingMode.CEILING);
|
||||
}
|
||||
|
||||
private static int smear(int hashCode) {
|
||||
hashCode ^= hashCode >>> 20 ^ hashCode >>> 12;
|
||||
return hashCode ^ hashCode >>> 7 ^ hashCode >>> 4;
|
||||
}
|
||||
|
||||
private static class PaddedSemaphore
|
||||
extends Semaphore {
|
||||
long q1;
|
||||
long q2;
|
||||
long q3;
|
||||
|
||||
PaddedSemaphore(int permits) {
|
||||
super(permits, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PaddedLock
|
||||
extends ReentrantLock {
|
||||
long q1;
|
||||
long q2;
|
||||
long q3;
|
||||
|
||||
PaddedLock() {
|
||||
super(false);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class LargeLazyStriped<L>
|
||||
extends PowerOfTwoStriped<L> {
|
||||
final ConcurrentMap<Integer, L> locks;
|
||||
final Supplier<L> supplier;
|
||||
final int size;
|
||||
|
||||
LargeLazyStriped(int stripes, Supplier<L> supplier) {
|
||||
super(stripes);
|
||||
this.size = this.mask == -1 ? Integer.MAX_VALUE : this.mask + 1;
|
||||
this.supplier = supplier;
|
||||
this.locks = new MapMaker().weakValues().makeMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public L getAt(int index) {
|
||||
Object existing;
|
||||
if (this.size != Integer.MAX_VALUE) {
|
||||
Preconditions.checkElementIndex(index, this.size());
|
||||
}
|
||||
if ((existing = this.locks.get(index)) != null) {
|
||||
return (L)existing;
|
||||
}
|
||||
L created = this.supplier.get();
|
||||
existing = this.locks.putIfAbsent(index, created);
|
||||
return (L)MoreObjects.firstNonNull(existing, created);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return this.size;
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class SmallLazyStriped<L>
|
||||
extends PowerOfTwoStriped<L> {
|
||||
final AtomicReferenceArray<ArrayReference<? extends L>> locks;
|
||||
final Supplier<L> supplier;
|
||||
final int size;
|
||||
final ReferenceQueue<L> queue = new ReferenceQueue();
|
||||
|
||||
SmallLazyStriped(int stripes, Supplier<L> supplier) {
|
||||
super(stripes);
|
||||
this.size = this.mask == -1 ? Integer.MAX_VALUE : this.mask + 1;
|
||||
this.locks = new AtomicReferenceArray(this.size);
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public L getAt(int index) {
|
||||
ArrayReference<? extends L> existingRef;
|
||||
L existing;
|
||||
if (this.size != Integer.MAX_VALUE) {
|
||||
Preconditions.checkElementIndex(index, this.size());
|
||||
}
|
||||
L l = existing = (existingRef = this.locks.get(index)) == null ? null : (L)existingRef.get();
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
L created = this.supplier.get();
|
||||
ArrayReference<L> newRef = new ArrayReference<L>(created, index, this.queue);
|
||||
while (!this.locks.compareAndSet(index, existingRef, newRef)) {
|
||||
existingRef = this.locks.get(index);
|
||||
existing = existingRef == null ? null : (L)existingRef.get();
|
||||
if (existing == null) continue;
|
||||
return existing;
|
||||
}
|
||||
this.drainQueue();
|
||||
return created;
|
||||
}
|
||||
|
||||
private void drainQueue() {
|
||||
Reference<L> ref;
|
||||
while ((ref = this.queue.poll()) != null) {
|
||||
ArrayReference arrayRef = (ArrayReference)ref;
|
||||
this.locks.compareAndSet(arrayRef.index, arrayRef, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
private static final class ArrayReference<L>
|
||||
extends WeakReference<L> {
|
||||
final int index;
|
||||
|
||||
ArrayReference(L referent, int index, ReferenceQueue<L> queue) {
|
||||
super(referent, queue);
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class CompactStriped<L>
|
||||
extends PowerOfTwoStriped<L> {
|
||||
private final Object[] array;
|
||||
|
||||
private CompactStriped(int stripes, Supplier<L> supplier) {
|
||||
super(stripes);
|
||||
Preconditions.checkArgument(stripes <= 0x40000000, "Stripes must be <= 2^30)");
|
||||
this.array = new Object[this.mask + 1];
|
||||
for (int i = 0; i < this.array.length; ++i) {
|
||||
this.array[i] = supplier.get();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public L getAt(int index) {
|
||||
return (L)this.array[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return this.array.length;
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class PowerOfTwoStriped<L>
|
||||
extends Striped<L> {
|
||||
final int mask;
|
||||
|
||||
PowerOfTwoStriped(int stripes) {
|
||||
Preconditions.checkArgument(stripes > 0, "Stripes must be positive");
|
||||
this.mask = stripes > 0x40000000 ? -1 : Striped.ceilToPowerOfTwo(stripes) - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
final int indexFor(Object key) {
|
||||
int hash = Striped.smear(key.hashCode());
|
||||
return hash & this.mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final L get(Object key) {
|
||||
return this.getAt(this.indexFor(key));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public final class ThreadFactoryBuilder {
|
||||
private String nameFormat = null;
|
||||
private Boolean daemon = null;
|
||||
private Integer priority = null;
|
||||
private Thread.UncaughtExceptionHandler uncaughtExceptionHandler = null;
|
||||
private ThreadFactory backingThreadFactory = null;
|
||||
|
||||
public ThreadFactoryBuilder setNameFormat(String nameFormat) {
|
||||
String.format(nameFormat, 0);
|
||||
this.nameFormat = nameFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThreadFactoryBuilder setDaemon(boolean daemon) {
|
||||
this.daemon = daemon;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThreadFactoryBuilder setPriority(int priority) {
|
||||
Preconditions.checkArgument(priority >= 1, "Thread priority (%s) must be >= %s", priority, 1);
|
||||
Preconditions.checkArgument(priority <= 10, "Thread priority (%s) must be <= %s", priority, 10);
|
||||
this.priority = priority;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThreadFactoryBuilder setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
|
||||
this.uncaughtExceptionHandler = Preconditions.checkNotNull(uncaughtExceptionHandler);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThreadFactoryBuilder setThreadFactory(ThreadFactory backingThreadFactory) {
|
||||
this.backingThreadFactory = Preconditions.checkNotNull(backingThreadFactory);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThreadFactory build() {
|
||||
return ThreadFactoryBuilder.build(this);
|
||||
}
|
||||
|
||||
private static ThreadFactory build(ThreadFactoryBuilder builder) {
|
||||
final String nameFormat = builder.nameFormat;
|
||||
final Boolean daemon = builder.daemon;
|
||||
final Integer priority = builder.priority;
|
||||
final Thread.UncaughtExceptionHandler uncaughtExceptionHandler = builder.uncaughtExceptionHandler;
|
||||
final ThreadFactory backingThreadFactory = builder.backingThreadFactory != null ? builder.backingThreadFactory : Executors.defaultThreadFactory();
|
||||
final AtomicLong count = nameFormat != null ? new AtomicLong(0L) : 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
15
src/com/google/common/util/concurrent/TimeLimiter.java
Normal file
15
src/com/google/common/util/concurrent/TimeLimiter.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Beta
|
||||
public interface TimeLimiter {
|
||||
public <T> T newProxy(T var1, Class<T> var2, long var3, TimeUnit var5);
|
||||
|
||||
public <T> T callWithTimeout(Callable<T> var1, long var2, TimeUnit var4, boolean var5) throws Exception;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public final class UncaughtExceptionHandlers {
|
||||
private UncaughtExceptionHandlers() {
|
||||
}
|
||||
|
||||
public static Thread.UncaughtExceptionHandler systemExit() {
|
||||
return new Exiter(Runtime.getRuntime());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static final class Exiter
|
||||
implements Thread.UncaughtExceptionHandler {
|
||||
private static final Logger logger = Logger.getLogger(Exiter.class.getName());
|
||||
private final Runtime runtime;
|
||||
|
||||
Exiter(Runtime runtime) {
|
||||
this.runtime = runtime;
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
logger.log(Level.SEVERE, String.format("Caught an exception in %s. Shutting down.", t), e);
|
||||
}
|
||||
catch (Throwable errorInLogging) {
|
||||
System.err.println(e.getMessage());
|
||||
System.err.println(errorInLogging.getMessage());
|
||||
}
|
||||
finally {
|
||||
this.runtime.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.annotations.GwtCompatible;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@GwtCompatible
|
||||
public class UncheckedExecutionException
|
||||
extends RuntimeException {
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
protected UncheckedExecutionException() {
|
||||
}
|
||||
|
||||
protected UncheckedExecutionException(@Nullable String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UncheckedExecutionException(@Nullable String message, @Nullable Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public UncheckedExecutionException(@Nullable Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class UncheckedTimeoutException
|
||||
extends RuntimeException {
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
public UncheckedTimeoutException() {
|
||||
}
|
||||
|
||||
public UncheckedTimeoutException(@Nullable String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UncheckedTimeoutException(@Nullable Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public UncheckedTimeoutException(@Nullable String message, @Nullable Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
250
src/com/google/common/util/concurrent/Uninterruptibles.java
Normal file
250
src/com/google/common/util/concurrent/Uninterruptibles.java
Normal file
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
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.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Beta
|
||||
public final class Uninterruptibles {
|
||||
public static void awaitUninterruptibly(CountDownLatch latch) {
|
||||
boolean interrupted = false;
|
||||
while (true) {
|
||||
try {
|
||||
latch.await();
|
||||
return;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
boolean bl = latch.await(remainingNanos, TimeUnit.NANOSECONDS);
|
||||
return bl;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
remainingNanos = end - System.nanoTime();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void joinUninterruptibly(Thread toJoin) {
|
||||
boolean interrupted = false;
|
||||
while (true) {
|
||||
try {
|
||||
toJoin.join();
|
||||
return;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <V> V getUninterruptibly(Future<V> future) throws ExecutionException {
|
||||
boolean interrupted = false;
|
||||
while (true) {
|
||||
try {
|
||||
V v = future.get();
|
||||
return v;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
V v;
|
||||
try {
|
||||
v = future.get(remainingNanos, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
remainingNanos = end - System.nanoTime();
|
||||
continue;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.NANOSECONDS.timedJoin(toJoin, remainingNanos);
|
||||
return;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
remainingNanos = end - System.nanoTime();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <E> E takeUninterruptibly(BlockingQueue<E> queue) {
|
||||
boolean interrupted = false;
|
||||
while (true) {
|
||||
try {
|
||||
E e = queue.take();
|
||||
return e;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <E> void putUninterruptibly(BlockingQueue<E> queue, E element) {
|
||||
boolean interrupted = false;
|
||||
while (true) {
|
||||
try {
|
||||
queue.put(element);
|
||||
return;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.NANOSECONDS.sleep(remainingNanos);
|
||||
return;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
remainingNanos = end - System.nanoTime();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean tryAcquireUninterruptibly(Semaphore semaphore, long timeout, TimeUnit unit) {
|
||||
return Uninterruptibles.tryAcquireUninterruptibly(semaphore, 1, timeout, unit);
|
||||
}
|
||||
|
||||
public static boolean tryAcquireUninterruptibly(Semaphore semaphore, int permits, long timeout, TimeUnit unit) {
|
||||
boolean interrupted = false;
|
||||
try {
|
||||
long remainingNanos = unit.toNanos(timeout);
|
||||
long end = System.nanoTime() + remainingNanos;
|
||||
while (true) {
|
||||
try {
|
||||
boolean bl = semaphore.tryAcquire(permits, remainingNanos, TimeUnit.NANOSECONDS);
|
||||
return bl;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
remainingNanos = end - System.nanoTime();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Uninterruptibles() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
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.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
abstract class WrappingExecutorService
|
||||
implements ExecutorService {
|
||||
private final ExecutorService delegate;
|
||||
|
||||
protected WrappingExecutorService(ExecutorService delegate) {
|
||||
this.delegate = Preconditions.checkNotNull(delegate);
|
||||
}
|
||||
|
||||
protected abstract <T> Callable<T> wrapTask(Callable<T> var1);
|
||||
|
||||
protected Runnable wrapTask(Runnable command) {
|
||||
final Callable<Object> wrapped = this.wrapTask(Executors.callable(command, null));
|
||||
return new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
wrapped.call();
|
||||
}
|
||||
catch (Exception e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final <T> ImmutableList<Callable<T>> wrapTasks(Collection<? extends Callable<T>> tasks) {
|
||||
ImmutableList.Builder builder = ImmutableList.builder();
|
||||
for (Callable<T> task : tasks) {
|
||||
builder.add(this.wrapTask(task));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void execute(Runnable command) {
|
||||
this.delegate.execute(this.wrapTask(command));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> Future<T> submit(Callable<T> task) {
|
||||
return this.delegate.submit(this.wrapTask(Preconditions.checkNotNull(task)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Future<?> submit(Runnable task) {
|
||||
return this.delegate.submit(this.wrapTask(task));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> Future<T> submit(Runnable task, T result) {
|
||||
return this.delegate.submit(this.wrapTask(task), result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
|
||||
return this.delegate.invokeAll(this.wrapTasks(tasks));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return this.delegate.invokeAll(this.wrapTasks(tasks), timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
|
||||
return this.delegate.invokeAny(this.wrapTasks(tasks));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
return this.delegate.invokeAny(this.wrapTasks(tasks), timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void shutdown() {
|
||||
this.delegate.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Runnable> shutdownNow() {
|
||||
return this.delegate.shutdownNow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isShutdown() {
|
||||
return this.delegate.isShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isTerminated() {
|
||||
return this.delegate.isTerminated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return this.delegate.awaitTermination(timeout, unit);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import com.google.common.util.concurrent.WrappingExecutorService;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
abstract class WrappingScheduledExecutorService
|
||||
extends WrappingExecutorService
|
||||
implements ScheduledExecutorService {
|
||||
final ScheduledExecutorService delegate;
|
||||
|
||||
protected WrappingScheduledExecutorService(ScheduledExecutorService delegate) {
|
||||
super(delegate);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
|
||||
return this.delegate.schedule(this.wrapTask(command), delay, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <V> ScheduledFuture<V> schedule(Callable<V> task, long delay, TimeUnit unit) {
|
||||
return this.delegate.schedule(this.wrapTask(task), delay, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
|
||||
return this.delegate.scheduleAtFixedRate(this.wrapTask(command), initialDelay, period, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
|
||||
return this.delegate.scheduleWithFixedDelay(this.wrapTask(command), initialDelay, delay, unit);
|
||||
}
|
||||
}
|
8
src/com/google/common/util/concurrent/package-info.java
Normal file
8
src/com/google/common/util/concurrent/package-info.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
package com.google.common.util.concurrent;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue