From ea4f8b67f2f05cae446c40a30ca0138f9c964dff Mon Sep 17 00:00:00 2001 From: Agetian Date: Thu, 13 Jul 2017 20:08:47 +0000 Subject: [PATCH] - Unfortunately, have to revert r34731 - breaks mobile Forge (at least when running on desktop, e.g. for debugging purposes, but quite possibly on Android itself as well) and does not allow to cast anything from hand at all, making the single click on a card function as a selection (but not allowing to actually cast the spell). --- .../src/main/java/forge/util/ThreadUtil.java | 6 +-- .../src/main/java/forge/game/GameAction.java | 15 +------ .../match/input/InputSyncronizedBase.java | 45 +++---------------- 3 files changed, 11 insertions(+), 55 deletions(-) diff --git a/forge-core/src/main/java/forge/util/ThreadUtil.java b/forge-core/src/main/java/forge/util/ThreadUtil.java index 4ec6fb0f0a9..fd49e51506e 100644 --- a/forge-core/src/main/java/forge/util/ThreadUtil.java +++ b/forge-core/src/main/java/forge/util/ThreadUtil.java @@ -20,10 +20,8 @@ public class ThreadUtil { } } - // Use a single game thread, rather than a pool of them, because when something - // needs to execute on the game thread, it's because it's not thread safe. - private final static ExecutorService gameThread = Executors.newSingleThreadExecutor(new WorkerThreadFactory("Game")); - private static ExecutorService getGameThreadPool() { return gameThread; } + private final static ExecutorService gameThreadPool = Executors.newCachedThreadPool(new WorkerThreadFactory("Game")); + private static ExecutorService getGameThreadPool() { return gameThreadPool; } private final static ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2, new WorkerThreadFactory("Delayed")); private static ScheduledExecutorService getScheduledPool() { return scheduledPool; } diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 83bf3505205..b035731f1f2 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -17,7 +17,6 @@ */ package forge.game; -import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Iterables; @@ -77,7 +76,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.concurrent.Callable; /** * Methods for common actions performed during a game. @@ -1746,17 +1744,8 @@ public class GameAction { // state effects are checked only when someone gets priority } - private Function invokeFunction; - public synchronized void setInvokeFunction(Function invokeFunction) { - this.invokeFunction = invokeFunction; - } - - // Invokes given runnable on the Game thread - used to start game and perform actions from UI when waiting for input. - public synchronized void invoke(final Runnable proc) { - if (invokeFunction != null) { - invokeFunction.apply(proc); - return; - } + // Invokes given runnable in Game thread pool - used to start game and perform actions from UI (when game-0 waits for input) + public void invoke(final Runnable proc) { if (ThreadUtil.isGameThread()) { proc.run(); } diff --git a/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java b/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java index d916514c1b4..9ca2f6ce712 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java +++ b/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java @@ -1,34 +1,25 @@ package forge.match.input; -import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.CountDownLatch; -import com.google.common.base.Function; import forge.FThreads; import forge.error.BugReporter; import forge.player.PlayerControllerHuman; -import forge.util.ThreadUtil; public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized { private static final long serialVersionUID = 8756177361251703052L; - private static final Runnable terminationMarker = new Runnable() { public void run() { } }; - - // The gameTaskQueue indicates tasks to run while blocked on the game. To stop, add terminationMarker (as null is - // not allowed). - private LinkedBlockingDeque gameTaskQueue = new LinkedBlockingDeque(); + private final CountDownLatch cdlDone; public InputSyncronizedBase(final PlayerControllerHuman controller) { super(controller); + cdlDone = new CountDownLatch(1); } @Override public void awaitLatchRelease() { FThreads.assertExecutedByEdt(false); - try { - Runnable r = gameTaskQueue.take(); - while (r != terminationMarker) { - r.run(); - r = gameTaskQueue.take(); - } + try{ + cdlDone.await(); } catch (final InterruptedException e) { BugReporter.reportException(e); } @@ -36,34 +27,12 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn @Override public final void relaseLatchWhenGameIsOver() { - gameTaskQueue.add(terminationMarker); + cdlDone.countDown(); } public void showAndWait() { - final boolean isGameThread = ThreadUtil.isGameThread(); - - if (isGameThread) { - // If we're on the game thread, redirect the "run on game thread" function to instead go through us. - getController().getGame().getAction().setInvokeFunction(new Function() { - public Void apply(Runnable r) { - gameTaskQueue.add(r); - return null; - } - }); - } - getController().getInputQueue().setInput(this); awaitLatchRelease(); - - if (isGameThread) { - // Reset the invoke function to null. - getController().getGame().getAction().setInvokeFunction(null); - // There's a race that a new task may be queued up before we've reset the invoke function. - // To handle this, schedule any remaining tasks normally. - for (Runnable r : gameTaskQueue) { - getController().getGame().getAction().invoke(r); - } - } } protected final void stop() { @@ -81,7 +50,7 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn if (getController().getInputQueue().getInput() != null) { getController().getInputQueue().removeInput(InputSyncronizedBase.this); } - gameTaskQueue.add(terminationMarker); + cdlDone.countDown(); } protected void onStop() { }