From 0728b0eb0f2dbd037b4b371048803b205640ae38 Mon Sep 17 00:00:00 2001 From: franz1981 Date: Mon, 3 Jul 2023 14:49:30 +0200 Subject: [PATCH] Save performing volatile set on LazyValue::set/clear --- .../java/io/quarkus/arc/impl/LazyValue.java | 21 +++++++++++++++---- .../main/java/io/quarkus/qute/LazyValue.java | 21 +++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LazyValue.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LazyValue.java index 5c383b25516eb..2618a82938d65 100644 --- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LazyValue.java +++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LazyValue.java @@ -1,5 +1,6 @@ package io.quarkus.arc.impl; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.function.Supplier; /** @@ -8,6 +9,9 @@ */ public class LazyValue { + private static final AtomicReferenceFieldUpdater VALUE_UPDATER = AtomicReferenceFieldUpdater + .newUpdater(LazyValue.class, Object.class, "value"); + private final Supplier supplier; private transient volatile T value; @@ -22,10 +26,14 @@ public T get() { return valueCopy; } synchronized (this) { - if (value == null) { - value = supplier.get(); + valueCopy = value; + if (valueCopy != null) { + return valueCopy; } - return value; + valueCopy = supplier.get(); + // lazySet == setRelease: it ensure safe publication of the instance + VALUE_UPDATER.lazySet(this, valueCopy); + return valueCopy; } } @@ -34,8 +42,13 @@ public T getIfPresent() { } public void clear() { + if (value == null) { + return; + } synchronized (this) { - value = null; + if (value != null) { + VALUE_UPDATER.lazySet(this, null); + } } } diff --git a/independent-projects/qute/core/src/main/java/io/quarkus/qute/LazyValue.java b/independent-projects/qute/core/src/main/java/io/quarkus/qute/LazyValue.java index 53f3195feedba..713f83998ee56 100644 --- a/independent-projects/qute/core/src/main/java/io/quarkus/qute/LazyValue.java +++ b/independent-projects/qute/core/src/main/java/io/quarkus/qute/LazyValue.java @@ -1,9 +1,13 @@ package io.quarkus.qute; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.function.Supplier; final class LazyValue { + private static final AtomicReferenceFieldUpdater VALUE_UPDATER = AtomicReferenceFieldUpdater + .newUpdater(LazyValue.class, Object.class, "value"); + private final Supplier supplier; private transient volatile T value; @@ -18,10 +22,14 @@ public T get() { return valueCopy; } synchronized (this) { - if (value == null) { - value = supplier.get(); + valueCopy = value; + if (valueCopy != null) { + return valueCopy; } - return value; + valueCopy = supplier.get(); + // lazySet == setRelease: it ensure safe publication of the instance + VALUE_UPDATER.lazySet(this, valueCopy); + return valueCopy; } } @@ -30,8 +38,13 @@ public T getIfPresent() { } public void clear() { + if (value == null) { + return; + } synchronized (this) { - value = null; + if (value != null) { + VALUE_UPDATER.lazySet(this, null); + } } }