From 30aa937aa227e0cb5d3d63d2827df0aaa4006432 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Fri, 14 Jan 2005 01:40:49 +0000
Subject: [PATCH] small modification to make the solver interface not block the
 GUI when the solver runs without printing messages

---
 Fltk/Solvers.cpp | 120 ++++++++++++++++++++++++++++++-----------------
 doc/VERSIONS     |   6 ++-
 2 files changed, 80 insertions(+), 46 deletions(-)

diff --git a/Fltk/Solvers.cpp b/Fltk/Solvers.cpp
index c2d97b19f2..22fd93f046 100644
--- a/Fltk/Solvers.cpp
+++ b/Fltk/Solvers.cpp
@@ -1,4 +1,4 @@
-// $Id: Solvers.cpp,v 1.32 2005-01-13 23:39:10 geuzaine Exp $
+// $Id: Solvers.cpp,v 1.33 2005-01-14 01:40:49 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -40,6 +40,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/poll.h>
 #include <sys/un.h>
 #include <unistd.h>
 
@@ -118,56 +119,87 @@ int Solver(int num, char *args)
     SINFO[num].nbval[i] = 0;
   SINFO[num].pid = 0;
 
+  struct pollfd pfd;
+  pfd.fd = sock;
+  pfd.events = POLLIN|POLLPRI;
+  
   while(1) {
-    if(SINFO[num].pid < 0)
-      break;
-    Gmsh_ReceiveString(sock, &type, str);
-    switch (type) {
-    case GMSH_CLIENT_START:
-      SINFO[num].pid = atoi(str);
-      break;
-    case GMSH_CLIENT_STOP:
-      SINFO[num].pid = -1;
-      stop = 1;
-      break;
-    case GMSH_CLIENT_PROGRESS:
-      Msg(STATUS3N, "%s %s", SINFO[num].name, str);
-      break;
-    case GMSH_CLIENT_OPTION_1:
-    case GMSH_CLIENT_OPTION_2:
-    case GMSH_CLIENT_OPTION_3:
-    case GMSH_CLIENT_OPTION_4:
-    case GMSH_CLIENT_OPTION_5:
-      i = type - GMSH_CLIENT_OPTION;
-      strcpy(SINFO[num].option[i][SINFO[num].nbval[i]++], str);
-      break;
-    case GMSH_CLIENT_VIEW:
-      if(SINFO[num].merge_views) {
-        n = List_Nbr(CTX.post.list);
-        MergeProblem(str);
-        Draw();
-        if(n != List_Nbr(CTX.post.list))
-          WID->set_context(menu_post, 0);
+    // poll the socket file descriptor every 10 milliseconds until
+    // data is avalable; when nothing is available, just tend to
+    // pending GUI events. (This is much easier to manage than
+    // non-blocking IO. The real solution is of course to use threads,
+    // but that's still a bit of a nightmare to maintain in a portable
+    // way on all the platforms.)
+    while(1){
+      if(SINFO[num].pid < 0){ // process has been killed
+	stop = 1;
+	break;
       }
+      int ret = poll(&pfd, 1, 10);
+      if(ret == 0){ // nothing available
+	WID->check();
+      }
+      else if(ret > 0){ // data is there
+        break;
+      }
+      else{ // error
+        stop = 1;
+        break;
+      }
+    }
+  
+    if(stop)
       break;
-    case GMSH_CLIENT_INFO:
-      Msg(SOLVER, "%-8.8s: %s", SINFO[num].name, str);
-      break;
-    case GMSH_CLIENT_WARNING:
-    case GMSH_CLIENT_ERROR:
-      Msg(SOLVERR, "%-8.8s: %s", SINFO[num].name, str);
-      break;
-    default:
-      Msg(WARNING, "Unknown type of message received from %s",
-          SINFO[num].name);
-      Msg(SOLVER, "%-8.8s: %s", SINFO[num].name, str);
-      break;
+
+    if(Gmsh_ReceiveString(sock, &type, str)){
+      switch (type) {
+      case GMSH_CLIENT_START:
+	SINFO[num].pid = atoi(str);
+	break;
+      case GMSH_CLIENT_STOP:
+	SINFO[num].pid = -1;
+	stop = 1;
+	break;
+      case GMSH_CLIENT_PROGRESS:
+	Msg(STATUS3N, "%s %s", SINFO[num].name, str);
+	break;
+      case GMSH_CLIENT_OPTION_1:
+      case GMSH_CLIENT_OPTION_2:
+      case GMSH_CLIENT_OPTION_3:
+      case GMSH_CLIENT_OPTION_4:
+      case GMSH_CLIENT_OPTION_5:
+	i = type - GMSH_CLIENT_OPTION;
+	strcpy(SINFO[num].option[i][SINFO[num].nbval[i]++], str);
+	break;
+      case GMSH_CLIENT_VIEW:
+	if(SINFO[num].merge_views) {
+	  n = List_Nbr(CTX.post.list);
+	  MergeProblem(str);
+	  Draw();
+	  if(n != List_Nbr(CTX.post.list))
+	    WID->set_context(menu_post, 0);
+	}
+	break;
+      case GMSH_CLIENT_INFO:
+	Msg(SOLVER, "%-8.8s: %s", SINFO[num].name, str);
+	break;
+      case GMSH_CLIENT_WARNING:
+      case GMSH_CLIENT_ERROR:
+	Msg(SOLVERR, "%-8.8s: %s", SINFO[num].name, str);
+	break;
+      default:
+	Msg(WARNING, "Unknown type of message received from %s",
+	    SINFO[num].name);
+	Msg(SOLVER, "%-8.8s: %s", SINFO[num].name, str);
+	break;
+      }
+      WID->check();
     }
-    WID->check(); // update the GUI
+
     if(stop)
       break;
   }
-
+  
   for(i = 0; i < SINFO[num].nboptions; i++) {
     if(SINFO[num].nbval[i]) {
       WID->solver[num].choice[i]->clear();
diff --git a/doc/VERSIONS b/doc/VERSIONS
index 1942c8cc2d..6877b998c9 100644
--- a/doc/VERSIONS
+++ b/doc/VERSIONS
@@ -1,4 +1,4 @@
-$Id: VERSIONS,v 1.301 2005-01-13 05:45:45 geuzaine Exp $
+$Id: VERSIONS,v 1.302 2005-01-14 01:40:49 geuzaine Exp $
 
 New since 1.58: added support for discrete (triangulated) surfaces,
 either in STL format or with the new "Discrete Surface" command; added
@@ -9,7 +9,9 @@ view data (based on the same or on a different mesh); generalized
 Plugin(CutGrid); new plugins (Eigenvalues, Gradient, Curl,
 Divergence); changed default colormap to match Matlab's "Jet"
 colormap; new transformation matrix option for views (for
-non-destructive rotations, symmetries, etc.); fixed small bugs.
+non-destructive rotations, symmetries, etc.); improved solver
+interface to keep the GUI responsive during solver calls; the fixed
+small bugs.
 
 New in 1.58: fixed UNIX socket interface on Windows (broken by the TCP
 solver patch in 1.57); bumped version number of default
-- 
GitLab