[xiph-commits] r12279 - trunk/sushivision

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Mon Jan 1 13:05:54 PST 2007


Author: xiphmont
Date: 2007-01-01 13:05:48 -0800 (Mon, 01 Jan 2007)
New Revision: 12279

Modified:
   trunk/sushivision/gtksucks.c
   trunk/sushivision/gtksucks.h
   trunk/sushivision/internal.h
   trunk/sushivision/main.c
   trunk/sushivision/panel-1d.c
   trunk/sushivision/panel-1d.h
   trunk/sushivision/panel-2d.c
   trunk/sushivision/panel-2d.h
   trunk/sushivision/panel.c
Log:
More concurrency and responsiveness fixes 



Modified: trunk/sushivision/gtksucks.c
===================================================================
--- trunk/sushivision/gtksucks.c	2006-12-31 23:59:27 UTC (rev 12278)
+++ trunk/sushivision/gtksucks.c	2007-01-01 21:05:48 UTC (rev 12279)
@@ -226,6 +226,10 @@
   gdk_threads_set_lock_functions(recursive_gdk_lock,recursive_gdk_unlock);
 }
 
+pthread_mutex_t *gtk_get_mutex(void){
+  return &gdkm;
+}
+
 /**********************************************************************/
 /* Not really a fixup; generate menus that declare what the keyboard
    shortcuts are */

Modified: trunk/sushivision/gtksucks.h
===================================================================
--- trunk/sushivision/gtksucks.h	2006-12-31 23:59:27 UTC (rev 12278)
+++ trunk/sushivision/gtksucks.h	2007-01-01 21:05:48 UTC (rev 12279)
@@ -26,6 +26,7 @@
 extern void gtk_widget_remove_events (GtkWidget *widget, gint events);
 extern void gtk_button3_fixup();
 extern void gtk_mutex_fixup();
+extern pthread_mutex_t *gtk_get_mutex();
 extern GtkWidget *gtk_menu_new_twocol(GtkWidget *bind, 
 				      char **menu_list, 
 				      char **shortcuts,

Modified: trunk/sushivision/internal.h
===================================================================
--- trunk/sushivision/internal.h	2006-12-31 23:59:27 UTC (rev 12278)
+++ trunk/sushivision/internal.h	2007-01-01 21:05:48 UTC (rev 12279)
@@ -62,6 +62,8 @@
   int realized;
   int maps_dirty;
   int legend_dirty;
+  int maps_rendering;
+  int legend_rendering;
 
   // function bundles 
   void (*realize)(sushiv_panel_t *p);

Modified: trunk/sushivision/main.c
===================================================================
--- trunk/sushivision/main.c	2006-12-31 23:59:27 UTC (rev 12278)
+++ trunk/sushivision/main.c	2007-01-01 21:05:48 UTC (rev 12279)
@@ -37,17 +37,15 @@
 static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t mc = PTHREAD_COND_INITIALIZER;
 sig_atomic_t _sushiv_exiting=0;
+static int wake_pending = 0;
 
 static int instances;
 static sushiv_instance_t **instance_list;
 
 void _sushiv_clean_exit(int sig){
   _sushiv_exiting = 1;
+  _sushiv_wake_workers();
 
-  pthread_mutex_lock(&m);
-  pthread_cond_broadcast(&mc);
-  pthread_mutex_unlock(&m);
-
   //signal(sig,SIG_IGN);
   if(sig!=SIGINT)
     fprintf(stderr,
@@ -80,16 +78,16 @@
 void _sushiv_wake_workers(){
   if(instances){
     pthread_mutex_lock(&m);
+    wake_pending = instances;
     pthread_cond_broadcast(&mc);
     pthread_mutex_unlock(&m);
   }
 }
 
 static void *worker_thread(void *dummy){
-  pthread_mutex_lock(&m);
   while(1){
     if(_sushiv_exiting)break;
-
+    
     // look for work
     {
       int i,j,flag=0;
@@ -98,17 +96,52 @@
 	sushiv_instance_t *s = instance_list[j];
 				 
 	for(i=0;i<s->panels;i++){
+	  sushiv_panel_t *p = s->panel_list[i];
+
 	  if(_sushiv_exiting)break;
-	  pthread_mutex_unlock(&m);
+
+	  // pending remap work?
+	  gdk_threads_enter();
+	  if(p->private->maps_dirty && !p->private->maps_rendering){
+	    p->private->maps_dirty = 0;
+	    p->private->maps_rendering = 1;
+	    flag = 1;
+	    
+	    gdk_threads_leave ();
+	    p->private->map_redraw(p);
+	    gdk_threads_enter ();
+
+	    p->private->maps_rendering = 0;
+	  }
+
+	  // pending legend work?
+	  if(p->private->legend_dirty && !p->private->legend_rendering){
+	    p->private->legend_dirty = 0;
+	    p->private->legend_rendering = 1;
+	    flag = 1;
+	    
+	    gdk_threads_leave ();
+	    p->private->legend_redraw(p);
+	    gdk_threads_enter ();
+
+	    p->private->maps_rendering = 0;
+	  }
+	  gdk_threads_leave ();
+
+	  // pending computation work?
 	  flag |= _sushiv_panel_cooperative_compute(s->panel_list[i]);
-	  pthread_mutex_lock(&m);
 	}
       }
       if(flag==1)continue;
     }
     
     // nothing to do, wait
-    pthread_cond_wait(&mc,&m);
+    pthread_mutex_lock(&m);
+    if(!wake_pending)
+      pthread_cond_wait(&mc,&m);
+    else
+      wake_pending--;
+    pthread_mutex_unlock(&m);
   }
   
   pthread_mutex_unlock(&m);

Modified: trunk/sushivision/panel-1d.c
===================================================================
--- trunk/sushivision/panel-1d.c	2006-12-31 23:59:27 UTC (rev 12278)
+++ trunk/sushivision/panel-1d.c	2007-01-01 21:05:48 UTC (rev 12279)
@@ -65,25 +65,27 @@
     int dw = p1->data_size;
     double h = p1->panel_h;
 
-    scalespace sx = (p1->flip?p1->y:p1->x);
-    scalespace sy = (p1->flip?p1->x:p1->y);
-    
     /* blank frame to black */
     cairo_set_source_rgb (c, 0,0,0);
     cairo_paint(c);
 
-    /* do the panel and plot scales match?  If not, redraw the plot
-       scales */
-    if(memcmp(&sx,&plot->x,sizeof(sx)) |
-       memcmp(&sy,&plot->y,sizeof(sy))){
-      plot->x = sx;
-      plot->y = sy;
+    if(p1->data_vec){
 
-      plot_draw_scales(plot);
-    }
+      /* do the panel and plot scales match?  If not, redraw the plot
+	 scales */
+      
+      scalespace sx = (p1->flip?p1->y:p1->x);
+      scalespace sy = (p1->flip?p1->x:p1->y);
+      
+      if(memcmp(&sx,&plot->x,sizeof(sx)) ||
+	 memcmp(&sy,&plot->y,sizeof(sy))){
+	plot->x = sx;
+	plot->y = sy;
+	
+	plot_draw_scales(plot);
+      }
 
-    /* by objective */
-    if(p1->data_vec){
+      /* by objective */
       for(i=0;i<p->objectives;i++){
 	double *data_vec = p1->data_vec[i];
 	if(data_vec){

Modified: trunk/sushivision/panel-1d.h
===================================================================
--- trunk/sushivision/panel-1d.h	2006-12-31 23:59:27 UTC (rev 12278)
+++ trunk/sushivision/panel-1d.h	2007-01-01 21:05:48 UTC (rev 12279)
@@ -61,7 +61,6 @@
   int x_dnum; // number of dimension within panel, not global instance
 
   int last_line;
-  int dirty_flag;
 
   int peak_count;
 } sushiv_panel1d_t;

Modified: trunk/sushivision/panel-2d.c
===================================================================
--- trunk/sushivision/panel-2d.c	2006-12-31 23:59:27 UTC (rev 12278)
+++ trunk/sushivision/panel-2d.c	2007-01-01 21:05:48 UTC (rev 12279)
@@ -104,16 +104,6 @@
     plot_draw_scales(plot);
 }
 
-static int ilog10(int x){
-  int count=0;
-  if(x<0)x=-x;
-  while(x){
-    count++;
-    x/=10;
-  }
-  return count;
-}
-
 static void update_legend(sushiv_panel_t *p){  
   sushiv_panel2d_t *p2 = p->subtype->p2;
   Plot *plot = PLOT(p->private->graph);
@@ -583,6 +573,7 @@
     
     p2->serialno++;
     p2->last_line = 0;
+    p2->completed_lines = 0;
     
     _sushiv_wake_workers();
   }
@@ -833,14 +824,18 @@
     
     /* move rendered line back into widget */
     gdk_threads_enter ();
+    p2->completed_lines++;
+
     if(p2->serialno == serialno){
       u_int32_t *line = plot_get_background_line(plot, y);
       memcpy(line,render,w*sizeof(*render));
-      plot_expose_request_line(plot,y);
-      
-      if(p2->last_line==h){ // yes, the current last_line!
+      if(p2->completed_lines==h){ 
 	_sushiv_panel_dirty_legend(p);
-      }
+	plot_expose_request(plot);
+      }else
+	plot_expose_request_line(plot,y);
+      
+
     }
   }
    

Modified: trunk/sushivision/panel-2d.h
===================================================================
--- trunk/sushivision/panel-2d.h	2006-12-31 23:59:27 UTC (rev 12278)
+++ trunk/sushivision/panel-2d.h	2007-01-01 21:05:48 UTC (rev 12279)
@@ -52,7 +52,7 @@
   int y_dnum; // number of dimension within panel, not global instance
 
   int last_line;
-  int dirty_flag;
+  int completed_lines;
 
   int peak_count;
 

Modified: trunk/sushivision/panel.c
===================================================================
--- trunk/sushivision/panel.c	2006-12-31 23:59:27 UTC (rev 12278)
+++ trunk/sushivision/panel.c	2007-01-01 21:05:48 UTC (rev 12279)
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <pthread.h>
 #include <errno.h>
 #include <math.h>
 #include <signal.h>
@@ -45,70 +46,40 @@
   return 0;
 }
 
-/* doesn't take an unbounded period, but shouldn't be
-   synchronous in the interests of responsiveness. */
-static gboolean _map_idle_work(gpointer ptr){
-  sushiv_instance_t *s = (sushiv_instance_t *)ptr;
-  int i,flag=1;
-  
-  while(flag){
-    flag = 0;
-    
-    for(i=0;i<s->panels;i++){
-      sushiv_panel_t *p = s->panel_list[i];
-      gdk_threads_enter ();
-      if(p->private->maps_dirty){
-	p->private->maps_dirty = 0;
-	flag=1;
-	gdk_threads_leave ();
-      
-	p->private->map_redraw(p);
+// the following is slightly odd; we want map and legend updates to
+// fire when the UI is otherwise idle (only good way to do event
+// compression in gtk), but we don't want it processed int he main UI
+// thread because of render latencies.  Thus we have a map/legend
+// chain register an idle handler that then wakes the worker threads
+// and has them render the map/legend changes
 
-      }else
-	gdk_threads_leave ();
-    }
-  }
-
+static gboolean _idle_map_fire(gpointer ptr){
+  sushiv_panel_t *p = (sushiv_panel_t *)ptr;
+  gdk_threads_enter ();
+  p->private->maps_dirty = 1;
+  gdk_threads_leave ();
+  _sushiv_wake_workers();
   return FALSE;
 }
 
-static gboolean _legend_idle_work(gpointer ptr){
-  sushiv_instance_t *s = (sushiv_instance_t *)ptr;
-  int i,flag=1;
-  
-  while(flag){
-    flag = 0;
-
-    for(i=0;i<s->panels;i++){
-      sushiv_panel_t *p = s->panel_list[i];
-      gdk_threads_enter ();
-      if(p->private->legend_dirty){
-	p->private->legend_dirty = 0;
-	flag=1;
-	gdk_threads_leave ();
-      
-	p->private->legend_redraw(p);
-
-      }else
-	gdk_threads_leave ();
-    }
-  }
-
+static gboolean _idle_legend_fire(gpointer ptr){
+  sushiv_panel_t *p = (sushiv_panel_t *)ptr;
+  gdk_threads_enter ();
+  p->private->legend_dirty = 1;
+  gdk_threads_leave ();
+  _sushiv_wake_workers();
   return FALSE;
 }
 
-
 void _sushiv_panel_dirty_map(sushiv_panel_t *p){
   gdk_threads_enter ();
-  p->private->maps_dirty = 1;
-  g_idle_add(_map_idle_work,p->sushi);
+  g_idle_add(_idle_map_fire,p);
   gdk_threads_leave ();
 }
 
 void _sushiv_panel_dirty_legend(sushiv_panel_t *p){
   gdk_threads_enter ();
-  p->private->legend_dirty = 1;
-  g_idle_add(_legend_idle_work,p->sushi);
+  g_idle_add(_idle_legend_fire,p);
   gdk_threads_leave ();
 }
 



More information about the commits mailing list