750 lines
29 KiB
Java
750 lines
29 KiB
Java
package androidx.concurrent.futures;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.RestrictTo;
|
|
import c.i.b.d.a.a;
|
|
import java.util.Locale;
|
|
import java.util.Objects;
|
|
import java.util.concurrent.CancellationException;
|
|
import java.util.concurrent.ExecutionException;
|
|
import java.util.concurrent.Executor;
|
|
import java.util.concurrent.Future;
|
|
import java.util.concurrent.ScheduledFuture;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeoutException;
|
|
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
|
import java.util.concurrent.locks.LockSupport;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
public abstract class AbstractResolvableFuture<V> implements a<V> {
|
|
public static final AtomicHelper ATOMIC_HELPER;
|
|
public static final boolean GENERATE_CANCELLATION_CAUSES = Boolean.parseBoolean(System.getProperty("guava.concurrent.generate_cancellation_cause", "false"));
|
|
private static final Object NULL = new Object();
|
|
private static final long SPIN_THRESHOLD_NANOS = 1000;
|
|
private static final Logger log = Logger.getLogger(AbstractResolvableFuture.class.getName());
|
|
@Nullable
|
|
public volatile Listener listeners;
|
|
@Nullable
|
|
public volatile Object value;
|
|
@Nullable
|
|
public volatile Waiter waiters;
|
|
|
|
public static abstract class AtomicHelper {
|
|
private AtomicHelper() {
|
|
}
|
|
|
|
public abstract boolean casListeners(AbstractResolvableFuture<?> abstractResolvableFuture, Listener listener, Listener listener2);
|
|
|
|
public abstract boolean casValue(AbstractResolvableFuture<?> abstractResolvableFuture, Object obj, Object obj2);
|
|
|
|
public abstract boolean casWaiters(AbstractResolvableFuture<?> abstractResolvableFuture, Waiter waiter, Waiter waiter2);
|
|
|
|
public abstract void putNext(Waiter waiter, Waiter waiter2);
|
|
|
|
public abstract void putThread(Waiter waiter, Thread thread);
|
|
}
|
|
|
|
public static final class Cancellation {
|
|
public static final Cancellation CAUSELESS_CANCELLED;
|
|
public static final Cancellation CAUSELESS_INTERRUPTED;
|
|
@Nullable
|
|
public final Throwable cause;
|
|
public final boolean wasInterrupted;
|
|
|
|
static {
|
|
if (AbstractResolvableFuture.GENERATE_CANCELLATION_CAUSES) {
|
|
CAUSELESS_CANCELLED = null;
|
|
CAUSELESS_INTERRUPTED = null;
|
|
return;
|
|
}
|
|
CAUSELESS_CANCELLED = new Cancellation(false, null);
|
|
CAUSELESS_INTERRUPTED = new Cancellation(true, null);
|
|
}
|
|
|
|
public Cancellation(boolean z2, @Nullable Throwable th) {
|
|
this.wasInterrupted = z2;
|
|
this.cause = th;
|
|
}
|
|
}
|
|
|
|
public static final class Failure {
|
|
public static final Failure FALLBACK_INSTANCE = new Failure(new AnonymousClass1("Failure occurred while trying to finish a future."));
|
|
public final Throwable exception;
|
|
|
|
/* renamed from: androidx.concurrent.futures.AbstractResolvableFuture$Failure$1 reason: invalid class name */
|
|
public static class AnonymousClass1 extends Throwable {
|
|
public AnonymousClass1(String str) {
|
|
super(str);
|
|
}
|
|
|
|
@Override // java.lang.Throwable
|
|
public synchronized Throwable fillInStackTrace() {
|
|
return this;
|
|
}
|
|
}
|
|
|
|
public Failure(Throwable th) {
|
|
this.exception = (Throwable) AbstractResolvableFuture.checkNotNull(th);
|
|
}
|
|
}
|
|
|
|
public static final class Listener {
|
|
public static final Listener TOMBSTONE = new Listener(null, null);
|
|
public final Executor executor;
|
|
@Nullable
|
|
public Listener next;
|
|
public final Runnable task;
|
|
|
|
public Listener(Runnable runnable, Executor executor) {
|
|
this.task = runnable;
|
|
this.executor = executor;
|
|
}
|
|
}
|
|
|
|
public static final class SafeAtomicHelper extends AtomicHelper {
|
|
public final AtomicReferenceFieldUpdater<AbstractResolvableFuture, Listener> listenersUpdater;
|
|
public final AtomicReferenceFieldUpdater<AbstractResolvableFuture, Object> valueUpdater;
|
|
public final AtomicReferenceFieldUpdater<Waiter, Waiter> waiterNextUpdater;
|
|
public final AtomicReferenceFieldUpdater<Waiter, Thread> waiterThreadUpdater;
|
|
public final AtomicReferenceFieldUpdater<AbstractResolvableFuture, Waiter> waitersUpdater;
|
|
|
|
public SafeAtomicHelper(AtomicReferenceFieldUpdater<Waiter, Thread> atomicReferenceFieldUpdater, AtomicReferenceFieldUpdater<Waiter, Waiter> atomicReferenceFieldUpdater2, AtomicReferenceFieldUpdater<AbstractResolvableFuture, Waiter> atomicReferenceFieldUpdater3, AtomicReferenceFieldUpdater<AbstractResolvableFuture, Listener> atomicReferenceFieldUpdater4, AtomicReferenceFieldUpdater<AbstractResolvableFuture, Object> atomicReferenceFieldUpdater5) {
|
|
super();
|
|
this.waiterThreadUpdater = atomicReferenceFieldUpdater;
|
|
this.waiterNextUpdater = atomicReferenceFieldUpdater2;
|
|
this.waitersUpdater = atomicReferenceFieldUpdater3;
|
|
this.listenersUpdater = atomicReferenceFieldUpdater4;
|
|
this.valueUpdater = atomicReferenceFieldUpdater5;
|
|
}
|
|
|
|
@Override // androidx.concurrent.futures.AbstractResolvableFuture.AtomicHelper
|
|
public boolean casListeners(AbstractResolvableFuture<?> abstractResolvableFuture, Listener listener, Listener listener2) {
|
|
return this.listenersUpdater.compareAndSet(abstractResolvableFuture, listener, listener2);
|
|
}
|
|
|
|
@Override // androidx.concurrent.futures.AbstractResolvableFuture.AtomicHelper
|
|
public boolean casValue(AbstractResolvableFuture<?> abstractResolvableFuture, Object obj, Object obj2) {
|
|
return this.valueUpdater.compareAndSet(abstractResolvableFuture, obj, obj2);
|
|
}
|
|
|
|
@Override // androidx.concurrent.futures.AbstractResolvableFuture.AtomicHelper
|
|
public boolean casWaiters(AbstractResolvableFuture<?> abstractResolvableFuture, Waiter waiter, Waiter waiter2) {
|
|
return this.waitersUpdater.compareAndSet(abstractResolvableFuture, waiter, waiter2);
|
|
}
|
|
|
|
@Override // androidx.concurrent.futures.AbstractResolvableFuture.AtomicHelper
|
|
public void putNext(Waiter waiter, Waiter waiter2) {
|
|
this.waiterNextUpdater.lazySet(waiter, waiter2);
|
|
}
|
|
|
|
@Override // androidx.concurrent.futures.AbstractResolvableFuture.AtomicHelper
|
|
public void putThread(Waiter waiter, Thread thread) {
|
|
this.waiterThreadUpdater.lazySet(waiter, thread);
|
|
}
|
|
}
|
|
|
|
public static final class SetFuture<V> implements Runnable {
|
|
public final a<? extends V> future;
|
|
public final AbstractResolvableFuture<V> owner;
|
|
|
|
public SetFuture(AbstractResolvableFuture<V> abstractResolvableFuture, a<? extends V> aVar) {
|
|
this.owner = abstractResolvableFuture;
|
|
this.future = aVar;
|
|
}
|
|
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
if (this.owner.value == this) {
|
|
if (AbstractResolvableFuture.ATOMIC_HELPER.casValue(this.owner, this, AbstractResolvableFuture.getFutureValue(this.future))) {
|
|
AbstractResolvableFuture.complete(this.owner);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static final class SynchronizedHelper extends AtomicHelper {
|
|
public SynchronizedHelper() {
|
|
super();
|
|
}
|
|
|
|
@Override // androidx.concurrent.futures.AbstractResolvableFuture.AtomicHelper
|
|
public boolean casListeners(AbstractResolvableFuture<?> abstractResolvableFuture, Listener listener, Listener listener2) {
|
|
synchronized (abstractResolvableFuture) {
|
|
if (abstractResolvableFuture.listeners != listener) {
|
|
return false;
|
|
}
|
|
abstractResolvableFuture.listeners = listener2;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
@Override // androidx.concurrent.futures.AbstractResolvableFuture.AtomicHelper
|
|
public boolean casValue(AbstractResolvableFuture<?> abstractResolvableFuture, Object obj, Object obj2) {
|
|
synchronized (abstractResolvableFuture) {
|
|
if (abstractResolvableFuture.value != obj) {
|
|
return false;
|
|
}
|
|
abstractResolvableFuture.value = obj2;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
@Override // androidx.concurrent.futures.AbstractResolvableFuture.AtomicHelper
|
|
public boolean casWaiters(AbstractResolvableFuture<?> abstractResolvableFuture, Waiter waiter, Waiter waiter2) {
|
|
synchronized (abstractResolvableFuture) {
|
|
if (abstractResolvableFuture.waiters != waiter) {
|
|
return false;
|
|
}
|
|
abstractResolvableFuture.waiters = waiter2;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
@Override // androidx.concurrent.futures.AbstractResolvableFuture.AtomicHelper
|
|
public void putNext(Waiter waiter, Waiter waiter2) {
|
|
waiter.next = waiter2;
|
|
}
|
|
|
|
@Override // androidx.concurrent.futures.AbstractResolvableFuture.AtomicHelper
|
|
public void putThread(Waiter waiter, Thread thread) {
|
|
waiter.thread = thread;
|
|
}
|
|
}
|
|
|
|
public static final class Waiter {
|
|
public static final Waiter TOMBSTONE = new Waiter(false);
|
|
@Nullable
|
|
public volatile Waiter next;
|
|
@Nullable
|
|
public volatile Thread thread;
|
|
|
|
public Waiter() {
|
|
AbstractResolvableFuture.ATOMIC_HELPER.putThread(this, Thread.currentThread());
|
|
}
|
|
|
|
public Waiter(boolean z2) {
|
|
}
|
|
|
|
public void setNext(Waiter waiter) {
|
|
AbstractResolvableFuture.ATOMIC_HELPER.putNext(this, waiter);
|
|
}
|
|
|
|
public void unpark() {
|
|
Thread thread = this.thread;
|
|
if (thread != null) {
|
|
this.thread = null;
|
|
LockSupport.unpark(thread);
|
|
}
|
|
}
|
|
}
|
|
|
|
static {
|
|
AtomicHelper atomicHelper;
|
|
Throwable th;
|
|
try {
|
|
atomicHelper = new SafeAtomicHelper(AtomicReferenceFieldUpdater.newUpdater(Waiter.class, Thread.class, "thread"), AtomicReferenceFieldUpdater.newUpdater(Waiter.class, Waiter.class, "next"), AtomicReferenceFieldUpdater.newUpdater(AbstractResolvableFuture.class, Waiter.class, "waiters"), AtomicReferenceFieldUpdater.newUpdater(AbstractResolvableFuture.class, Listener.class, "listeners"), AtomicReferenceFieldUpdater.newUpdater(AbstractResolvableFuture.class, Object.class, "value"));
|
|
th = null;
|
|
} catch (Throwable th2) {
|
|
th = th2;
|
|
atomicHelper = new SynchronizedHelper();
|
|
}
|
|
ATOMIC_HELPER = atomicHelper;
|
|
if (th != null) {
|
|
log.log(Level.SEVERE, "SafeAtomicHelper is broken!", th);
|
|
}
|
|
}
|
|
|
|
private void addDoneString(StringBuilder sb) {
|
|
try {
|
|
Object uninterruptibly = getUninterruptibly(this);
|
|
sb.append("SUCCESS, result=[");
|
|
sb.append(userObjectToString(uninterruptibly));
|
|
sb.append("]");
|
|
} catch (ExecutionException e) {
|
|
sb.append("FAILURE, cause=[");
|
|
sb.append(e.getCause());
|
|
sb.append("]");
|
|
} catch (CancellationException unused) {
|
|
sb.append("CANCELLED");
|
|
} catch (RuntimeException e2) {
|
|
sb.append("UNKNOWN, cause=[");
|
|
sb.append(e2.getClass());
|
|
sb.append(" thrown from get()]");
|
|
}
|
|
}
|
|
|
|
private static CancellationException cancellationExceptionWithCause(@Nullable String str, @Nullable Throwable th) {
|
|
CancellationException cancellationException = new CancellationException(str);
|
|
cancellationException.initCause(th);
|
|
return cancellationException;
|
|
}
|
|
|
|
@NonNull
|
|
public static <T> T checkNotNull(@Nullable T t) {
|
|
Objects.requireNonNull(t);
|
|
return t;
|
|
}
|
|
|
|
private Listener clearListeners(Listener listener) {
|
|
Listener listener2;
|
|
do {
|
|
listener2 = this.listeners;
|
|
} while (!ATOMIC_HELPER.casListeners(this, listener2, Listener.TOMBSTONE));
|
|
Listener listener3 = listener;
|
|
Listener listener4 = listener2;
|
|
while (listener4 != null) {
|
|
Listener listener5 = listener4.next;
|
|
listener4.next = listener3;
|
|
listener3 = listener4;
|
|
listener4 = listener5;
|
|
}
|
|
return listener3;
|
|
}
|
|
|
|
/* JADX DEBUG: Failed to insert an additional move for type inference into block B:13:0x0001 */
|
|
/* JADX WARN: Multi-variable type inference failed */
|
|
/* JADX WARNING: Unknown variable types count: 1 */
|
|
public static void complete(AbstractResolvableFuture<?> abstractResolvableFuture) {
|
|
Listener listener = null;
|
|
while (true) {
|
|
abstractResolvableFuture.releaseWaiters();
|
|
abstractResolvableFuture.afterDone();
|
|
Listener clearListeners = abstractResolvableFuture.clearListeners(listener);
|
|
while (true) {
|
|
if (clearListeners != null) {
|
|
listener = clearListeners.next;
|
|
Runnable runnable = clearListeners.task;
|
|
if (runnable instanceof SetFuture) {
|
|
SetFuture setFuture = (SetFuture) runnable;
|
|
abstractResolvableFuture = setFuture.owner;
|
|
if (abstractResolvableFuture.value == setFuture) {
|
|
if (ATOMIC_HELPER.casValue(abstractResolvableFuture, setFuture, getFutureValue(setFuture.future))) {
|
|
}
|
|
} else {
|
|
continue;
|
|
}
|
|
} else {
|
|
executeListener(runnable, clearListeners.executor);
|
|
}
|
|
clearListeners = listener;
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void executeListener(Runnable runnable, Executor executor) {
|
|
try {
|
|
executor.execute(runnable);
|
|
} catch (RuntimeException e) {
|
|
Logger logger = log;
|
|
Level level = Level.SEVERE;
|
|
logger.log(level, "RuntimeException while executing runnable " + runnable + " with executor " + executor, (Throwable) e);
|
|
}
|
|
}
|
|
|
|
/* JADX DEBUG: Multi-variable search result rejected for r2v0, resolved type: java.lang.Object */
|
|
/* JADX WARN: Multi-variable type inference failed */
|
|
private V getDoneValue(Object obj) throws ExecutionException {
|
|
if (obj instanceof Cancellation) {
|
|
throw cancellationExceptionWithCause("Task was cancelled.", ((Cancellation) obj).cause);
|
|
} else if (obj instanceof Failure) {
|
|
throw new ExecutionException(((Failure) obj).exception);
|
|
} else if (obj == NULL) {
|
|
return null;
|
|
} else {
|
|
return obj;
|
|
}
|
|
}
|
|
|
|
public static Object getFutureValue(a<?> aVar) {
|
|
if (aVar instanceof AbstractResolvableFuture) {
|
|
Object obj = ((AbstractResolvableFuture) aVar).value;
|
|
if (!(obj instanceof Cancellation)) {
|
|
return obj;
|
|
}
|
|
Cancellation cancellation = (Cancellation) obj;
|
|
return cancellation.wasInterrupted ? cancellation.cause != null ? new Cancellation(false, cancellation.cause) : Cancellation.CAUSELESS_CANCELLED : obj;
|
|
}
|
|
boolean isCancelled = aVar.isCancelled();
|
|
if ((!GENERATE_CANCELLATION_CAUSES) && isCancelled) {
|
|
return Cancellation.CAUSELESS_CANCELLED;
|
|
}
|
|
try {
|
|
Object uninterruptibly = getUninterruptibly(aVar);
|
|
return uninterruptibly == null ? NULL : uninterruptibly;
|
|
} catch (ExecutionException e) {
|
|
return new Failure(e.getCause());
|
|
} catch (CancellationException e2) {
|
|
if (isCancelled) {
|
|
return new Cancellation(false, e2);
|
|
}
|
|
return new Failure(new IllegalArgumentException("get() threw CancellationException, despite reporting isCancelled() == false: " + aVar, e2));
|
|
} catch (Throwable th) {
|
|
return new Failure(th);
|
|
}
|
|
}
|
|
|
|
private static <V> V getUninterruptibly(Future<V> future) throws ExecutionException {
|
|
V v;
|
|
boolean z2 = false;
|
|
while (true) {
|
|
try {
|
|
v = future.get();
|
|
break;
|
|
} catch (InterruptedException unused) {
|
|
z2 = true;
|
|
} catch (Throwable th) {
|
|
if (z2) {
|
|
Thread.currentThread().interrupt();
|
|
}
|
|
throw th;
|
|
}
|
|
}
|
|
if (z2) {
|
|
Thread.currentThread().interrupt();
|
|
}
|
|
return v;
|
|
}
|
|
|
|
private void releaseWaiters() {
|
|
Waiter waiter;
|
|
do {
|
|
waiter = this.waiters;
|
|
} while (!ATOMIC_HELPER.casWaiters(this, waiter, Waiter.TOMBSTONE));
|
|
while (waiter != null) {
|
|
waiter.unpark();
|
|
waiter = waiter.next;
|
|
}
|
|
}
|
|
|
|
private void removeWaiter(Waiter waiter) {
|
|
waiter.thread = null;
|
|
while (true) {
|
|
Waiter waiter2 = this.waiters;
|
|
if (waiter2 != Waiter.TOMBSTONE) {
|
|
Waiter waiter3 = null;
|
|
while (waiter2 != null) {
|
|
Waiter waiter4 = waiter2.next;
|
|
if (waiter2.thread != null) {
|
|
waiter3 = waiter2;
|
|
} else if (waiter3 != null) {
|
|
waiter3.next = waiter4;
|
|
if (waiter3.thread == null) {
|
|
}
|
|
} else if (!ATOMIC_HELPER.casWaiters(this, waiter2, waiter4)) {
|
|
}
|
|
waiter2 = waiter4;
|
|
}
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
private String userObjectToString(Object obj) {
|
|
return obj == this ? "this future" : String.valueOf(obj);
|
|
}
|
|
|
|
@Override // c.i.b.d.a.a
|
|
public final void addListener(Runnable runnable, Executor executor) {
|
|
checkNotNull(runnable);
|
|
checkNotNull(executor);
|
|
Listener listener = this.listeners;
|
|
if (listener != Listener.TOMBSTONE) {
|
|
Listener listener2 = new Listener(runnable, executor);
|
|
do {
|
|
listener2.next = listener;
|
|
if (!ATOMIC_HELPER.casListeners(this, listener, listener2)) {
|
|
listener = this.listeners;
|
|
} else {
|
|
return;
|
|
}
|
|
} while (listener != Listener.TOMBSTONE);
|
|
}
|
|
executeListener(runnable, executor);
|
|
}
|
|
|
|
public void afterDone() {
|
|
}
|
|
|
|
@Override // java.util.concurrent.Future
|
|
public final boolean cancel(boolean z2) {
|
|
Object obj = this.value;
|
|
if (!(obj == null) && !(obj instanceof SetFuture)) {
|
|
return false;
|
|
}
|
|
Cancellation cancellation = GENERATE_CANCELLATION_CAUSES ? new Cancellation(z2, new CancellationException("Future.cancel() was called.")) : z2 ? Cancellation.CAUSELESS_INTERRUPTED : Cancellation.CAUSELESS_CANCELLED;
|
|
boolean z3 = false;
|
|
AbstractResolvableFuture<V> abstractResolvableFuture = this;
|
|
while (true) {
|
|
if (ATOMIC_HELPER.casValue(abstractResolvableFuture, obj, cancellation)) {
|
|
if (z2) {
|
|
abstractResolvableFuture.interruptTask();
|
|
}
|
|
complete(abstractResolvableFuture);
|
|
if (!(obj instanceof SetFuture)) {
|
|
return true;
|
|
}
|
|
a<? extends V> aVar = ((SetFuture) obj).future;
|
|
if (aVar instanceof AbstractResolvableFuture) {
|
|
abstractResolvableFuture = (AbstractResolvableFuture) aVar;
|
|
obj = abstractResolvableFuture.value;
|
|
if (!(obj == null) && !(obj instanceof SetFuture)) {
|
|
return true;
|
|
}
|
|
z3 = true;
|
|
} else {
|
|
aVar.cancel(z2);
|
|
return true;
|
|
}
|
|
} else {
|
|
obj = abstractResolvableFuture.value;
|
|
if (!(obj instanceof SetFuture)) {
|
|
return z3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override // java.util.concurrent.Future
|
|
public final V get() throws InterruptedException, ExecutionException {
|
|
Object obj;
|
|
if (!Thread.interrupted()) {
|
|
Object obj2 = this.value;
|
|
if ((obj2 != null) && (!(obj2 instanceof SetFuture))) {
|
|
return getDoneValue(obj2);
|
|
}
|
|
Waiter waiter = this.waiters;
|
|
if (waiter != Waiter.TOMBSTONE) {
|
|
Waiter waiter2 = new Waiter();
|
|
do {
|
|
waiter2.setNext(waiter);
|
|
if (ATOMIC_HELPER.casWaiters(this, waiter, waiter2)) {
|
|
do {
|
|
LockSupport.park(this);
|
|
if (!Thread.interrupted()) {
|
|
obj = this.value;
|
|
} else {
|
|
removeWaiter(waiter2);
|
|
throw new InterruptedException();
|
|
}
|
|
} while (!((obj != null) & (!(obj instanceof SetFuture))));
|
|
return getDoneValue(obj);
|
|
}
|
|
waiter = this.waiters;
|
|
} while (waiter != Waiter.TOMBSTONE);
|
|
}
|
|
return getDoneValue(this.value);
|
|
}
|
|
throw new InterruptedException();
|
|
}
|
|
|
|
@Override // java.util.concurrent.Future
|
|
public final V get(long j, TimeUnit timeUnit) throws InterruptedException, TimeoutException, ExecutionException {
|
|
long nanos = timeUnit.toNanos(j);
|
|
if (!Thread.interrupted()) {
|
|
Object obj = this.value;
|
|
if ((obj != null) && (!(obj instanceof SetFuture))) {
|
|
return getDoneValue(obj);
|
|
}
|
|
long nanoTime = nanos > 0 ? System.nanoTime() + nanos : 0;
|
|
if (nanos >= 1000) {
|
|
Waiter waiter = this.waiters;
|
|
if (waiter != Waiter.TOMBSTONE) {
|
|
Waiter waiter2 = new Waiter();
|
|
do {
|
|
waiter2.setNext(waiter);
|
|
if (ATOMIC_HELPER.casWaiters(this, waiter, waiter2)) {
|
|
do {
|
|
LockSupport.parkNanos(this, nanos);
|
|
if (!Thread.interrupted()) {
|
|
Object obj2 = this.value;
|
|
if ((obj2 != null) && (!(obj2 instanceof SetFuture))) {
|
|
return getDoneValue(obj2);
|
|
}
|
|
nanos = nanoTime - System.nanoTime();
|
|
} else {
|
|
removeWaiter(waiter2);
|
|
throw new InterruptedException();
|
|
}
|
|
} while (nanos >= 1000);
|
|
removeWaiter(waiter2);
|
|
} else {
|
|
waiter = this.waiters;
|
|
}
|
|
} while (waiter != Waiter.TOMBSTONE);
|
|
}
|
|
return getDoneValue(this.value);
|
|
}
|
|
while (nanos > 0) {
|
|
Object obj3 = this.value;
|
|
if ((obj3 != null) && (!(obj3 instanceof SetFuture))) {
|
|
return getDoneValue(obj3);
|
|
}
|
|
if (!Thread.interrupted()) {
|
|
nanos = nanoTime - System.nanoTime();
|
|
} else {
|
|
throw new InterruptedException();
|
|
}
|
|
}
|
|
String abstractResolvableFuture = toString();
|
|
String timeUnit2 = timeUnit.toString();
|
|
Locale locale = Locale.ROOT;
|
|
String lowerCase = timeUnit2.toLowerCase(locale);
|
|
StringBuilder N = c.d.b.a.a.N("Waited ", j, " ");
|
|
N.append(timeUnit.toString().toLowerCase(locale));
|
|
String sb = N.toString();
|
|
if (nanos + 1000 < 0) {
|
|
String s2 = c.d.b.a.a.s(sb, " (plus ");
|
|
long j2 = -nanos;
|
|
long convert = timeUnit.convert(j2, TimeUnit.NANOSECONDS);
|
|
long nanos2 = j2 - timeUnit.toNanos(convert);
|
|
int i = (convert > 0 ? 1 : (convert == 0 ? 0 : -1));
|
|
boolean z2 = i == 0 || nanos2 > 1000;
|
|
if (i > 0) {
|
|
String str = s2 + convert + " " + lowerCase;
|
|
if (z2) {
|
|
str = c.d.b.a.a.s(str, ",");
|
|
}
|
|
s2 = c.d.b.a.a.s(str, " ");
|
|
}
|
|
if (z2) {
|
|
s2 = c.d.b.a.a.p(s2, nanos2, " nanoseconds ");
|
|
}
|
|
sb = c.d.b.a.a.s(s2, "delay)");
|
|
}
|
|
if (isDone()) {
|
|
throw new TimeoutException(c.d.b.a.a.s(sb, " but future completed as timeout expired"));
|
|
}
|
|
throw new TimeoutException(c.d.b.a.a.t(sb, " for ", abstractResolvableFuture));
|
|
}
|
|
throw new InterruptedException();
|
|
}
|
|
|
|
public void interruptTask() {
|
|
}
|
|
|
|
@Override // java.util.concurrent.Future
|
|
public final boolean isCancelled() {
|
|
return this.value instanceof Cancellation;
|
|
}
|
|
|
|
@Override // java.util.concurrent.Future
|
|
public final boolean isDone() {
|
|
Object obj = this.value;
|
|
return (!(obj instanceof SetFuture)) & (obj != null);
|
|
}
|
|
|
|
public final void maybePropagateCancellationTo(@Nullable Future<?> future) {
|
|
if ((future != null) && isCancelled()) {
|
|
future.cancel(wasInterrupted());
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
public String pendingToString() {
|
|
Object obj = this.value;
|
|
if (obj instanceof SetFuture) {
|
|
return c.d.b.a.a.C(c.d.b.a.a.K("setFuture=["), userObjectToString(((SetFuture) obj).future), "]");
|
|
}
|
|
if (!(this instanceof ScheduledFuture)) {
|
|
return null;
|
|
}
|
|
StringBuilder K = c.d.b.a.a.K("remaining delay=[");
|
|
K.append(((ScheduledFuture) this).getDelay(TimeUnit.MILLISECONDS));
|
|
K.append(" ms]");
|
|
return K.toString();
|
|
}
|
|
|
|
public boolean set(@Nullable V v) {
|
|
if (v == null) {
|
|
v = (V) NULL;
|
|
}
|
|
if (!ATOMIC_HELPER.casValue(this, null, v)) {
|
|
return false;
|
|
}
|
|
complete(this);
|
|
return true;
|
|
}
|
|
|
|
public boolean setException(Throwable th) {
|
|
if (!ATOMIC_HELPER.casValue(this, null, new Failure((Throwable) checkNotNull(th)))) {
|
|
return false;
|
|
}
|
|
complete(this);
|
|
return true;
|
|
}
|
|
|
|
public boolean setFuture(a<? extends V> aVar) {
|
|
SetFuture setFuture;
|
|
Failure failure;
|
|
checkNotNull(aVar);
|
|
Object obj = this.value;
|
|
if (obj == null) {
|
|
if (aVar.isDone()) {
|
|
if (!ATOMIC_HELPER.casValue(this, null, getFutureValue(aVar))) {
|
|
return false;
|
|
}
|
|
complete(this);
|
|
return true;
|
|
}
|
|
setFuture = new SetFuture(this, aVar);
|
|
if (ATOMIC_HELPER.casValue(this, null, setFuture)) {
|
|
try {
|
|
aVar.addListener(setFuture, DirectExecutor.INSTANCE);
|
|
} catch (Throwable unused) {
|
|
failure = Failure.FALLBACK_INSTANCE;
|
|
}
|
|
return true;
|
|
}
|
|
obj = this.value;
|
|
}
|
|
if (obj instanceof Cancellation) {
|
|
aVar.cancel(((Cancellation) obj).wasInterrupted);
|
|
}
|
|
return false;
|
|
ATOMIC_HELPER.casValue(this, setFuture, failure);
|
|
return true;
|
|
}
|
|
|
|
@Override // java.lang.Object
|
|
public String toString() {
|
|
String str;
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append(super.toString());
|
|
sb.append("[status=");
|
|
if (isCancelled()) {
|
|
sb.append("CANCELLED");
|
|
} else if (isDone()) {
|
|
addDoneString(sb);
|
|
} else {
|
|
try {
|
|
str = pendingToString();
|
|
} catch (RuntimeException e) {
|
|
StringBuilder K = c.d.b.a.a.K("Exception thrown from implementation: ");
|
|
K.append(e.getClass());
|
|
str = K.toString();
|
|
}
|
|
if (str != null && !str.isEmpty()) {
|
|
sb.append("PENDING, info=[");
|
|
sb.append(str);
|
|
sb.append("]");
|
|
} else if (isDone()) {
|
|
addDoneString(sb);
|
|
} else {
|
|
sb.append("PENDING");
|
|
}
|
|
}
|
|
sb.append("]");
|
|
return sb.toString();
|
|
}
|
|
|
|
public final boolean wasInterrupted() {
|
|
Object obj = this.value;
|
|
return (obj instanceof Cancellation) && ((Cancellation) obj).wasInterrupted;
|
|
}
|
|
}
|