final promise optimization

This commit is contained in:
tommyskeff
2025-01-07 14:51:37 +00:00
parent fbeef9833b
commit e10db36a63

View File

@@ -11,37 +11,36 @@ import org.slf4j.Logger;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle; import java.lang.invoke.VarHandle;
import java.util.Collection; import java.util.*;
import java.util.Collections;
import java.util.Iterator;
import java.util.Objects;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.function.Consumer; import java.util.function.Consumer;
@SuppressWarnings({"FieldMayBeFinal", "unchecked"})
public abstract class AbstractPromise<T, FS, FA> implements CompletablePromise<T> { public abstract class AbstractPromise<T, FS, FA> implements CompletablePromise<T> {
private static final VarHandle COMPLETION_HANDLE; private static final VarHandle COMPLETION_HANDLE;
private static final VarHandle LISTENERS_HANDLE;
static { static {
try { try {
MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandles.Lookup lookup = MethodHandles.lookup();
COMPLETION_HANDLE = lookup.findVarHandle(AbstractPromise.class, "completion", PromiseCompletion.class); COMPLETION_HANDLE = lookup.findVarHandle(AbstractPromise.class, "completion", PromiseCompletion.class);
LISTENERS_HANDLE = lookup.findVarHandle(AbstractPromise.class, "listeners", Collection.class);
} catch (ReflectiveOperationException e) { } catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e); throw new ExceptionInInitializerError(e);
} }
} }
private final AtomicReference<Collection<PromiseListener<T>>> listeners;
private final Sync sync; private final Sync sync;
@SuppressWarnings("FieldMayBeFinal") private volatile Collection<PromiseListener<T>> listeners;
private volatile PromiseCompletion<T> completion; private volatile PromiseCompletion<T> completion;
public AbstractPromise() { public AbstractPromise() {
this.listeners = new AtomicReference<>(Collections.emptyList());
this.sync = new Sync(); this.sync = new Sync();
this.listeners = Collections.EMPTY_LIST;
this.completion = null; this.completion = null;
} }
@@ -400,13 +399,20 @@ public abstract class AbstractPromise<T, FS, FA> implements CompletablePromise<T
} }
private @NotNull Promise<T> addAnyListener(PromiseListener<T> listener) { private @NotNull Promise<T> addAnyListener(PromiseListener<T> listener) {
Collection<PromiseListener<T>> res = listeners.updateAndGet(v -> { Collection<PromiseListener<T>> prev = listeners, next = null;
if (v == Collections.EMPTY_LIST) v = new ConcurrentLinkedQueue<>(); for (boolean haveNext = false;;) {
if (v != null) v.add(listener); if (!haveNext) {
return v; next = prev == Collections.EMPTY_LIST ? new ConcurrentLinkedQueue<>() : prev;
}); if (next != null) next.add(listener);
}
if (res == null) { if (LISTENERS_HANDLE.weakCompareAndSet(this, prev, next))
break;
haveNext = (prev == (prev = listeners));
}
if (next == null) {
if (listener instanceof AsyncPromiseListener) { if (listener instanceof AsyncPromiseListener) {
callListenerAsync(listener, Objects.requireNonNull(getCompletion())); callListenerAsync(listener, Objects.requireNonNull(getCompletion()));
} else { } else {
@@ -492,7 +498,8 @@ public abstract class AbstractPromise<T, FS, FA> implements CompletablePromise<T
if (!COMPLETION_HANDLE.compareAndSet(this, null, cmp)) return; if (!COMPLETION_HANDLE.compareAndSet(this, null, cmp)) return;
sync.releaseShared(1); sync.releaseShared(1);
Iterator<PromiseListener<T>> iter = listeners.getAndSet(null).iterator();
Iterator<PromiseListener<T>> iter = ((Iterable<PromiseListener<T>>) LISTENERS_HANDLE.getAndSet(this, null)).iterator();
try { try {
while (iter.hasNext()) { while (iter.hasNext()) {
PromiseListener<T> listener = iter.next(); PromiseListener<T> listener = iter.next();