Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
mariofusco committed Jun 27, 2024
1 parent 8a14d9b commit 2eec9a3
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,10 @@ static <T> T withJarFile(JarResource jarResource, String resource, JarFileConsum

// Happy path: the jar reference already exists and it's ready to be used
final var localJarFileRefFuture = jarResource.jarFileReference.get();
if (localJarFileRefFuture != null) {
if (localJarFileRefFuture.join().acquire()) {
return consumeSharedJarFile(localJarFileRefFuture, jarResource, resource, fileConsumer);
if (localJarFileRefFuture != null && localJarFileRefFuture.isDone()) {
JarFileReference jarFileReference = localJarFileRefFuture.join();
if (jarFileReference.acquire()) {
return consumeSharedJarFile(jarFileReference, jarResource, resource, fileConsumer);
}
}

Expand All @@ -103,7 +104,8 @@ static <T> T withJarFile(JarResource jarResource, String resource, JarFileConsum
// Platform threads can load the jarfile asynchronously and eventually blocking till not ready
// to avoid loading the same jarfile multiple times in parallel
if (!isVirtualThread()) {
return consumeSharedJarFile(asyncLoadAcquiredJarFile(jarResource), jarResource, resource, fileConsumer);
// It's ok to eventually block on a join() here since we're sure this is used only by platform thread
return consumeSharedJarFile(asyncLoadAcquiredJarFile(jarResource).join(), jarResource, resource, fileConsumer);
}

// Virtual threads needs to load the jarfile synchronously to avoid blocking. This means that eventually
Expand All @@ -112,16 +114,16 @@ static <T> T withJarFile(JarResource jarResource, String resource, JarFileConsum
if (jarResource.jarFileReference.compareAndSet(localJarFileRefFuture, newJarFileRef) ||
jarResource.jarFileReference.compareAndSet(null, newJarFileRef)) {
// The new file reference has been successfully published and can be used by the current and other threads
return consumeSharedJarFile(newJarFileRef, jarResource, resource, fileConsumer);
// The join() cannot be blocking here since the CompletableFuture has been created already completed
return consumeSharedJarFile(newJarFileRef.join(), jarResource, resource, fileConsumer);
}

// The newly created file reference hasn't been published, so it can be used exclusively by the current virtual thread
return consumeUnsharedJarFile(newJarFileRef, jarResource, resource, fileConsumer);
}

private static <T> T consumeSharedJarFile(CompletableFuture<JarFileReference> jarFileReferenceFuture,
private static <T> T consumeSharedJarFile(JarFileReference jarFileReference,
JarResource jarResource, String resource, JarFileConsumer<T> fileConsumer) {
JarFileReference jarFileReference = jarFileReferenceFuture.join();
try {
return fileConsumer.apply(jarFileReference.jarFile, jarResource.jarPath, resource);
} finally {
Expand Down Expand Up @@ -165,13 +167,11 @@ private static CompletableFuture<JarFileReference> asyncLoadAcquiredJarFile(JarR
private static CompletableFuture<JarFileReference> getJarFileReferenceFuture(JarResource jarResource) {
CompletableFuture future = new CompletableFuture();
if (jarResource.jarFileReference.compareAndSet(null, future)) {
future.completeAsync(() -> {
try {
return new JarFileReference(JarFiles.create(jarResource.jarPath.toFile()), false);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
try {
future.complete(new JarFileReference(JarFiles.create(jarResource.jarPath.toFile()), false));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return jarResource.jarFileReference.get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,13 @@ public ProtectionDomain getProtectionDomain() {

@Override
public void close() {
var ref = jarFileReference.get();
if (ref != null) {
ref.join().close(this);
var futureRef = jarFileReference.get();
if (futureRef != null) {
// The jarfile has been already used and it's going to be removed from the cache,
// so the future must be already completed
var ref = futureRef.getNow(null);
assert (ref != null);
ref.close(this);
}
}

Expand Down

0 comments on commit 2eec9a3

Please sign in to comment.