[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