You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@logging.apache.org by Matt Sicker <ma...@apache.org> on 2022/11/18 04:14:30 UTC

Re: [logging-log4j2] branch master updated: Add Lazy::pure for pure reified values

Oops, “reified” should say “memoized”. You get the idea.
—
Matt Sicker

> On Nov 17, 2022, at 22:12, mattsicker@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 <ma...@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 <ma...@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) {
>