mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +00:00
Thread-related routines moved from FControl to FThreads
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -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/CommandList.java svneol=native#text/plain
|
||||||
src/main/java/forge/Constant.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/CounterType.java svneol=native#text/plain
|
||||||
|
src/main/java/forge/FThreads.java -text
|
||||||
src/main/java/forge/GameEntity.java -text
|
src/main/java/forge/GameEntity.java -text
|
||||||
src/main/java/forge/GameLog.java -text
|
src/main/java/forge/GameLog.java -text
|
||||||
src/main/java/forge/ImageCache.java svneol=native#text/plain
|
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/InputBlock.java svneol=native#text/plain
|
||||||
src/main/java/forge/control/input/InputCleanup.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/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/InputMulligan.java svneol=native#text/plain
|
||||||
src/main/java/forge/control/input/InputPassPriority.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
|
src/main/java/forge/control/input/InputPayDiscardCost.java -text
|
||||||
|
|||||||
109
src/main/java/forge/FThreads.java
Normal file
109
src/main/java/forge/FThreads.java
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -39,9 +39,9 @@ import javax.swing.SwingUtilities;
|
|||||||
|
|
||||||
import org.apache.commons.lang.time.StopWatch;
|
import org.apache.commons.lang.time.StopWatch;
|
||||||
|
|
||||||
|
import forge.FThreads;
|
||||||
import forge.card.CardRules;
|
import forge.card.CardRules;
|
||||||
import forge.card.CardRulesReader;
|
import forge.card.CardRulesReader;
|
||||||
import forge.control.FControl;
|
|
||||||
import forge.error.BugReporter;
|
import forge.error.BugReporter;
|
||||||
import forge.gui.toolbox.FProgressBar;
|
import forge.gui.toolbox.FProgressBar;
|
||||||
import forge.util.FileUtil;
|
import forge.util.FileUtil;
|
||||||
@@ -62,7 +62,7 @@ public class CardStorageReader {
|
|||||||
/** Default charset when loading from files. */
|
/** Default charset when loading from files. */
|
||||||
public static final String DEFAULT_CHARSET_NAME = "US-ASCII";
|
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 int NUMBER_OF_PARTS = 25;
|
||||||
|
|
||||||
final private CountDownLatch cdl = new CountDownLatch(NUMBER_OF_PARTS);
|
final private CountDownLatch cdl = new CountDownLatch(NUMBER_OF_PARTS);
|
||||||
@@ -209,7 +209,7 @@ public class CardStorageReader {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if ( useThreadPool ) {
|
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);
|
final List<Future<List<CardRules>>> parts = executor.invokeAll(tasks);
|
||||||
executor.shutdown();
|
executor.shutdown();
|
||||||
cdl.await();
|
cdl.await();
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ import java.awt.event.WindowEvent;
|
|||||||
import java.awt.event.WindowListener;
|
import java.awt.event.WindowListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JLayeredPane;
|
import javax.swing.JLayeredPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -85,14 +82,8 @@ public enum FControl {
|
|||||||
DRAFTING_PROCESS
|
DRAFTING_PROCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ExecutorService threadPool = Executors.newCachedThreadPool();
|
|
||||||
|
|
||||||
private final SoundSystem soundSystem = new SoundSystem();
|
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>
|
* <p>
|
||||||
* FControl.
|
* FControl.
|
||||||
@@ -317,21 +308,4 @@ public enum FControl {
|
|||||||
public SoundSystem getSoundSystem() {
|
public SoundSystem getSoundSystem() {
|
||||||
return soundSystem;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/main/java/forge/control/input/InputLockUI.java
Normal file
18
src/main/java/forge/control/input/InputLockUI.java
Normal 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...");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -31,7 +31,6 @@ import java.util.List;
|
|||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.gui.match.VMatchUI;
|
import forge.gui.match.VMatchUI;
|
||||||
@@ -89,26 +88,6 @@ public final class GuiUtils {
|
|||||||
return ttf;
|
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   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) {
|
|
||||||
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.
|
* Clear all visually highlighted card panels on the battlefield.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import java.util.Date;
|
|||||||
import javax.swing.JProgressBar;
|
import javax.swing.JProgressBar;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
import forge.gui.GuiUtils;
|
import forge.FThreads;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple progress bar component using the Forge skin.
|
* A simple progress bar component using the Forge skin.
|
||||||
@@ -37,7 +37,7 @@ public class FProgressBar extends JProgressBar {
|
|||||||
* @param s0   A description to prepend before statistics.
|
* @param s0   A description to prepend before statistics.
|
||||||
*/
|
*/
|
||||||
public void setDescription(final String s0) {
|
public void setDescription(final String s0) {
|
||||||
GuiUtils.checkEDT("FProgressBar$setDescription", true);
|
FThreads.checkEDT("FProgressBar$setDescription", true);
|
||||||
this.desc = s0;
|
this.desc = s0;
|
||||||
this.setString(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. */
|
/** Resets the various values required for this class. Must be called from EDT. */
|
||||||
public void reset() {
|
public void reset() {
|
||||||
GuiUtils.checkEDT("FProgressBar$reset", true);
|
FThreads.checkEDT("FProgressBar$reset", true);
|
||||||
this.setIndeterminate(true);
|
this.setIndeterminate(true);
|
||||||
this.setValue(0);
|
this.setValue(0);
|
||||||
this.tempVal = 0;
|
this.tempVal = 0;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import javax.swing.SwingUtilities;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.border.LineBorder;
|
import javax.swing.border.LineBorder;
|
||||||
|
|
||||||
|
import forge.FThreads;
|
||||||
import forge.gui.GuiUtils;
|
import forge.gui.GuiUtils;
|
||||||
import forge.view.FView;
|
import forge.view.FView;
|
||||||
|
|
||||||
@@ -419,7 +420,7 @@ public enum FSkin {
|
|||||||
*/
|
*/
|
||||||
public static void loadLight(final String skinName) {
|
public static void loadLight(final String skinName) {
|
||||||
// No need for this method to be loaded while on the EDT.
|
// 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.
|
// Non-default (preferred) skin name and dir.
|
||||||
FSkin.preferredName = skinName.toLowerCase().replace(' ', '_');
|
FSkin.preferredName = skinName.toLowerCase().replace(' ', '_');
|
||||||
@@ -479,7 +480,7 @@ public enum FSkin {
|
|||||||
*/
|
*/
|
||||||
public static void loadFull() {
|
public static void loadFull() {
|
||||||
// No need for this method to be loaded while on the EDT.
|
// 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,
|
// Preferred skin name must be called via loadLight() method,
|
||||||
// which does some cleanup and init work.
|
// which does some cleanup and init work.
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import forge.Constant;
|
import forge.Constant;
|
||||||
import forge.Constant.Preferences;
|
import forge.Constant.Preferences;
|
||||||
|
import forge.FThreads;
|
||||||
import forge.card.BoosterData;
|
import forge.card.BoosterData;
|
||||||
import forge.card.CardBlock;
|
import forge.card.CardBlock;
|
||||||
import forge.card.CardRulesReader;
|
import forge.card.CardRulesReader;
|
||||||
@@ -43,7 +44,6 @@ import forge.game.MatchController;
|
|||||||
import forge.game.limited.GauntletMini;
|
import forge.game.limited.GauntletMini;
|
||||||
import forge.game.player.LobbyPlayer;
|
import forge.game.player.LobbyPlayer;
|
||||||
import forge.gauntlet.GauntletData;
|
import forge.gauntlet.GauntletData;
|
||||||
import forge.gui.GuiUtils;
|
|
||||||
import forge.item.CardDb;
|
import forge.item.CardDb;
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
@@ -161,7 +161,7 @@ public enum FModel {
|
|||||||
this.loadDynamicGamedata();
|
this.loadDynamicGamedata();
|
||||||
|
|
||||||
// Loads all cards (using progress bar).
|
// 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);
|
final CardStorageReader reader = new CardStorageReader(NewConstants.CARD_DATA_DIR, true);
|
||||||
try {
|
try {
|
||||||
// this fills in our map of card names to Card instances.
|
// this fills in our map of card names to Card instances.
|
||||||
|
|||||||
Reference in New Issue
Block a user