diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/Suppliers.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/Suppliers.java new file mode 100644 index 0000000000..59ccd7782f --- /dev/null +++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/Suppliers.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.activemq.artemis.utils; + +import java.io.Serializable; +import java.util.function.Supplier; + +public class Suppliers { + + /** + * Returns a supplier which caches the instance retrieved during the first + * call to {@code get()} and returns that value on subsequent calls to + * {@code get()}. See: + * memoization + * + *

The returned supplier is thread-safe. The delegate's {@code get()} + * method will be invoked at most once. The supplier's serialized form does + * not contain the cached value, which will be recalculated when {@code get()} + * is called on the reserialized instance. + * + *

If {@code delegate} is an instance created by an earlier call to {@code + * memoize}, it is returned directly. + */ + public static Supplier memoize(Supplier delegate) { + return (delegate instanceof MemoizingSupplier) + ? delegate + : new MemoizingSupplier(checkNotNull(delegate)); + } + + private static class MemoizingSupplier implements Supplier, Serializable { + final Supplier delegate; + transient volatile boolean initialized; + // "value" does not need to be volatile; visibility piggy-backs + // on volatile read of "initialized". + transient T value; + + MemoizingSupplier(Supplier delegate) { + this.delegate = delegate; + } + + @Override + public T get() { + // A 2-field variant of Double Checked Locking. + if (!initialized) { + synchronized (this) { + if (!initialized) { + T t = delegate.get(); + value = t; + initialized = true; + return t; + } + } + } + return value; + } + + @Override + public String toString() { + return "Suppliers.memoize(" + delegate + ")"; + } + + private static final long serialVersionUID = 0; + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } +} diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/message/impl/CoreMessageObjectPools.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/message/impl/CoreMessageObjectPools.java index d4e3ed1659..7ee7d0a0b4 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/message/impl/CoreMessageObjectPools.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/message/impl/CoreMessageObjectPools.java @@ -16,11 +16,13 @@ */ package org.apache.activemq.artemis.core.message.impl; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; + import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.utils.Suppliers; import org.apache.activemq.artemis.utils.collections.TypedProperties; +import java.util.function.Supplier; + public class CoreMessageObjectPools { private Supplier addressDecoderPool = Suppliers.memoize(SimpleString.ByteBufSimpleStringPool::new);