Skip to content

Commit

Permalink
Fix concurrency issue in SafeLazy
Browse files Browse the repository at this point in the history
By storing the thunk and the result as final fields of a contained class, we ensure that they will will always be in sync with each other when used, without actually locking anything.
  • Loading branch information
pnf authored and eed3si9n committed Feb 21, 2020
1 parent b8a0dd5 commit 87c74a9
Showing 1 changed file with 18 additions and 18 deletions.
36 changes: 18 additions & 18 deletions internal/compiler-interface/src/main/java/xsbti/api/SafeLazy.java
Expand Up @@ -42,30 +42,30 @@ public T get() {
});
}

private static final class Impl<T> extends xsbti.api.AbstractLazy<T> {
private Supplier<T> thunk = null;
private T result = null;

Impl(Supplier<T> thunk) {
private static final class Thunky<T> {
final Supplier<T> thunk;
final T result;
Thunky(Supplier<T> thunk, T result) {
this.thunk = thunk;
this.result = result;
}
}

/**
* Return cached result or force lazy evaluation.
*
* Don't call it in a multi-threaded environment.
*/
public synchronized T get() {
if (thunk == null) return result;
else {
result = thunk.get();
private static final class Impl<T> extends xsbti.api.AbstractLazy<T> {
private Thunky<T> thunky;

thunk = null; // also allows it to be GC'ed
Impl(Supplier<T> thunk) {
this.thunky = new Thunky(thunk, null);
}

return result;
public T get() {
Thunky<T> t = thunky;
if (t.result == null) {
T r = t.thunk.get();
t = new Thunky(null, r);
thunky = t;
}
return t.result;
}
}
}


0 comments on commit 87c74a9

Please sign in to comment.