From 5fa426177eebc00ed12375732632d7263bef364b Mon Sep 17 00:00:00 2001
From: Philipp Spohr <spohr.philipp@web.de>
Date: Wed, 6 Sep 2017 11:33:43 +0200
Subject: [PATCH] Implemented Thread-Control / Limitation (prevents freezing
 keeps GUI usable)

---
 .../ba/yoshikoWrapper/core/AlgorithmTask.java    |  9 +++++++++
 .../hhu/ba/yoshikoWrapper/core/ParameterSet.java |  1 +
 .../de/hhu/ba/yoshikoWrapper/gui/MainPanel.java  |  1 +
 .../yoshikoWrapper/gui/OperationModePanel.java   | 16 +++++++++++++++-
 .../ba/yoshikoWrapper/swig/CplexInformer.java    |  4 ++--
 .../ba/yoshikoWrapper/swig/LibraryInterface.java |  4 ++++
 .../yoshikoWrapper/swig/LibraryInterfaceJNI.java |  9 +++++----
 src/main/resources/YoshikoStrings.properties     |  2 ++
 8 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/core/AlgorithmTask.java b/src/main/java/de/hhu/ba/yoshikoWrapper/core/AlgorithmTask.java
index 50887d9..7212b08 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/core/AlgorithmTask.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/core/AlgorithmTask.java
@@ -92,6 +92,9 @@ public class AlgorithmTask extends AbstractTask {
 		
 		//Set time limit
 		LibraryInterface.setTimeLimit(parameterSet.timeLimit);
+		if (parameterSet.disableMultiThreading) {
+			LibraryInterface.setThreadLimit(1);
+		}
 
 		//Create a node map to identify nodes and eges in the solution
 		NodeMap nodeMap  = new NodeMap(net);
@@ -122,6 +125,7 @@ public class AlgorithmTask extends AbstractTask {
 		);
 		class CallbackHandler extends CplexInformer{
 			
+			@Override
 			public boolean continueOnTimeout() {
 				try {
 					int result = JOptionPane.showConfirmDialog(
@@ -141,6 +145,11 @@ public class AlgorithmTask extends AbstractTask {
 					return false;
 				}
 			}
+			
+			@Override
+			public void updateGap(double gap) {
+				taskMonitor.setStatusMessage(LocalizationManager.get("currentGap")+": "+gap);
+			}
 		}
 		
 		ca.registerCplexInformer(new CallbackHandler());
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/core/ParameterSet.java b/src/main/java/de/hhu/ba/yoshikoWrapper/core/ParameterSet.java
index 863c869..f74c050 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/core/ParameterSet.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/core/ParameterSet.java
@@ -16,5 +16,6 @@ public class ParameterSet {
 	public boolean usePartitionCuts;
 	public boolean useHeuristic;
 	public int solCount;
+	public boolean disableMultiThreading;
 	
 }
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/gui/MainPanel.java b/src/main/java/de/hhu/ba/yoshikoWrapper/gui/MainPanel.java
index 0ce16d3..35e6c6f 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/gui/MainPanel.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/gui/MainPanel.java
@@ -255,6 +255,7 @@ public class MainPanel extends JPanel implements CytoPanelComponent {
 		ret.usePartitionCuts = opModePanel.usePartitionCuts(); 
 		ret.useHeuristic = opModePanel.useHeuristic();
 		ret.solCount = opModePanel.getSolCount();
+		ret.disableMultiThreading = opModePanel.isMultiThreadingDisabled();
 		return ret;
 	}
 
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/gui/OperationModePanel.java b/src/main/java/de/hhu/ba/yoshikoWrapper/gui/OperationModePanel.java
index a761e96..a92ee23 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/gui/OperationModePanel.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/gui/OperationModePanel.java
@@ -32,6 +32,7 @@ import javax.swing.JCheckBox;
 import javax.swing.JPanel;
 import javax.swing.JRadioButton;
 
+import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;
 
 import javax.swing.GroupLayout.Alignment;
 
@@ -45,6 +46,7 @@ public class OperationModePanel extends JPanel{
 	private final SolutionNumberChooser solutionNumberChooser;
 	private final JCheckBox useTriangleCutsBox;
 	private final JCheckBox usePartitionCutsBox;
+	private final JCheckBox disableMultiThreading;
 	
 	private final ButtonGroup heuristicGroup;
 
@@ -65,6 +67,9 @@ public class OperationModePanel extends JPanel{
 		useTriangleCutsBox = new JCheckBox("Use Triangle Cuts");
 		usePartitionCutsBox = new JCheckBox("Use Partition Cuts");
 		
+		disableMultiThreading = new JCheckBox(LocalizationManager.get("disableMultiThreading"));
+		disableMultiThreading.setSelected(true);
+		
 		//Link time limit option to ILP
 		useILP.addActionListener(ilpHeuristicSwitch);
 		useHeuristic.addActionListener(ilpHeuristicSwitch);
@@ -75,7 +80,8 @@ public class OperationModePanel extends JPanel{
 				solutionNumberChooser,
 				timeLimitSetter,
 				useTriangleCutsBox,
-				usePartitionCutsBox
+				usePartitionCutsBox,
+				disableMultiThreading
 		);
 
 		//Layout
@@ -90,6 +96,7 @@ public class OperationModePanel extends JPanel{
 				.addComponent(timeLimitSetter, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
 				.addComponent(useTriangleCutsBox, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
 				.addComponent(usePartitionCutsBox, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
+				.addComponent(disableMultiThreading, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
 		);
 		
 		layout.setVerticalGroup(layout.createSequentialGroup()
@@ -99,6 +106,7 @@ public class OperationModePanel extends JPanel{
 				.addComponent(timeLimitSetter)
 				.addComponent(useTriangleCutsBox)
 				.addComponent(usePartitionCutsBox)
+				.addComponent(disableMultiThreading)
 		);
 		
 		this.setLayout(layout);
@@ -113,12 +121,14 @@ public class OperationModePanel extends JPanel{
 				useTriangleCutsBox.setEnabled(true);
 				usePartitionCutsBox.setEnabled(true);
 				solutionNumberChooser.setEnabled(true);
+				disableMultiThreading.setEnabled(true);
 			}
 			else {
 				timeLimitSetter.setEnabled(false);
 				useTriangleCutsBox.setEnabled(false);
 				usePartitionCutsBox.setEnabled(false);
 				solutionNumberChooser.setEnabled(false);
+				disableMultiThreading.setEnabled(false);
 			}
 		}	
 	};
@@ -140,6 +150,10 @@ public class OperationModePanel extends JPanel{
 	public boolean useHeuristic() {
 		return useHeuristic.isSelected();
 	}
+	
+	public boolean isMultiThreadingDisabled() {
+		return disableMultiThreading.isSelected();
+	}
 
 	public int getSolCount() {
 		return solutionNumberChooser.getSolCount();
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/swig/CplexInformer.java b/src/main/java/de/hhu/ba/yoshikoWrapper/swig/CplexInformer.java
index 7ea4abb..818781d 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/swig/CplexInformer.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/swig/CplexInformer.java
@@ -50,8 +50,8 @@ public class CplexInformer {
     LibraryInterfaceJNI.CplexInformer_change_ownership(this, swigCPtr, true);
   }
 
-  public void callback(double gap) {
-    if (getClass() == CplexInformer.class) LibraryInterfaceJNI.CplexInformer_callback(swigCPtr, this, gap); else LibraryInterfaceJNI.CplexInformer_callbackSwigExplicitCplexInformer(swigCPtr, this, gap);
+  public void updateGap(double gap) {
+    if (getClass() == CplexInformer.class) LibraryInterfaceJNI.CplexInformer_updateGap(swigCPtr, this, gap); else LibraryInterfaceJNI.CplexInformer_updateGapSwigExplicitCplexInformer(swigCPtr, this, gap);
   }
 
   public boolean continueOnTimeout() {
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/swig/LibraryInterface.java b/src/main/java/de/hhu/ba/yoshikoWrapper/swig/LibraryInterface.java
index df59eeb..82e0dee 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/swig/LibraryInterface.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/swig/LibraryInterface.java
@@ -17,6 +17,10 @@ public class LibraryInterface {
     LibraryInterfaceJNI.setTimeLimit(limit);
   }
 
+  public static void setThreadLimit(int limit) {
+    LibraryInterfaceJNI.setThreadLimit(limit);
+  }
+
   public static void setVerbosity(int level) {
     LibraryInterfaceJNI.setVerbosity(level);
   }
diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/swig/LibraryInterfaceJNI.java b/src/main/java/de/hhu/ba/yoshikoWrapper/swig/LibraryInterfaceJNI.java
index ebcafd9..dcaa7e5 100644
--- a/src/main/java/de/hhu/ba/yoshikoWrapper/swig/LibraryInterfaceJNI.java
+++ b/src/main/java/de/hhu/ba/yoshikoWrapper/swig/LibraryInterfaceJNI.java
@@ -46,8 +46,8 @@ public class LibraryInterfaceJNI {
   public final static native void LibraryInput_addEdge__SWIG_1(long jarg1, LibraryInput jarg1_, long jarg2, long jarg3, double jarg4, boolean jarg5, boolean jarg6);
   public final static native void LibraryInput_setSize(long jarg1, LibraryInput jarg1_, long jarg2);
   public final static native void LibraryInput_setDefaultInsertionCost(long jarg1, LibraryInput jarg1_, double jarg2);
-  public final static native void CplexInformer_callback(long jarg1, CplexInformer jarg1_, double jarg2);
-  public final static native void CplexInformer_callbackSwigExplicitCplexInformer(long jarg1, CplexInformer jarg1_, double jarg2);
+  public final static native void CplexInformer_updateGap(long jarg1, CplexInformer jarg1_, double jarg2);
+  public final static native void CplexInformer_updateGapSwigExplicitCplexInformer(long jarg1, CplexInformer jarg1_, double jarg2);
   public final static native boolean CplexInformer_continueOnTimeout(long jarg1, CplexInformer jarg1_);
   public final static native boolean CplexInformer_continueOnTimeoutSwigExplicitCplexInformer(long jarg1, CplexInformer jarg1_);
   public final static native void delete_CplexInformer(long jarg1);
@@ -60,11 +60,12 @@ public class LibraryInterfaceJNI {
   public final static native void delete_CoreAlgorithm(long jarg1);
   public final static native String getVersionString();
   public final static native void setTimeLimit(int jarg1);
+  public final static native void setThreadLimit(int jarg1);
   public final static native void setVerbosity(int jarg1);
   public final static native long getRun(long jarg1, LibraryInput jarg1_, int jarg2, String jarg3, double jarg4, boolean jarg5, boolean jarg6, boolean jarg7);
 
-  public static void SwigDirector_CplexInformer_callback(CplexInformer jself, double gap) {
-    jself.callback(gap);
+  public static void SwigDirector_CplexInformer_updateGap(CplexInformer jself, double gap) {
+    jself.updateGap(gap);
   }
   public static boolean SwigDirector_CplexInformer_continueOnTimeout(CplexInformer jself) {
     return jself.continueOnTimeout();
diff --git a/src/main/resources/YoshikoStrings.properties b/src/main/resources/YoshikoStrings.properties
index 124cb05..372a54b 100644
--- a/src/main/resources/YoshikoStrings.properties
+++ b/src/main/resources/YoshikoStrings.properties
@@ -61,3 +61,5 @@ notOptimal = Not Optimal Solution
 ilpMarker = ILP Properties
 timeoutMarker = Timed Out
 gap = Gap
+currentGap = [ILP] Current Gap: 
+disableMultiThreading = Disable Multithreading
-- 
GitLab