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 <[email protected]>
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 <[email protected]>
---
 .../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