diff --git a/server/src/main/java/org/elasticsearch/action/ActionListener.java b/server/src/main/java/org/elasticsearch/action/ActionListener.java index 8d66ffd9c058a..26ad669e50223 100644 --- a/server/src/main/java/org/elasticsearch/action/ActionListener.java +++ b/server/src/main/java/org/elasticsearch/action/ActionListener.java @@ -275,29 +275,7 @@ static ActionListener runBefore(ActionListener de * and {@link #onFailure(Exception)} of the provided listener will be called at most once. */ static ActionListener notifyOnce(ActionListener delegate) { - final var delegateRef = new AtomicReference<>(delegate); - return new ActionListener<>() { - @Override - public void onResponse(Response response) { - final var acquired = delegateRef.getAndSet(null); - if (acquired != null) { - acquired.onResponse(response); - } - } - - @Override - public void onFailure(Exception e) { - final var acquired = delegateRef.getAndSet(null); - if (acquired != null) { - safeOnFailure(acquired, e); - } - } - - @Override - public String toString() { - return "notifyOnce[" + delegateRef.get() + "]"; - } - }; + return new ActionListenerImplementations.NotifyOnceActionListener<>(delegate); } /** diff --git a/server/src/main/java/org/elasticsearch/action/ActionListenerImplementations.java b/server/src/main/java/org/elasticsearch/action/ActionListenerImplementations.java index d699558cb15ed..cf8c64c4ba66d 100644 --- a/server/src/main/java/org/elasticsearch/action/ActionListenerImplementations.java +++ b/server/src/main/java/org/elasticsearch/action/ActionListenerImplementations.java @@ -14,6 +14,7 @@ import org.elasticsearch.core.Releasable; import org.elasticsearch.core.Releasables; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -250,4 +251,35 @@ public String toString() { return super.toString() + "/" + runBefore; } } + + // Extend AtomicReference directly for minimum memory overhead and indirection. + static final class NotifyOnceActionListener extends AtomicReference> + implements + ActionListener { + + NotifyOnceActionListener(ActionListener delegate) { + super(delegate); + } + + @Override + public void onResponse(Response response) { + final var acquired = getAndSet(null); + if (acquired != null) { + acquired.onResponse(response); + } + } + + @Override + public void onFailure(Exception e) { + final var acquired = getAndSet(null); + if (acquired != null) { + safeOnFailure(acquired, e); + } + } + + @Override + public String toString() { + return "notifyOnce[" + get() + "]"; + } + } }