Fix so Auto payment occurs in Game thread

This commit is contained in:
drdev
2013-12-12 11:49:50 +00:00
parent 1c391a7c7e
commit 849655cb2f
2 changed files with 38 additions and 11 deletions

View File

@@ -1,5 +1,6 @@
package forge.util; package forge.util;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
@@ -7,11 +8,10 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class ThreadUtil { public class ThreadUtil {
static {
static {
System.out.printf("(ThreadUtil first call): Running on a machine with %d cpu core(s)%n", Runtime.getRuntime().availableProcessors() ); System.out.printf("(ThreadUtil first call): Running on a machine with %d cpu core(s)%n", Runtime.getRuntime().availableProcessors() );
} }
private static class WorkerThreadFactory implements ThreadFactory { private static class WorkerThreadFactory implements ThreadFactory {
private int countr = 0; private int countr = 0;
private String prefix = ""; private String prefix = "";
@@ -24,9 +24,7 @@ public class ThreadUtil {
return new Thread(r, prefix + "-" + countr++); return new Thread(r, prefix + "-" + countr++);
} }
} }
private final static ExecutorService gameThreadPool = Executors.newCachedThreadPool(new WorkerThreadFactory("Game")); private final static ExecutorService gameThreadPool = Executors.newCachedThreadPool(new WorkerThreadFactory("Game"));
private static ExecutorService getGameThreadPool() { return gameThreadPool; } private static ExecutorService getGameThreadPool() { return gameThreadPool; }
private final static ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2, new WorkerThreadFactory("Delayed")); private final static ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2, new WorkerThreadFactory("Delayed"));
@@ -36,18 +34,40 @@ public class ThreadUtil {
public final static ExecutorService getComputingPool(float loadFactor) { public final static ExecutorService getComputingPool(float loadFactor) {
return Executors.newFixedThreadPool((int)(Runtime.getRuntime().availableProcessors() / (1-loadFactor))); return Executors.newFixedThreadPool((int)(Runtime.getRuntime().availableProcessors() / (1-loadFactor)));
} }
public static boolean isMultiCoreSystem() { public static boolean isMultiCoreSystem() {
return Runtime.getRuntime().availableProcessors() > 1; return Runtime.getRuntime().availableProcessors() > 1;
} }
public static void invokeInGameThread(Runnable toRun) { public static void invokeInGameThread(Runnable toRun) {
getGameThreadPool().execute(toRun); getGameThreadPool().execute(toRun);
} }
public static void invokeInGameThreadAndWait(final Runnable toRun) {
if (isGameThread()) {
toRun.run(); //just run in the current thread
return;
}
final CountDownLatch latch = new CountDownLatch(1);
getGameThreadPool().execute(new Runnable() {
@Override
public void run() {
toRun.run();
latch.countDown();
}
});
try {
latch.await();
}
catch (final InterruptedException ex) {
throw new RuntimeException(ex);
}
}
public static void delay(int milliseconds, Runnable inputUpdater) { public static void delay(int milliseconds, Runnable inputUpdater) {
getScheduledPool().schedule(inputUpdater, milliseconds, TimeUnit.MILLISECONDS); getScheduledPool().schedule(inputUpdater, milliseconds, TimeUnit.MILLISECONDS);
} }
public static boolean isGameThread() { public static boolean isGameThread() {
return Thread.currentThread().getName().startsWith("Game"); return Thread.currentThread().getName().startsWith("Game");
} }

View File

@@ -25,6 +25,7 @@ import forge.game.spellability.AbilityManaPart;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
import forge.util.Evaluator; import forge.util.Evaluator;
import forge.util.ThreadUtil;
import forge.view.ButtonUtil; import forge.view.ButtonUtil;
/** /**
@@ -288,13 +289,19 @@ public abstract class InputPayMana extends InputSyncronizedBase {
protected void onOk() { protected void onOk() {
if (supportAutoPay()) { if (supportAutoPay()) {
//use AI utility to automatically pay mana cost if possible //use AI utility to automatically pay mana cost if possible
Runnable proc = new Runnable() { final Runnable proc = new Runnable() {
@Override @Override
public void run() { public void run() {
ComputerUtilMana.payManaCost(manaCost, saPaidFor, player); ComputerUtilMana.payManaCost(manaCost, saPaidFor, player);
} }
}; };
runAsAi(proc); //must run in game thread as certain payment actions can only be automated there
ThreadUtil.invokeInGameThreadAndWait(new Runnable() {
@Override
public void run() {
runAsAi(proc);
}
});
this.showMessage(); this.showMessage();
} }
} }