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) {
> 

Reply via email to