Skip to contentMethod: get()
1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * TheseFoolishThings: Miscellaneous utilities
5: * http://tidalwave.it/projects/thesefoolishthings
6: *
7: * Copyright (C) 2009 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * 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
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
22: * git clone https://github.com/tidalwave-it/thesefoolishthings-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.util;
27:
28: // import javax.annotation.concurrent.ThreadSafe;
29: import jakarta.annotation.Nonnull;
30: import java.util.concurrent.atomic.AtomicBoolean;
31: import java.util.concurrent.atomic.AtomicReference;
32: import java.util.function.Supplier;
33: import it.tidalwave.util.annotation.VisibleForTesting;
34: import lombok.EqualsAndHashCode;
35: import lombok.Getter;
36: import lombok.RequiredArgsConstructor;
37:
38: /***************************************************************************************************************************************************************
39: *
40: * A supplier of an object that is lazily evaluated (when its value is requested for the first time). It warranties
41: * that the real wrapped supplier is called only once.
42: *
43: * @author Fabrizio Giudici
44: * @since 3.2-ALPHA-13
45: *
46: **************************************************************************************************************************************************************/
47: /* @ThreadSafe */ @RequiredArgsConstructor(staticName = "of") @EqualsAndHashCode(of = {"ref", "initialized"})
48: public class LazySupplier<T> implements Supplier<T>
49: {
50: @Nonnull
51: private final Supplier<T> supplier;
52:
53: @VisibleForTesting final AtomicReference<T> ref = new AtomicReference<>(null);
54:
55: @Getter
56: @VisibleForTesting final AtomicBoolean initialized = new AtomicBoolean(false);
57:
58: /** {@inheritDoc} */
59: @Override @Nonnull
60: public synchronized T get()
61: {
62: // AtomicReference.updateAndGet() not good because in case of contention it might call supplier multiple times
63: // We don't mess with double check for null since nowadays synchronized is fast
64:• if (ref.get() == null)
65: {
66: ref.set(supplier.get());
67: initialized.set(true);
68: }
69:
70: return ref.get();
71: }
72:
73: public synchronized void clear()
74: {
75: ref.set(null);
76: }
77:
78: public synchronized void set (@Nonnull final T ref)
79: {
80: this.ref.set(ref);
81: }
82:
83: @Nonnull
84: public String toString()
85: {
86: return String.format("LazySupplier(%s)", (ref.get() == null && !initialized.get()) ? "<not initialised>" : ref.get());
87: }
88: }