[gnumeric] solver: isolate OS differences in gnm-solver.c



commit 379ca2bc31856e68bd5a729c0e0d4856d9cc639d
Author: Morten Welinder <terra gnome org>
Date:   Tue Nov 17 13:29:25 2009 -0500

    solver: isolate OS differences in gnm-solver.c

 plugins/glpk/gnm-glpk.c       |   20 ++++++------
 plugins/lpsolve/gnm-lpsolve.c |   13 +++-----
 src/gnm-marshalers.list       |    1 +
 src/tools/gnm-solver.c        |   62 ++++++++++++++++++++++++++++++----------
 src/tools/gnm-solver.h        |    5 +--
 5 files changed, 63 insertions(+), 38 deletions(-)
---
diff --git a/plugins/glpk/gnm-glpk.c b/plugins/glpk/gnm-glpk.c
index 64d9b97..ed6528b 100644
--- a/plugins/glpk/gnm-glpk.c
+++ b/plugins/glpk/gnm-glpk.c
@@ -13,9 +13,6 @@
 #include <glib/gstdio.h>
 #include <string.h>
 #include <unistd.h>
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
 
 #define PRIVATE_KEY "::glpk::"
 
@@ -173,16 +170,16 @@ fail:
 
 
 static void
-cb_child_exit (GPid pid, gint status, GnmGlpk *lp)
+gnm_glpk_child_exit (GnmSubSolver *subsol, gboolean normal, int code,
+		     GnmGlpk *lp)
 {
-	GnmSubSolver *subsol = lp->parent;
 	GnmSolver *sol = GNM_SOLVER (subsol);
 
 	if (sol->status != GNM_SOLVER_STATUS_RUNNING)
 		return;
 
-	if (WIFEXITED (status)) {
-		switch (WEXITSTATUS (status)) {
+	if (normal) {
+		switch (code) {
 		case 0: {
 			GnmLocale *locale = gnm_push_C_locale ();
 			gnm_glpk_read_solution (lp);
@@ -256,13 +253,16 @@ gnm_glpk_start (GnmSolver *sol, WorkbookControl *wbc, GError **err,
 {
 	GnmSubSolver *subsol = GNM_SUB_SOLVER (sol);
 	gboolean ok;
-	gchar *argv[6];
+	gchar *argv[7];
 	int argc = 0;
+	GnmSolverParameters *param = sol->params;
 
 	g_return_val_if_fail (sol->status == GNM_SOLVER_STATUS_PREPARED, FALSE);
 
 	argv[argc++] = (gchar *)"glpsol";
-	// FIXME: Handle automatic scaling.
+	argv[argc++] = (gchar *)(param->options.automatic_scaling
+				 ? "--scale"
+				 : "--noscale");
 	argv[argc++] = (gchar *)"--write";
 	argv[argc++] = lp->result_filename;
 	argv[argc++] = (gchar *)"--cpxlp";
@@ -272,7 +272,6 @@ gnm_glpk_start (GnmSolver *sol, WorkbookControl *wbc, GError **err,
 
 	ok = gnm_sub_solver_spawn (subsol, argv,
 				   cb_child_setup, NULL,
-				   (GChildWatchFunc)cb_child_exit, lp,
 				   NULL, NULL,
 				   NULL, NULL,
 				   err);
@@ -311,6 +310,7 @@ glpk_solver_factory (GnmSolverFactory *factory, GnmSolverParameters *params)
 	g_signal_connect (res, "prepare", G_CALLBACK (gnm_glpk_prepare), lp);
 	g_signal_connect (res, "start", G_CALLBACK (gnm_glpk_start), lp);
 	g_signal_connect (res, "stop", G_CALLBACK (gnm_glpk_stop), lp);
+	g_signal_connect (res, "child-exit", G_CALLBACK (gnm_glpk_child_exit), lp);
 
 	g_object_set_data_full (G_OBJECT (res), PRIVATE_KEY, lp,
 				(GDestroyNotify)gnm_glpk_final);
diff --git a/plugins/lpsolve/gnm-lpsolve.c b/plugins/lpsolve/gnm-lpsolve.c
index 968974b..f41e5d4 100644
--- a/plugins/lpsolve/gnm-lpsolve.c
+++ b/plugins/lpsolve/gnm-lpsolve.c
@@ -8,9 +8,6 @@
 #include <gsf/gsf-impl-utils.h>
 #include <glib/gi18n-lib.h>
 #include <string.h>
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
 
 #define PRIVATE_KEY "::lpsolve::"
 
@@ -153,19 +150,19 @@ cb_read_stdout (GIOChannel *channel, GIOCondition cond, GnmLPSolve *lp)
 
 
 static void
-cb_child_exit (GPid pid, gint status, GnmLPSolve *lp)
+gnm_lpsolve_child_exit (GnmSubSolver *subsol, gboolean normal, int code,
+			GnmLPSolve *lp)
 {
-	GnmSubSolver *subsol = lp->parent;
 	GnmSolver *sol = GNM_SOLVER (subsol);
 	GnmSolverStatus new_status = GNM_SOLVER_STATUS_DONE;
 
 	if (sol->status != GNM_SOLVER_STATUS_RUNNING)
 		return;
 
-	if (WIFEXITED (status)) {
+	if (normal) {
 		GnmSolverResult *r;
 
-		switch (WEXITSTATUS (status)) {
+		switch (code) {
 		case 0: /* Optimal */
 			gnm_sub_solver_flush (subsol);
 			if (lp->result)
@@ -270,7 +267,6 @@ gnm_lpsolve_start (GnmSolver *sol, WorkbookControl *wbc, GError **err,
 
 	ok = gnm_sub_solver_spawn (subsol, argv,
 				   cb_child_setup, NULL,
-				   (GChildWatchFunc)cb_child_exit, lp,
 				   (GIOFunc)cb_read_stdout, lp,
 				   NULL, NULL,
 				   err);
@@ -309,6 +305,7 @@ lpsolve_solver_factory (GnmSolverFactory *factory, GnmSolverParameters *params)
 	g_signal_connect (res, "prepare", G_CALLBACK (gnm_lpsolve_prepare), lp);
 	g_signal_connect (res, "start", G_CALLBACK (gnm_lpsolve_start), lp);
 	g_signal_connect (res, "stop", G_CALLBACK (gnm_lpsolve_stop), lp);
+	g_signal_connect (res, "child-exit", G_CALLBACK (gnm_lpsolve_child_exit), lp);
 
 	g_object_set_data_full (G_OBJECT (res), PRIVATE_KEY, lp,
 				(GDestroyNotify)gnm_lpsolve_final);
diff --git a/src/gnm-marshalers.list b/src/gnm-marshalers.list
index 2fff383..bbe5bbd 100644
--- a/src/gnm-marshalers.list
+++ b/src/gnm-marshalers.list
@@ -27,3 +27,4 @@ INT:INT
 POINTER:INT,INT
 POINTER:VOID
 VOID:INT,INT
+VOID:BOOLEAN,INT
diff --git a/src/tools/gnm-solver.c b/src/tools/gnm-solver.c
index 51a7f82..44ddd8c 100644
--- a/src/tools/gnm-solver.c
+++ b/src/tools/gnm-solver.c
@@ -22,6 +22,16 @@
 #include <sys/wait.h>
 #endif
 
+#ifdef G_OS_WIN32
+#include <windows.h>
+#ifndef WIFEXITED
+#define WIFEXITED(x) ((x) != STILL_ACTIVE)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(x) (x)
+#endif
+#endif
+
 /* ------------------------------------------------------------------------- */
 
 gboolean
@@ -727,6 +737,7 @@ enum {
 	SOL_SIG_PREPARE,
 	SOL_SIG_START,
 	SOL_SIG_STOP,
+	SOL_SIG_CHILD_EXIT,
 	SOL_SIG_LAST
 };
 
@@ -1055,6 +1066,16 @@ gnm_solver_class_init (GObjectClass *object_class)
 			      gnm__BOOLEAN__POINTER,
 			      G_TYPE_BOOLEAN, 1,
 			      G_TYPE_POINTER);
+
+	solver_signals[SOL_SIG_CHILD_EXIT] =
+		g_signal_new ("child-exit",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GnmSolverClass, child_exit),
+			      NULL, NULL,
+			      gnm__VOID__BOOLEAN_INT,
+			      G_TYPE_NONE, 2,
+			      G_TYPE_BOOLEAN, G_TYPE_INT);
 }
 
 GSF_CLASS (GnmSolver, gnm_solver,
@@ -1096,12 +1117,14 @@ gnm_sub_solver_clear (GnmSubSolver *subsol)
 	if (subsol->child_watch) {
 		g_source_remove (subsol->child_watch);
 		subsol->child_watch = 0;
-		subsol->child_exit = NULL;
-		subsol->exit_data = NULL;
 	}
 
 	if (subsol->child_pid) {
+#ifdef G_OS_WIN32
+		TerminateProcess (subsol->child_pid, 127);
+#else
 		kill (subsol->child_pid, SIGKILL);
+#endif
 		g_spawn_close_pid (subsol->child_pid);
 		subsol->child_pid = (GPid)0;
 	}
@@ -1159,28 +1182,37 @@ gnm_sub_solver_init (GnmSubSolver *subsol)
 static void
 cb_child_exit (GPid pid, gint status, GnmSubSolver *subsol)
 {
-	if (gnm_solver_debug ()) {
-		if (WIFEXITED (status))
+	gboolean normal = WIFEXITED (status);
+	int code;
+
+	subsol->child_watch = 0;
+
+	if (normal) {
+		code = WEXITSTATUS (status);
+		if (gnm_solver_debug ())
 			g_printerr ("Solver process exited with code %d\n",
-				    WEXITSTATUS (status));
-		else if (WIFSIGNALED (status)) 
+				    code);
+#ifndef G_OS_WIN32
+	} else if (WIFSIGNALED (status)) {
+		code = WTERMSIG (status);
+		if (gnm_solver_debug ())
 			g_printerr ("Solver process received signal %d\n",
-				    WTERMSIG (status));
-		else
-			g_printerr ("Solver process exited with status 0x%x\n",
-				    status);
+				    code);
+#endif
+	} else {
+		code = -1;
+		g_printerr ("Solver process exited with status 0x%x\n",
+			    status);
 	}
 
-	subsol->child_watch = 0;
-	if (subsol->child_exit)
-		subsol->child_exit (pid, status, subsol->exit_data);
+	g_signal_emit (subsol, solver_signals[SOL_SIG_CHILD_EXIT], 0,
+		       normal, code);
 }
 
 gboolean
 gnm_sub_solver_spawn (GnmSubSolver *subsol,
 		      char **argv,
 		      GSpawnChildSetupFunc child_setup, gpointer setup_data,
-		      GChildWatchFunc child_exit, gpointer exit_data,
 		      GIOFunc io_stdout, gpointer stdout_data,
 		      GIOFunc io_stderr, gpointer stderr_data,
 		      GError **err)
@@ -1224,8 +1256,6 @@ gnm_sub_solver_spawn (GnmSubSolver *subsol,
 	if (!ok)
 		goto fail;
 
-	subsol->child_exit = child_exit;
-	subsol->exit_data = exit_data;
 	subsol->child_watch =
 		g_child_watch_add (subsol->child_pid,
 				   (GChildWatchFunc)cb_child_exit, subsol);
diff --git a/src/tools/gnm-solver.h b/src/tools/gnm-solver.h
index 7a6adad..83722de 100644
--- a/src/tools/gnm-solver.h
+++ b/src/tools/gnm-solver.h
@@ -207,6 +207,7 @@ typedef struct {
 	gboolean (*start) (GnmSolver *solver,
 			   WorkbookControl *wbc, GError **err);
 	gboolean (*stop) (GnmSolver *solver, GError **err);
+	gboolean (*child_exit) (GnmSolver *solver, gboolean normal, int code);
 } GnmSolverClass;
 
 GType gnm_solver_get_type  (void);
@@ -250,9 +251,6 @@ typedef struct {
 	GPid child_pid;
 	guint child_watch;
 
-	GChildWatchFunc child_exit;
-	gpointer exit_data;
-
 	gint fd[3];
 	GIOChannel *channels[3];
 	guint channel_watches[3];
@@ -272,7 +270,6 @@ gboolean gnm_sub_solver_spawn
 		(GnmSubSolver *subsol,
 		 char **argv,
 		 GSpawnChildSetupFunc child_setup, gpointer setup_data,
-		 GChildWatchFunc child_exit, gpointer exit_data,
 		 GIOFunc io_stdout, gpointer stdout_data,
 		 GIOFunc io_stderr, gpointer stderr_data,
 		 GError **err);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]