obsidian-launcher/src/com/google/common/util/concurrent/MoreExecutors.java
2022-08-09 23:00:29 -07:00

632 lines
23 KiB
Java

/*
* 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);
}
}
}