From e10db36a63b176daa17ee5a51ed149ed7cdab55c Mon Sep 17 00:00:00 2001 From: tommyskeff Date: Tue, 7 Jan 2025 14:51:37 +0000 Subject: [PATCH] final promise optimization --- .../futur/promise/AbstractPromise.java | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 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 526f242..c0538e2 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 @@ -11,37 +11,36 @@ 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.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.function.Consumer; +@SuppressWarnings({"FieldMayBeFinal", "unchecked"}) public abstract class AbstractPromise implements CompletablePromise { private static final VarHandle COMPLETION_HANDLE; + private static final VarHandle LISTENERS_HANDLE; static { try { MethodHandles.Lookup lookup = MethodHandles.lookup(); COMPLETION_HANDLE = lookup.findVarHandle(AbstractPromise.class, "completion", PromiseCompletion.class); + LISTENERS_HANDLE = lookup.findVarHandle(AbstractPromise.class, "listeners", Collection.class); } catch (ReflectiveOperationException e) { throw new ExceptionInInitializerError(e); } } - private final AtomicReference>> listeners; private final Sync sync; - @SuppressWarnings("FieldMayBeFinal") + private volatile Collection> listeners; private volatile PromiseCompletion completion; public AbstractPromise() { - this.listeners = new AtomicReference<>(Collections.emptyList()); this.sync = new Sync(); + this.listeners = Collections.EMPTY_LIST; this.completion = null; } @@ -400,13 +399,20 @@ public abstract class AbstractPromise implements CompletablePromise addAnyListener(PromiseListener listener) { - Collection> res = listeners.updateAndGet(v -> { - if (v == Collections.EMPTY_LIST) v = new ConcurrentLinkedQueue<>(); - if (v != null) v.add(listener); - return v; - }); + Collection> prev = listeners, next = null; + for (boolean haveNext = false;;) { + if (!haveNext) { + 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) { callListenerAsync(listener, Objects.requireNonNull(getCompletion())); } else { @@ -492,7 +498,8 @@ public abstract class AbstractPromise implements CompletablePromise> iter = listeners.getAndSet(null).iterator(); + + Iterator> iter = ((Iterable>) LISTENERS_HANDLE.getAndSet(this, null)).iterator(); try { while (iter.hasNext()) { PromiseListener listener = iter.next();