13
0
geforkt von Mirrors/Velocity

Improve native initialization logic, again

Dieser Commit ist enthalten in:
Andrew Steinborn 2018-09-17 15:02:49 -04:00
Ursprung e75ec71b32
Commit fc48db62b5

Datei anzeigen

@ -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;
} }
} }