Oops, “reified” should say “memoized”. You get the idea. — Matt Sicker
> On Nov 17, 2022, at 22:12, mattsic...@apache.org wrote: > > This is an automated email from the ASF dual-hosted git repository. > > mattsicker pushed a commit to branch master > in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git > > > The following commit(s) were added to refs/heads/master by this push: > new 2986332a90 Add Lazy::pure for pure reified values > 2986332a90 is described below > > commit 2986332a90e10d14547faf8729e19ec7ff01c622 > Author: Matt Sicker <mattsic...@apache.org> > AuthorDate: Thu Nov 17 22:10:29 2022 -0600 > > Add Lazy::pure for pure reified values > > This adds a Lazy variant where the supplier function is a pure function. > Given a pure function, memory reordering semantics are mostly irrelevant, so > this can both safely recompute the value and publish more than one resulting > computed reference as the results should all be the same value. > > This updates JSON encoding cache tables to use Lazy::pure. > > Signed-off-by: Matt Sicker <mattsic...@apache.org> > --- > .../java/org/apache/logging/log4j/util/Lazy.java | 13 ++++++++++ > .../org/apache/logging/log4j/util/LazyUtil.java | 29 ++++++++++++++++++++++ > .../apache/logging/log4j/core/util/JsonUtils.java | 2 +- > .../layout/template/json/util/JsonWriter.java | 2 +- > 4 files changed, 44 insertions(+), 2 deletions(-) > > diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/Lazy.java > b/log4j-api/src/main/java/org/apache/logging/log4j/util/Lazy.java > index ec3edb5b61..1c08f6d8d8 100644 > --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/Lazy.java > +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/Lazy.java > @@ -16,6 +16,7 @@ > */ > package org.apache.logging.log4j.util; > > +import java.util.Objects; > import java.util.function.Function; > import java.util.function.Supplier; > > @@ -44,6 +45,7 @@ public interface Lazy<T> extends Supplier<T> { > * Creates a lazy value using the provided Supplier for initialization > guarded by a Lock. > */ > static <T> Lazy<T> lazy(final Supplier<T> supplier) { > + Objects.requireNonNull(supplier); > return new LazyUtil.SafeLazy<>(supplier); > } > > @@ -59,6 +61,17 @@ public interface Lazy<T> extends Supplier<T> { > * in order to set the initialized value. > */ > static <T> Lazy<T> relaxed(final Supplier<T> supplier) { > + Objects.requireNonNull(supplier); > return new LazyUtil.ReleaseAcquireLazy<>(supplier); > } > + > + /** > + * Creates a pure lazy value using the provided Supplier to initialize > the value. The supplier may be invoked more > + * than once, and the return value should be a purely computed value as > the result may be a different instance > + * each time. This is useful for building cache tables and other pure > computations. > + */ > + static <T> Lazy<T> pure(final Supplier<T> supplier) { > + Objects.requireNonNull(supplier); > + return new LazyUtil.PureLazy<>(supplier); > + } > } > diff --git > a/log4j-api/src/main/java/org/apache/logging/log4j/util/LazyUtil.java > b/log4j-api/src/main/java/org/apache/logging/log4j/util/LazyUtil.java > index a75935ea8c..0150aaf289 100644 > --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/LazyUtil.java > +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/LazyUtil.java > @@ -162,4 +162,33 @@ final class LazyUtil { > return isInitialized() ? String.valueOf(VALUE.getOpaque(value)) : > "Lazy value not initialized"; > } > } > + > + static class PureLazy<T> implements Lazy<T> { > + private final Supplier<T> supplier; > + private Object value; > + > + public PureLazy(final Supplier<T> supplier) { > + this.supplier = supplier; > + } > + > + @Override > + public T value() { > + Object value = this.value; > + if (value == null) { > + value = supplier.get(); > + this.value = wrapNull(value); > + } > + return unwrapNull(value); > + } > + > + @Override > + public boolean isInitialized() { > + return value != null; > + } > + > + @Override > + public void set(final T newValue) { > + value = newValue; > + } > + } > } > diff --git > a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java > b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java > index 3815967aeb..fede436bb2 100644 > --- > a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java > +++ > b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/JsonUtils.java > @@ -31,7 +31,7 @@ public final class JsonUtils { > * to use after backslash; and negative values that generic (backslash - > u) > * escaping is to be used. > */ > - private static final Lazy<int[]> ESC_CODES = Lazy.relaxed(() -> { > + private static final Lazy<int[]> ESC_CODES = Lazy.pure(() -> { > final int[] table = new int[128]; > // Control chars need generic escape sequence > for (int i = 0; i < 32; ++i) { > diff --git > a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java > > b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java > index 3ca6dc625a..0b987584a4 100644 > --- > a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java > +++ > b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java > @@ -67,7 +67,7 @@ public final class JsonWriter implements AutoCloseable, > Cloneable { > * character to use after backslash; and negative values, that generic > * (backslash - u) escaping is to be used. > */ > - private static final Lazy<int[]> ESC_CODES = Lazy.relaxed(() -> { > + private static final Lazy<int[]> ESC_CODES = Lazy.pure(() -> { > final int[] table = new int[128]; > // Control chars need generic escape sequence > for (int i = 0; i < 32; ++i) { >