geforkt von Mirrors/Velocity
Improve native initialization logic, again
Dieser Commit ist enthalten in:
Ursprung
e75ec71b32
Commit
fc48db62b5
@ -16,13 +16,14 @@ public class NativeCodeLoader<T> implements Supplier<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T get() {
|
public T get() {
|
||||||
if (selected == null) {
|
return tryLoad().object;
|
||||||
selected = tryLoad();
|
|
||||||
}
|
|
||||||
return selected.object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Variant<T> tryLoad() {
|
private Variant<T> tryLoad() {
|
||||||
|
if (selected != null) {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (selected != null) {
|
if (selected != null) {
|
||||||
return selected;
|
return selected;
|
||||||
@ -41,18 +42,15 @@ public class NativeCodeLoader<T> implements Supplier<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getLoadedVariant() {
|
public String getLoadedVariant() {
|
||||||
if (selected == null) {
|
return tryLoad().name;
|
||||||
selected = tryLoad();
|
|
||||||
}
|
|
||||||
return selected.name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Variant<T> {
|
static class Variant<T> {
|
||||||
private boolean available;
|
private volatile boolean available;
|
||||||
private final Runnable setup;
|
private final Runnable setup;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final T object;
|
private final T object;
|
||||||
private boolean hasBeenSetup = false;
|
private volatile boolean hasBeenSetup = false;
|
||||||
|
|
||||||
Variant(BooleanSupplier available, Runnable setup, String name, T object) {
|
Variant(BooleanSupplier available, Runnable setup, String name, T object) {
|
||||||
this.available = available.getAsBoolean();
|
this.available = available.getAsBoolean();
|
||||||
@ -61,27 +59,34 @@ public class NativeCodeLoader<T> implements Supplier<T> {
|
|||||||
this.object = object;
|
this.object = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setup() {
|
public T get() {
|
||||||
if (available && !hasBeenSetup) {
|
if (!available) {
|
||||||
try {
|
return null;
|
||||||
setup.run();
|
}
|
||||||
hasBeenSetup = true;
|
|
||||||
} catch (Exception e) {
|
// Make sure setup happens only once
|
||||||
available = false;
|
if (!hasBeenSetup) {
|
||||||
|
synchronized (this) {
|
||||||
|
// We change availability if need be below, may as well check it again here for sanity.
|
||||||
|
if (!available) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Okay, now try the setup if we haven't done so yet.
|
||||||
|
if (!hasBeenSetup) {
|
||||||
|
try {
|
||||||
|
setup.run();
|
||||||
|
hasBeenSetup = true;
|
||||||
|
return object;
|
||||||
|
} catch (Exception e) {
|
||||||
|
available = false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public T get() {
|
return object;
|
||||||
if (!hasBeenSetup) {
|
|
||||||
setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (available) {
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren