From fbeef9833bbceb04f099aa50cfcec331b1fb446b Mon Sep 17 00:00:00 2001 From: tommyskeff Date: Tue, 7 Jan 2025 14:22:33 +0000 Subject: [PATCH] small promise optimizations --- .../futur/promise/AbstractPromise.java | 101 ++++++++++++------ 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromise.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromise.java index f451c7d..526f242 100644 --- a/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromise.java +++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromise.java @@ -9,24 +9,40 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Objects; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.function.Consumer; public abstract class AbstractPromise implements CompletablePromise { + private static final VarHandle COMPLETION_HANDLE; + + static { + try { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + COMPLETION_HANDLE = lookup.findVarHandle(AbstractPromise.class, "completion", PromiseCompletion.class); + } catch (ReflectiveOperationException e) { + throw new ExceptionInInitializerError(e); + } + } + private final AtomicReference>> listeners; - private final AtomicReference> completion; - private final CountDownLatch latch; + private final Sync sync; + + @SuppressWarnings("FieldMayBeFinal") + private volatile PromiseCompletion completion; public AbstractPromise() { this.listeners = new AtomicReference<>(Collections.emptyList()); - this.completion = new AtomicReference<>(); - this.latch = new CountDownLatch(1); + this.sync = new Sync(); + this.completion = null; } public abstract @NotNull AbstractPromiseFactory getFactory(); @@ -60,13 +76,13 @@ public abstract class AbstractPromise implements CompletablePromise implements CompletablePromise implements CompletablePromise ctx) { - if (!setCompletion(ctx)) return; - latch.countDown(); + private void handleCompletion(@NotNull PromiseCompletion cmp) { + if (!COMPLETION_HANDLE.compareAndSet(this, null, cmp)) return; + sync.releaseShared(1); Iterator> iter = listeners.getAndSet(null).iterator(); - while (iter.hasNext()) { - PromiseListener listener = iter.next(); - - try { - if (listener instanceof AsyncPromiseListener) { - callListenerAsync(listener, ctx); - } else { - callListenerNow(listener, ctx); - } - } finally { - iter.forEachRemaining(v -> callListenerAsyncLastResort(v, ctx)); - } - } - } - - private void callListenerAsyncLastResort(PromiseListener listener, PromiseCompletion ctx) { try { - getFactory().getAsyncExecutor().run(() -> callListenerNow(listener, ctx)); - } catch (Throwable ignored) { - + while (iter.hasNext()) { + PromiseListener listener = iter.next(); + if (listener instanceof AsyncPromiseListener) { + callListenerAsync(listener, cmp); + } else { + callListenerNow(listener, cmp); + } + } + } finally { + iter.forEachRemaining(v -> callListenerAsyncLastResort(v, cmp)); } } - private boolean setCompletion(PromiseCompletion completion) { - return this.completion.compareAndSet(null, completion); + private void callListenerAsyncLastResort(PromiseListener listener, PromiseCompletion completion) { + try { + getFactory().getAsyncExecutor().run(() -> callListenerNow(listener, completion)); + } catch (Throwable ignored) {} } @Override @@ -521,12 +530,12 @@ public abstract class AbstractPromise implements CompletablePromise getCompletion() { - return completion.get(); + return completion; } @Override @@ -543,7 +552,33 @@ public abstract class AbstractPromise implements CompletablePromise