210 lines
8.4 KiB
Java
210 lines
8.4 KiB
Java
|
package com.google.common.util.concurrent;
|
||
|
|
||
|
import com.google.common.base.Preconditions;
|
||
|
import java.util.concurrent.Callable;
|
||
|
import java.util.concurrent.Executor;
|
||
|
import java.util.concurrent.atomic.AtomicReference;
|
||
|
|
||
|
/* loaded from: classes2.dex */
|
||
|
public final class ExecutionSequencer {
|
||
|
private final AtomicReference<ListenableFuture<Void>> ref = new AtomicReference<>(Futures.immediateVoidFuture());
|
||
|
private ThreadConfinedTaskQueue latestTaskQueue = new ThreadConfinedTaskQueue();
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: package-private */
|
||
|
/* loaded from: classes2.dex */
|
||
|
public enum RunningState {
|
||
|
NOT_RUN,
|
||
|
CANCELLED,
|
||
|
STARTED
|
||
|
}
|
||
|
|
||
|
private ExecutionSequencer() {
|
||
|
}
|
||
|
|
||
|
public static ExecutionSequencer create() {
|
||
|
return new ExecutionSequencer();
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes2.dex */
|
||
|
static final class ThreadConfinedTaskQueue {
|
||
|
Executor nextExecutor;
|
||
|
Runnable nextTask;
|
||
|
Thread thread;
|
||
|
|
||
|
private ThreadConfinedTaskQueue() {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public final <T> ListenableFuture<T> submit(Callable<T> callable, Executor executor) {
|
||
|
Preconditions.checkNotNull(callable);
|
||
|
Preconditions.checkNotNull(executor);
|
||
|
return submitAsync(new AsyncCallable<T>(this, callable) { // from class: com.google.common.util.concurrent.ExecutionSequencer.1
|
||
|
final Callable val$callable;
|
||
|
|
||
|
{
|
||
|
this.val$callable = callable;
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.AsyncCallable
|
||
|
public ListenableFuture<T> call() throws Exception {
|
||
|
return Futures.immediateFuture(this.val$callable.call());
|
||
|
}
|
||
|
|
||
|
public String toString() {
|
||
|
return this.val$callable.toString();
|
||
|
}
|
||
|
}, executor);
|
||
|
}
|
||
|
|
||
|
public final <T> ListenableFuture<T> submitAsync(AsyncCallable<T> asyncCallable, Executor executor) {
|
||
|
Preconditions.checkNotNull(asyncCallable);
|
||
|
Preconditions.checkNotNull(executor);
|
||
|
TaskNonReentrantExecutor taskNonReentrantExecutor = new TaskNonReentrantExecutor(executor, this);
|
||
|
AsyncCallable<T> asyncCallable2 = new AsyncCallable<T>(this, taskNonReentrantExecutor, asyncCallable) { // from class: com.google.common.util.concurrent.ExecutionSequencer.2
|
||
|
final AsyncCallable val$callable;
|
||
|
final TaskNonReentrantExecutor val$taskExecutor;
|
||
|
|
||
|
{
|
||
|
this.val$taskExecutor = taskNonReentrantExecutor;
|
||
|
this.val$callable = asyncCallable;
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.AsyncCallable
|
||
|
public ListenableFuture<T> call() throws Exception {
|
||
|
if (!this.val$taskExecutor.trySetStarted()) {
|
||
|
return Futures.immediateCancelledFuture();
|
||
|
}
|
||
|
return this.val$callable.call();
|
||
|
}
|
||
|
|
||
|
public String toString() {
|
||
|
return this.val$callable.toString();
|
||
|
}
|
||
|
};
|
||
|
SettableFuture create = SettableFuture.create();
|
||
|
ListenableFuture<Void> andSet = this.ref.getAndSet(create);
|
||
|
TrustedListenableFutureTask create2 = TrustedListenableFutureTask.create(asyncCallable2);
|
||
|
andSet.addListener(create2, taskNonReentrantExecutor);
|
||
|
ListenableFuture<T> nonCancellationPropagating = Futures.nonCancellationPropagating(create2);
|
||
|
Runnable runnable = new Runnable(this, create2, create, andSet, nonCancellationPropagating, taskNonReentrantExecutor) { // from class: com.google.common.util.concurrent.ExecutionSequencer.3
|
||
|
final SettableFuture val$newFuture;
|
||
|
final ListenableFuture val$oldFuture;
|
||
|
final ListenableFuture val$outputFuture;
|
||
|
final TaskNonReentrantExecutor val$taskExecutor;
|
||
|
final TrustedListenableFutureTask val$taskFuture;
|
||
|
|
||
|
{
|
||
|
this.val$taskFuture = create2;
|
||
|
this.val$newFuture = create;
|
||
|
this.val$oldFuture = andSet;
|
||
|
this.val$outputFuture = nonCancellationPropagating;
|
||
|
this.val$taskExecutor = taskNonReentrantExecutor;
|
||
|
}
|
||
|
|
||
|
@Override // java.lang.Runnable
|
||
|
public void run() {
|
||
|
if (this.val$taskFuture.isDone()) {
|
||
|
this.val$newFuture.setFuture(this.val$oldFuture);
|
||
|
} else if (this.val$outputFuture.isCancelled() && this.val$taskExecutor.trySetCancelled()) {
|
||
|
this.val$taskFuture.cancel(false);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
nonCancellationPropagating.addListener(runnable, MoreExecutors.directExecutor());
|
||
|
create2.addListener(runnable, MoreExecutors.directExecutor());
|
||
|
return nonCancellationPropagating;
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: package-private */
|
||
|
/* loaded from: classes2.dex */
|
||
|
public static final class TaskNonReentrantExecutor extends AtomicReference<RunningState> implements Executor, Runnable {
|
||
|
Executor delegate;
|
||
|
ExecutionSequencer sequencer;
|
||
|
Thread submitting;
|
||
|
Runnable task;
|
||
|
|
||
|
private TaskNonReentrantExecutor(Executor executor, ExecutionSequencer executionSequencer) {
|
||
|
super(RunningState.NOT_RUN);
|
||
|
this.delegate = executor;
|
||
|
this.sequencer = executionSequencer;
|
||
|
}
|
||
|
|
||
|
@Override // java.util.concurrent.Executor
|
||
|
public final void execute(Runnable runnable) {
|
||
|
if (get() == RunningState.CANCELLED) {
|
||
|
this.delegate = null;
|
||
|
this.sequencer = null;
|
||
|
return;
|
||
|
}
|
||
|
this.submitting = Thread.currentThread();
|
||
|
try {
|
||
|
ThreadConfinedTaskQueue threadConfinedTaskQueue = this.sequencer.latestTaskQueue;
|
||
|
if (threadConfinedTaskQueue.thread == this.submitting) {
|
||
|
this.sequencer = null;
|
||
|
Preconditions.checkState(threadConfinedTaskQueue.nextTask == null);
|
||
|
threadConfinedTaskQueue.nextTask = runnable;
|
||
|
threadConfinedTaskQueue.nextExecutor = this.delegate;
|
||
|
this.delegate = null;
|
||
|
} else {
|
||
|
Executor executor = this.delegate;
|
||
|
this.delegate = null;
|
||
|
this.task = runnable;
|
||
|
executor.execute(this);
|
||
|
}
|
||
|
} finally {
|
||
|
this.submitting = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* JADX WARN: Multi-variable type inference failed */
|
||
|
@Override // java.lang.Runnable
|
||
|
public final void run() {
|
||
|
Thread currentThread = Thread.currentThread();
|
||
|
Thread thread = null;
|
||
|
Object[] objArr = 0;
|
||
|
if (currentThread != this.submitting) {
|
||
|
Runnable runnable = this.task;
|
||
|
this.task = null;
|
||
|
runnable.run();
|
||
|
return;
|
||
|
}
|
||
|
ThreadConfinedTaskQueue threadConfinedTaskQueue = new ThreadConfinedTaskQueue();
|
||
|
threadConfinedTaskQueue.thread = currentThread;
|
||
|
this.sequencer.latestTaskQueue = threadConfinedTaskQueue;
|
||
|
this.sequencer = null;
|
||
|
try {
|
||
|
Runnable runnable2 = this.task;
|
||
|
this.task = null;
|
||
|
runnable2.run();
|
||
|
while (true) {
|
||
|
Runnable runnable3 = threadConfinedTaskQueue.nextTask;
|
||
|
boolean z = false;
|
||
|
boolean z2 = runnable3 != null;
|
||
|
Executor executor = threadConfinedTaskQueue.nextExecutor;
|
||
|
if (executor != null) {
|
||
|
z = true;
|
||
|
}
|
||
|
if (!z || !z2) {
|
||
|
return;
|
||
|
}
|
||
|
threadConfinedTaskQueue.nextTask = null;
|
||
|
threadConfinedTaskQueue.nextExecutor = null;
|
||
|
executor.execute(runnable3);
|
||
|
}
|
||
|
} finally {
|
||
|
threadConfinedTaskQueue.thread = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: private */
|
||
|
public boolean trySetStarted() {
|
||
|
return compareAndSet(RunningState.NOT_RUN, RunningState.STARTED);
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: private */
|
||
|
public boolean trySetCancelled() {
|
||
|
return compareAndSet(RunningState.NOT_RUN, RunningState.CANCELLED);
|
||
|
}
|
||
|
}
|
||
|
}
|