Thread-related routines moved from FControl to FThreads

This commit is contained in:
Maxmtg
2013-03-22 18:16:38 +00:00
parent 13cc4555e2
commit 72d38b34a3
9 changed files with 140 additions and 57 deletions

2
.gitattributes vendored
View File

@@ -13699,6 +13699,7 @@ src/main/java/forge/Command.java svneol=native#text/plain
src/main/java/forge/CommandList.java svneol=native#text/plain
src/main/java/forge/Constant.java svneol=native#text/plain
src/main/java/forge/CounterType.java svneol=native#text/plain
src/main/java/forge/FThreads.java -text
src/main/java/forge/GameEntity.java -text
src/main/java/forge/GameLog.java -text
src/main/java/forge/ImageCache.java svneol=native#text/plain
@@ -14083,6 +14084,7 @@ src/main/java/forge/control/input/InputAttack.java svneol=native#text/plain
src/main/java/forge/control/input/InputBlock.java svneol=native#text/plain
src/main/java/forge/control/input/InputCleanup.java svneol=native#text/plain
src/main/java/forge/control/input/InputControl.java svneol=native#text/plain
src/main/java/forge/control/input/InputLockUI.java -text
src/main/java/forge/control/input/InputMulligan.java svneol=native#text/plain
src/main/java/forge/control/input/InputPassPriority.java svneol=native#text/plain
src/main/java/forge/control/input/InputPayDiscardCost.java -text

View File

@@ -0,0 +1,109 @@
package forge;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.SwingUtilities;
import forge.control.input.InputLockUI;
/**
* TODO: Write javadoc for this type.
*
*/
public class FThreads {
static {
System.out.printf("(FThreads static ctor): Running on a machine with %d cpu core(s)%n", Runtime.getRuntime().availableProcessors() );
}
private final static ExecutorService threadPool = Executors.newCachedThreadPool();
public static ExecutorService getCachedPool() {
return threadPool;
}
// This pool is designed to parallel CPU or IO intensive tasks like parse cards or download images, assuming a load factor of 0.5
public final static ExecutorService getComputingPool(float loadFactor) {
return Executors.newFixedThreadPool((int)(Runtime.getRuntime().availableProcessors() / (1-loadFactor)));
}
public static boolean isMultiCoreSystem() {
return Runtime.getRuntime().availableProcessors() > 1;
}
/** Checks if calling method uses event dispatch thread.
* Exception thrown if method is on "wrong" thread.
* A boolean is passed to indicate if the method must be EDT or not.
*
* @param methodName   String, part of the custom exception message.
* @param mustBeEDT   boolean: true = exception if not EDT, false = exception if EDT
*/
public static void checkEDT(final String methodName, final boolean mustBeEDT) {
boolean isEDT = SwingUtilities.isEventDispatchThread();
if ( isEDT != mustBeEDT ) {
String modalOperator = mustBeEDT ? " must be" : " may not be";
throw new IllegalStateException( methodName + modalOperator + " accessed from the event dispatch thread.");
}
}
/**
* TODO: Write javadoc for this method.
* @param runnable
*/
public static void invokeInEDT(Runnable runnable) {
SwingUtilities.invokeLater(runnable);
}
/**
* Invoke the given Runnable in an Event Dispatch Thread and wait for it to
* finish; but <B>try to use SwingUtilities.invokeLater instead whenever
* feasible.</B>
*
* Exceptions generated by SwingUtilities.invokeAndWait (if used), are
* rethrown as RuntimeExceptions.
*
* @param proc
* the Runnable to run
* @see javax.swing.SwingUtilities#invokeLater(Runnable)
*/
public static void invokeInEDTAndWait(final Runnable proc) {
if (SwingUtilities.isEventDispatchThread()) {
// Just run in the current thread.
proc.run();
} else {
try {
SwingUtilities.invokeAndWait(proc);
} catch (final InterruptedException exn) {
throw new RuntimeException(exn);
} catch (final InvocationTargetException exn) {
throw new RuntimeException(exn);
}
}
}
public static void invokeInNewThread(Runnable proc) {
invokeInNewThread(proc, false);
}
private final static InputLockUI inpuptLock = new InputLockUI();
public static void invokeInNewThread(final Runnable proc, boolean lockUI) {
Runnable toRun = proc;
if( lockUI ) {
// checkEDT("FThreads.invokeInNewthread", true)
Singletons.getModel().getMatch().getInput().setInput(inpuptLock);
toRun = new Runnable() {
@Override
public void run() {
proc.run();
// may try special unlock method here
Singletons.getModel().getMatch().getInput().resetInput();
}
};
}
getCachedPool().execute(toRun);
}
}

View File

@@ -39,9 +39,9 @@ import javax.swing.SwingUtilities;
import org.apache.commons.lang.time.StopWatch;
import forge.FThreads;
import forge.card.CardRules;
import forge.card.CardRulesReader;
import forge.control.FControl;
import forge.error.BugReporter;
import forge.gui.toolbox.FProgressBar;
import forge.util.FileUtil;
@@ -62,7 +62,7 @@ public class CardStorageReader {
/** Default charset when loading from files. */
public static final String DEFAULT_CHARSET_NAME = "US-ASCII";
final private boolean useThreadPool = FControl.isMultiCoreSystem();
final private boolean useThreadPool = FThreads.isMultiCoreSystem();
final private int NUMBER_OF_PARTS = 25;
final private CountDownLatch cdl = new CountDownLatch(NUMBER_OF_PARTS);
@@ -209,7 +209,7 @@ public class CardStorageReader {
try {
if ( useThreadPool ) {
final ExecutorService executor = FControl.getComputingPool(0.5f);
final ExecutorService executor = FThreads.getComputingPool(0.5f);
final List<Future<List<CardRules>>> parts = executor.invokeAll(tasks);
executor.shutdown();
cdl.await();

View File

@@ -25,9 +25,6 @@ import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.ImageIcon;
import javax.swing.JLayeredPane;
import javax.swing.SwingUtilities;
@@ -85,14 +82,8 @@ public enum FControl {
DRAFTING_PROCESS
}
private final ExecutorService threadPool = Executors.newCachedThreadPool();
private final SoundSystem soundSystem = new SoundSystem();
static {
System.out.printf("(FControl static ctor): Running on a machine with %d cpu core(s)%n", Runtime.getRuntime().availableProcessors() );
}
/**
* <p>
* FControl.
@@ -317,21 +308,4 @@ public enum FControl {
public SoundSystem getSoundSystem() {
return soundSystem;
}
public ExecutorService getThreadPool() {
return threadPool;
}
// This pool is designed to parallel CPU or IO intensive tasks like parse cards or download images, assuming a load factor of 0.5
public final static ExecutorService getComputingPool(float loadFactor) {
return Executors.newFixedThreadPool((int)(Runtime.getRuntime().availableProcessors() / (1-loadFactor)));
}
/**
* TODO: Write javadoc for this method.
* @return
*/
public static boolean isMultiCoreSystem() {
return Runtime.getRuntime().availableProcessors() > 1;
}
}

View File

@@ -0,0 +1,18 @@
package forge.control.input;
import forge.gui.match.CMatchUI;
import forge.view.ButtonUtil;
/**
* TODO: Write javadoc for this type.
*
*/
public class InputLockUI extends Input {
private static final long serialVersionUID = 5777143577098597374L;
public void showMessage() {
ButtonUtil.disableAll();
CMatchUI.SINGLETON_INSTANCE.showMessage("Waiting for actions...");
}
}

View File

@@ -31,7 +31,6 @@ import java.util.List;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import forge.Card;
import forge.gui.match.VMatchUI;
@@ -89,26 +88,6 @@ public final class GuiUtils {
return ttf;
}
/** Checks if calling method uses event dispatch thread.
* Exception thrown if method is on "wrong" thread.
* A boolean is passed to indicate if the method must be EDT or not.
*
* @param methodName &emsp; String, part of the custom exception message.
* @param mustBeEDT &emsp; boolean: true = exception if not EDT, false = exception if EDT
*/
public static void checkEDT(final String methodName, final boolean mustBeEDT) {
boolean isEDT = SwingUtilities.isEventDispatchThread();
if (!isEDT && mustBeEDT) {
throw new IllegalStateException(
methodName + " must be accessed from the event dispatch thread.");
}
else if (isEDT && !mustBeEDT) {
throw new IllegalStateException(
methodName + " may not be accessed from the event dispatch thread.");
}
}
/**
* Clear all visually highlighted card panels on the battlefield.
*/

View File

@@ -5,7 +5,7 @@ import java.util.Date;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import forge.gui.GuiUtils;
import forge.FThreads;
/**
* A simple progress bar component using the Forge skin.
@@ -37,7 +37,7 @@ public class FProgressBar extends JProgressBar {
* @param s0 &emsp; A description to prepend before statistics.
*/
public void setDescription(final String s0) {
GuiUtils.checkEDT("FProgressBar$setDescription", true);
FThreads.checkEDT("FProgressBar$setDescription", true);
this.desc = s0;
this.setString(s0);
}
@@ -77,7 +77,7 @@ public class FProgressBar extends JProgressBar {
/** Resets the various values required for this class. Must be called from EDT. */
public void reset() {
GuiUtils.checkEDT("FProgressBar$reset", true);
FThreads.checkEDT("FProgressBar$reset", true);
this.setIndeterminate(true);
this.setValue(0);
this.tempVal = 0;

View File

@@ -37,6 +37,7 @@ import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
import forge.FThreads;
import forge.gui.GuiUtils;
import forge.view.FView;
@@ -419,7 +420,7 @@ public enum FSkin {
*/
public static void loadLight(final String skinName) {
// No need for this method to be loaded while on the EDT.
GuiUtils.checkEDT("FSkin$constructor", false);
FThreads.checkEDT("FSkin$constructor", false);
// Non-default (preferred) skin name and dir.
FSkin.preferredName = skinName.toLowerCase().replace(' ', '_');
@@ -479,7 +480,7 @@ public enum FSkin {
*/
public static void loadFull() {
// No need for this method to be loaded while on the EDT.
GuiUtils.checkEDT("FSkin$load", false);
FThreads.checkEDT("FSkin$load", false);
// Preferred skin name must be called via loadLight() method,
// which does some cleanup and init work.

View File

@@ -27,6 +27,7 @@ import java.util.List;
import forge.Constant;
import forge.Constant.Preferences;
import forge.FThreads;
import forge.card.BoosterData;
import forge.card.CardBlock;
import forge.card.CardRulesReader;
@@ -43,7 +44,6 @@ import forge.game.MatchController;
import forge.game.limited.GauntletMini;
import forge.game.player.LobbyPlayer;
import forge.gauntlet.GauntletData;
import forge.gui.GuiUtils;
import forge.item.CardDb;
import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref;
@@ -161,7 +161,7 @@ public enum FModel {
this.loadDynamicGamedata();
// Loads all cards (using progress bar).
GuiUtils.checkEDT("CardFactory$constructor", false);
FThreads.checkEDT("CardFactory$constructor", false);
final CardStorageReader reader = new CardStorageReader(NewConstants.CARD_DATA_DIR, true);
try {
// this fills in our map of card names to Card instances.