From d19d310fd96882a0f9927d50313bace048f73057 Mon Sep 17 00:00:00 2001 From: FalsePattern <30945458+FalsePattern@users.noreply.github.com> Date: Fri, 10 Jun 2022 03:08:15 +0200 Subject: [PATCH] deadlock avoidance --- .../lib/internal/proxy/ClientProxy.java | 67 ++++++++++++------- .../lib/internal/proxy/CommonProxy.java | 19 ++++-- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/falsepattern/lib/internal/proxy/ClientProxy.java b/src/main/java/com/falsepattern/lib/internal/proxy/ClientProxy.java index ab6ad54..a334361 100644 --- a/src/main/java/com/falsepattern/lib/internal/proxy/ClientProxy.java +++ b/src/main/java/com/falsepattern/lib/internal/proxy/ClientProxy.java @@ -19,7 +19,9 @@ import net.minecraftforge.event.entity.EntityJoinWorldEvent; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Callable; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; @SideOnly(Side.CLIENT) public class ClientProxy extends CommonProxy { @@ -34,33 +36,46 @@ public class ClientProxy extends CommonProxy { @Override public void postInit(FMLPostInitializationEvent e) { super.postInit(e); - chatFuture = Async.asyncWorker.submit(() -> { - val updates = updatesFuture.get(); - if (updates == null || updates.size() == 0) return null; - val updateText = new ArrayList(FormattedText.parse(I18n.format("falsepatternlib.chat.updatesavailable")).toChatText()); - val mods = Loader.instance().getIndexedModList(); - for (val update : updates) { - val mod = mods.get(update.modID); - updateText.addAll(FormattedText.parse(I18n.format("falsepatternlib.chat.modname", mod.getName())).toChatText()); - updateText.addAll(FormattedText.parse(I18n.format("falsepatternlib.chat.currentversion", update.currentVersion)).toChatText()); - updateText.addAll(FormattedText.parse(I18n.format("falsepatternlib.chat.latestversion", update.latestVersion)).toChatText()); - if (!update.updateURL.isEmpty()) { - val pre = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurlpre")).toChatText(); - val link = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurl")).toChatText(); - val post = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurlpost")).toChatText(); - pre.get(pre.size() - 1).appendSibling(link.get(0)); - link.get(link.size() - 1).appendSibling(post.get(0)); - for (val l: link) { - l.getChatStyle().setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, update.updateURL)); - } - link.remove(0); - post.remove(0); - updateText.addAll(pre); - updateText.addAll(link); - updateText.addAll(post); + chatFuture = Async.asyncWorker.submit(new Callable>() { + @Override + public List call() throws Exception { + //Deadlock avoidance + if (updatesFuture == null || updatesFuture.isCancelled()) { + chatFuture = null; + return null; } + if (!updatesFuture.isDone()) { + chatFuture = Async.asyncWorker.submit(this); + return null; + } + val updates = updatesFuture.get(); + if (updates == null || updates.size() == 0) + return null; + val updateText = new ArrayList(FormattedText.parse(I18n.format("falsepatternlib.chat.updatesavailable")).toChatText()); + val mods = Loader.instance().getIndexedModList(); + for (val update : updates) { + val mod = mods.get(update.modID); + updateText.addAll(FormattedText.parse(I18n.format("falsepatternlib.chat.modname", mod.getName())).toChatText()); + updateText.addAll(FormattedText.parse(I18n.format("falsepatternlib.chat.currentversion", update.currentVersion)).toChatText()); + updateText.addAll(FormattedText.parse(I18n.format("falsepatternlib.chat.latestversion", update.latestVersion)).toChatText()); + if (!update.updateURL.isEmpty()) { + val pre = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurlpre")).toChatText(); + val link = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurl")).toChatText(); + val post = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurlpost")).toChatText(); + pre.get(pre.size() - 1).appendSibling(link.get(0)); + link.get(link.size() - 1).appendSibling(post.get(0)); + for (val l : link) { + l.getChatStyle().setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, update.updateURL)); + } + link.remove(0); + post.remove(0); + updateText.addAll(pre); + updateText.addAll(link); + updateText.addAll(post); + } + } + return updateText; } - return updateText; }); } @@ -70,7 +85,7 @@ public class ClientProxy extends CommonProxy { !(e.entity instanceof EntityPlayerSP)) return; val player = (EntityPlayerSP) e.entity; try { - for (val line: chatFuture.get()) { + for (val line: chatFuture.get(1, TimeUnit.SECONDS)) { player.addChatMessage(line); } chatFuture = null; diff --git a/src/main/java/com/falsepattern/lib/internal/proxy/CommonProxy.java b/src/main/java/com/falsepattern/lib/internal/proxy/CommonProxy.java index 8010849..5bb0d3f 100644 --- a/src/main/java/com/falsepattern/lib/internal/proxy/CommonProxy.java +++ b/src/main/java/com/falsepattern/lib/internal/proxy/CommonProxy.java @@ -16,6 +16,7 @@ import lombok.var; import net.minecraftforge.common.MinecraftForge; import java.util.List; +import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -36,12 +37,22 @@ public class CommonProxy { if (LibraryConfig.ENABLE_UPDATE_CHECKER) { FalsePatternLib.getLog().info("Launching asynchronous update check."); val updateCheckFuture = UpdateChecker.fetchUpdatesAsync("https://falsepattern.com/mc/versions.json"); - updatesFuture = Async.asyncWorker.submit(() -> { - if (!updateCheckFuture.isCancelled()) { + updatesFuture = Async.asyncWorker.submit(new Callable>() { + @Override + public List call() { + //Deadlock avoidance + if (updateCheckFuture.isCancelled()) { + updatesFuture = null; + return null; + } + if (!updateCheckFuture.isDone()) { + updatesFuture = Async.asyncWorker.submit(this); + return null; + } try { var updates = updateCheckFuture.get(); if (updates != null && updates.size() > 0) { - for (val update:updates) { + for (val update : updates) { update.log(FalsePatternLib.getLog()); } } else if (updates == null) { @@ -54,8 +65,8 @@ public class CommonProxy { } catch (InterruptedException | ExecutionException ex) { FalsePatternLib.getLog().warn("Error while checking updates", ex); } + return null; } - return null; }); } }