-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c2dcaf2
commit 0631e7c
Showing
1 changed file
with
70 additions
and
0 deletions.
There are no files selected for viewing
70 changes: 70 additions & 0 deletions
70
kohlschutter-util/src/main/java/com/kohlschutter/util/Lazy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package com.kohlschutter.util; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.ExecutionException; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
import java.util.function.Supplier; | ||
|
||
/** | ||
* Wrapper for a lazy-initialized object. | ||
* | ||
* @param <V> The object type. | ||
* @author Christian Kohlschütter | ||
*/ | ||
public final class Lazy<V> { | ||
private final CompletableFuture<V> future = new CompletableFuture<V>(); | ||
private final AtomicBoolean supplied = new AtomicBoolean(); | ||
private final Supplier<V> supplier; | ||
|
||
/** | ||
* Creates a lazy-load wrapper, using the given supplier to supply the object upon the first call | ||
* to {@link #get()}. | ||
* | ||
* @param <V> The object type. | ||
* @param supplier The object supplier. | ||
* @return The wrapper instance. | ||
*/ | ||
public static final <V> Lazy<V> of(Supplier<V> supplier) { | ||
return new Lazy<>(supplier); | ||
} | ||
|
||
private Lazy(Supplier<V> supplier) { | ||
this.supplier = supplier; | ||
} | ||
|
||
/** | ||
* Returns the object. If this is the first call, the object is retrieved from the configured | ||
* supplier, and transitions this instance to a completed satate. | ||
* | ||
* @return The object. | ||
*/ | ||
public V get() { | ||
if (!future.isDone() && supplied.compareAndSet(false, true)) { | ||
future.complete(supplier.get()); | ||
} | ||
try { | ||
return future.get(); | ||
} catch (InterruptedException | ExecutionException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
/** | ||
* If not already completed, sets the value returned by {@link #get()} and related methods to the | ||
* given value, side-stepping the value that would be retrieved from the supplier. | ||
* | ||
* @param value the result value | ||
* @return {@code true} if this invocation caused this instance to transition to a completed | ||
* state, else {@code false} | ||
*/ | ||
public boolean complete(V value) { | ||
supplied.set(true); // NOTE: We do not compareAndSet here to allow #set from within supplier.get | ||
return future.complete(value); | ||
} | ||
|
||
@SuppressWarnings("null") | ||
@Override | ||
public String toString() { | ||
return super.toString() + "[supplied=" + supplied + "; value=" + future.getNow(null) + "]"; | ||
} | ||
} |