Improve native initialization logic

This uses the double-check pattern as recommended in Effective Java.
This commit is contained in:
Andrew Steinborn
2018-09-17 01:03:07 -04:00
parent 9c05203ce8
commit e75ec71b32

View File

@@ -8,7 +8,7 @@ import java.util.function.Supplier;
public class NativeCodeLoader<T> implements Supplier<T> { public class NativeCodeLoader<T> implements Supplier<T> {
private final List<Variant<T>> variants; private final List<Variant<T>> variants;
private Variant<T> selected; private volatile Variant<T> selected;
public NativeCodeLoader(List<Variant<T>> variants) { public NativeCodeLoader(List<Variant<T>> variants) {
this.variants = ImmutableList.copyOf(variants); this.variants = ImmutableList.copyOf(variants);
@@ -17,25 +17,32 @@ public class NativeCodeLoader<T> implements Supplier<T> {
@Override @Override
public T get() { public T get() {
if (selected == null) { if (selected == null) {
selected = select(); selected = tryLoad();
} }
return selected.object; return selected.object;
} }
private Variant<T> select() { private Variant<T> tryLoad() {
for (Variant<T> variant : variants) { synchronized (this) {
T got = variant.get(); if (selected != null) {
if (got == null) { return selected;
continue;
} }
return variant;
for (Variant<T> variant : variants) {
T got = variant.get();
if (got == null) {
continue;
}
selected = variant;
return selected;
}
throw new IllegalArgumentException("Can't find any suitable variants");
} }
throw new IllegalArgumentException("Can't find any suitable variants");
} }
public String getLoadedVariant() { public String getLoadedVariant() {
if (selected == null) { if (selected == null) {
selected = select(); selected = tryLoad();
} }
return selected.name; return selected.name;
} }