[xiph-commits] r13797 - trunk/sushivision

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Thu Sep 13 16:29:43 PDT 2007


Author: xiphmont
Date: 2007-09-13 16:29:43 -0700 (Thu, 13 Sep 2007)
New Revision: 13797

Modified:
   trunk/sushivision/gtksucks.c
   trunk/sushivision/gtksucks.h
   trunk/sushivision/internal.h
   trunk/sushivision/main.c
   trunk/sushivision/panel-2d.c
   trunk/sushivision/panel-2d.h
Log:


Modified: trunk/sushivision/gtksucks.c
===================================================================
--- trunk/sushivision/gtksucks.c	2007-09-13 23:05:16 UTC (rev 13796)
+++ trunk/sushivision/gtksucks.c	2007-09-13 23:29:43 UTC (rev 13797)
@@ -196,6 +196,54 @@
 }
 
 /**********************************************************************/
+/* fixup number 3: GDK uses whatever default mutex type offered by the
+   system, and this usually means non-recursive ('fast') mutextes.
+   The problem with this is that gdk_threads_enter() and
+   gdk_threads_leave() cannot be used in any call originating from the
+   main loop, but are required in calls from idle handlers and other
+   threads. In effect we would need seperate identical versions of
+   each widget method, one locked, one unlocked, depending on where
+   the call originated.  Eliminate this problem by installing a
+   recursive mutex. */
+
+static pthread_mutex_t gdkm;
+static pthread_mutexattr_t gdkma;
+static int depth = 0;
+static int firstunder = 0;
+
+void gdk_lock(void){
+  pthread_mutex_lock(&gdkm);
+  depth++;
+}
+
+void gdk_unlock(void){
+  depth--;
+  if(depth<0){
+    if(!firstunder){ // annoying detail of gtk locking; in apps that
+      // don't normally use threads, onr does not lock before entering
+      // mainloop; in apps that do thread, the mainloop must be
+      // locked.  We can't tell which situation was in place before
+      // setting up our own threading, so allow one refcount error
+      // which we assume was the unlocked mainloop of a normally
+      // unthreaded gtk app.
+      firstunder++;
+      depth=0;
+    }else{
+      fprintf(stderr,"Internal locking error; refcount < 0. Dumping core for debugging\n");
+      abort();
+    }
+  }else
+    pthread_mutex_unlock(&gdkm);
+}
+
+void _gtk_mutex_fixup(){
+  pthread_mutexattr_init(&gdkma);
+  pthread_mutexattr_settype(&gdkma,PTHREAD_MUTEX_RECURSIVE);
+  pthread_mutex_init(&gdkm,&gdkma);
+  gdk_threads_set_lock_functions(gdk_lock,gdk_unlock);
+}
+
+/**********************************************************************/
 /* Not really a fixup; generate menus that declare what the keyboard
    shortcuts are */
 

Modified: trunk/sushivision/gtksucks.h
===================================================================
--- trunk/sushivision/gtksucks.h	2007-09-13 23:05:16 UTC (rev 13796)
+++ trunk/sushivision/gtksucks.h	2007-09-13 23:29:43 UTC (rev 13797)
@@ -24,9 +24,7 @@
 
 extern void _gtk_widget_set_sensitive_fixup(GtkWidget *w, gboolean state);
 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 void _gtk_button3_fixup(void);
 
 extern GtkWidget *_gtk_menu_new_twocol(GtkWidget *bind, 
 				       _sv_propmap_t **items,
@@ -40,4 +38,8 @@
 extern void _gtk_box_freeze_child (GtkBox *box, GtkWidget *child);
 extern void _gtk_box_unfreeze_child (GtkBox *box, GtkWidget *child);
 
+extern void _gtk_mutex_fixup(void);
+extern void _gdk_lock(void);
+extern void _gdk_unlock(void);
+
 #endif

Modified: trunk/sushivision/internal.h
===================================================================
--- trunk/sushivision/internal.h	2007-09-13 23:05:16 UTC (rev 13796)
+++ trunk/sushivision/internal.h	2007-09-13 23:29:43 UTC (rev 13797)
@@ -29,38 +29,6 @@
 #include <libxml/tree.h>
 #include "sushivision.h"
 
-/* locking *****************************************************/
-
-// strict mutex acquisation ordering: 
-// gdk -> panel -> objective -> dimension -> scale
-// functions below check/enforce
-
-extern void _sv_gdk_lock_i(const char *func, int line);
-extern void _sv_gdk_unlock_i(const char *func, int line);
-extern void _sv_panel_lock_i(const char *func, int line);
-extern void _sv_panel_unlock_i(const char *func, int line);
-extern void _sv_objective_lock_i(const char *func, int line);
-extern void _sv_objective_unlock_i(const char *func, int line);
-extern void _sv_dimension_lock_i(const char *func, int line);
-extern void _sv_dimension_unlock_i(const char *func, int line);
-extern void _sv_scale_lock_i(const char *func, int line);
-extern void _sv_scale_unlock_i(const char *func, int line);
-
-#define gdk_lock() _sv_gdk_lock_i(__FUNCTION__,__LINE__);
-#define gdk_unlock() _sv_gdk_lock_i(__FUNCTION__,__LINE__);
-
-#define panel_lock() _sv_panel_lock_i(__FUNCTION__,__LINE__);
-#define panel_unlock() _sv_panel_lock_i(__FUNCTION__,__LINE__);
-
-#define obj_lock() _sv_objective_lock_i(__FUNCTION__,__LINE__);
-#define obj_unlock() _sv_objective_lock_i(__FUNCTION__,__LINE__);
-
-#define dim_lock() _sv_dimension_lock_i(__FUNCTION__,__LINE__);
-#define dim_unlock() _sv_dimension_lock_i(__FUNCTION__,__LINE__);
-
-#define scale_lock() _sv_scale_lock_i(__FUNCTION__,__LINE__);
-#define scale_unlock() _sv_scale_lock_i(__FUNCTION__,__LINE__);
-
 typedef struct {
   char *s;
   double v;

Modified: trunk/sushivision/main.c
===================================================================
--- trunk/sushivision/main.c	2007-09-13 23:05:16 UTC (rev 13796)
+++ trunk/sushivision/main.c	2007-09-13 23:29:43 UTC (rev 13797)
@@ -39,277 +39,48 @@
 #include "internal.h"
 #include "sushi-gtkrc.h"
 
-// strict mutex acquisation ordering: gdk -> panel -> objective -> dimension -> scale
-typedef struct {
-  int holding_gdk;
+// The locking model in sushivision is as simple as possible given the
+// computational and rendering concurrency.
 
-  int holding_panel;
-  const char *func_panel;
-  int line_panel;
+// All API and GTK/GDK access is locked by a single recursive mutex
+// installed into GDK.
 
-  int holding_obj;
-  const char *func_obj;
-  int line_obj;
+// Worker threads exist to handle high latency tasks asynchronously.
+// Tasks fall into three categories: data computation, plane
+// rendering, and scale/legend rendering.  The worker threads (with
+// one exception) never touch the main GDK mutex; any data protected
+// by the main mutex needed for a task is pulled out and encapsulated
+// when that task is set up from a GTK or API call.  The one exception
+// is expose requests after rendering; in this case, the worker waits
+// until it can drop all locks (usually as the very last step), does
+// so, and then issues an expose request locked by GDK.
 
-  int holding_dim;
-  const char *func_dim;
-  int line_dim;
+// All data objects that can be touched simultaneously by API/GTK/GDK
+// and the worker threads must also be locked.  This includes the
+// global panel list, each panel, each plane within the panel (and
+// subunits of the planes), the plot widget's canvas buffer, and the
+// plot widget's other render access.  Plot widget access is guarded
+// by standard mutexes.  The panel lists, panels and planes require
+// greater concurrency and use read/write mutexes.
 
-  int holding_scale;
-  const char *func_scale;
-  int line_scale;
+// lock acquisition order must move to the right:
+// GDK -> panel_list -> panel -> plane, plane_internal -> plot_main -> plot_bg 
+// 
+// Multiple panels (if needed) must be locked in order of list
+// Multiple planes (if needed) must be locked in order of list
+// Each plane type has an internal order for locking internal subunits 
 
-} mutexcheck;
+// Memory pointers/structures are protected by a r/w lock that is held
+// by any thread 'entering the abstraction' for the duration the
+// thread is assuming the structure will continue to exist.  It is
+// held even during long-latency operations to guarantee memory
+// consistency.
 
-static pthread_mutex_t panel_m = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t obj_m = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t dim_m = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t scale_m = PTHREAD_MUTEX_INITIALIZER;
-static pthread_key_t   _sv_mutexcheck_key;
+// The data inside a memory structure is protected by a second r/w
+// lock inside the structure that is dropped when possible during
+// long-duration operations.
 
-/**********************************************************************/
-/* GDK uses whatever default mutex type offered by the system, and
-   this usually means non-recursive ('fast') mutextes.  The problem
-   with this is that gdk_threads_enter() and gdk_threads_leave()
-   cannot be used in any call originating from the main loop, but are
-   required in calls from idle handlers and other threads. In effect
-   we would need seperate identical versions of each widget method,
-   one locked, one unlocked, depending on where the call originated.
-   Eliminate this problem by installing a recursive mutex. */
-
-static pthread_mutex_t gdk_m;
-static pthread_mutexattr_t gdk_ma;
-static int gdk_firstunder = 0;
-
-void _sv_gdk_lock_i(const char *func, int line){
-  mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key);
-  const char *m=NULL;
-  const char *f=NULL;
-  int l=-1;
-  
-  if(!check){
-    check = calloc(1,sizeof(*check));
-    pthread_setspecific(_sv_mutexcheck_key, (void *)check);
-  }
-
-  if(check->holding_panel){ m="panel"; f=check->func_panel; l=check->line_panel; }
-  if(check->holding_obj){ m="objective"; f=check->func_obj; l=check->line_obj; }
-  if(check->holding_dim){ m="dimension"; f=check->func_dim; l=check->line_dim; }
-  if(check->holding_scale){ m="scale"; f=check->func_scale; l=check->line_scale; }
-    
-  if(f){
-    if(func)
-      fprintf(stderr,"sushivision: Out of order locking error.\n"
-	      "\tTrying to acquire gdk lock in %s line %d,\n"
-	      "\t%s lock already held from %s line %d.\n",
-	      func,line,m,f,l);
-    else
-      fprintf(stderr,"sushivision: Out of order locking error.\n"
-	      "\tTrying to acquire gdk lock, %s lock already held\n"
-	      "\tfrom %s line %d.\n",
-	      m,f,l);
-  }
-
-  pthread_mutex_lock(&gdk_m);
-  check->holding_gdk++;
-
-}
-
-void _sv_gdk_unlock_i(const char *func, int line){
-  mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key);
-
-  if(!check){
-    if(!gdk_firstunder){ // annoying detail of gtk locking; in apps that
-      // don't normally use threads, one does not lock before entering
-      // mainloop; in apps that do thread, the mainloop must be
-      // locked.  We can't tell which situation was in place before
-      // setting up our own threading, so allow one refcount error
-      // which we assume was the unlocked mainloop of a normally
-      // unthreaded gtk app.
-      check = calloc(1,sizeof(*check));
-      pthread_setspecific(_sv_mutexcheck_key, (void *)check);
-      gdk_firstunder++;
-    }else{
-      if(func)
-	fprintf(stderr,"sushivision: locking error.\n"
-		"\tTrying to unlock gdk when no gdk lock held\n"
-		"\tin %s line %d.\n",
-		func,line);
-      else
-	fprintf(stderr,"sushivision: locking error.\n"
-		"\tTrying to unlock gdk when no gdk lock held.\n");
-      
-    }
-  }else{
-    check->holding_gdk--;
-    pthread_mutex_unlock(&gdk_m);
-  }
-}
-
-// dumbed down version to pass into gdk
-static void replacement_gdk_lock(void){
-  _sv_gdk_lock_i(NULL,-1);
-}
-
-static void replacement_gdk_unlock(void){
-  _sv_gdk_unlock_i(NULL,-1);
-}
-
-static mutexcheck *lockcheck(){
-  mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key);
-  if(!check){
-    check = calloc(1,sizeof(*check));
-    pthread_setspecific(_sv_mutexcheck_key, (void *)check);
-  }
-  return check;
-}
-
-void _sv_panel_lock_i(const char *func, int line){
-  mutexcheck *check = lockcheck();
-  const char *m=NULL, *f=NULL;
-  int l=-1;
-  
-  if(check->holding_obj){ m="objective"; f=check->func_obj; l=check->line_obj; }
-  if(check->holding_dim){ m="dimension"; f=check->func_dim; l=check->line_dim; }
-  if(check->holding_scale){ m="scale"; f=check->func_scale; l=check->line_scale; }
-    
-  if(f)
-    fprintf(stderr,"sushivision: Out of order locking error.\n"
-	    "\tTrying to acquire panel lock in %s line %d,\n"
-	    "\t%s lock already held from %s line %d.\n",
-	    func,line,m,f,l);
-
-  pthread_mutex_lock(&panel_m);
-  check->holding_panel++;
-  check->func_panel = func;
-  check->line_panel = line;
-
-}
-
-void _sv_panel_unlock_i(const char *func, int line){
-  mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key);
-  
-  if(!check || check->holding_panel<1){
-    fprintf(stderr,"sushivision: locking error.\n"
-	    "\tTrying to unlock panel when no panel lock held\n"
-	    "\tin %s line %d.\n",
-	    func,line);
-  }else{
-
-    check->holding_panel--;
-    check->func_panel = "(unknown)";
-    check->line_panel = -1;
-    pthread_mutex_unlock(&panel_m);
-
-  }
-}
-
-void _sv_objective_lock_i(const char *func, int line){
-  mutexcheck *check = lockcheck();
-  const char *m=NULL, *f=NULL;
-  int l=-1;
-  
-  if(check->holding_dim){ m="dimension"; f=check->func_dim; l=check->line_dim; }
-  if(check->holding_scale){ m="scale"; f=check->func_scale; l=check->line_scale; }
-    
-  if(f)
-    fprintf(stderr,"sushivision: Out of order locking error.\n"
-	    "\tTrying to acquire objective lock in %s line %d,\n"
-	    "\t%s lock already held from %s line %d.\n",
-	    func,line,m,f,l);
-
-  pthread_mutex_lock(&obj_m);
-  check->holding_obj++;
-  check->func_obj = func;
-  check->line_obj = line;
-
-}
-
-void _sv_objective_unlock_i(const char *func, int line){
-  mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key);
-  
-  if(!check || check->holding_obj<1){
-    fprintf(stderr,"sushivision: locking error.\n"
-	    "\tTrying to unlock objective when no objective lock held\n"
-	    "\tin %s line %d.\n",
-	    func,line);
-  }else{
-
-    check->holding_obj--;
-    check->func_obj = "(unknown)";
-    check->line_obj = -1;
-    pthread_mutex_unlock(&obj_m);
-
-  }
-}
-
-void _sv_dimension_lock_i(const char *func, int line){
-  mutexcheck *check = lockcheck();
-  const char *m=NULL, *f=NULL;
-  int l=-1;
-  
-  if(check->holding_scale){ m="scale"; f=check->func_scale; l=check->line_scale; }
-    
-  if(f)
-    fprintf(stderr,"sushivision: Out of order locking error.\n"
-	    "\tTrying to acquire dimension lock in %s line %d,\n"
-	    "\t%s lock already held from %s line %d.\n",
-	    func,line,m,f,l);
-
-  pthread_mutex_lock(&dim_m);
-  check->holding_dim++;
-  check->func_dim = func;
-  check->line_dim = line;
-
-}
-
-void _sv_dimension_unlock_i(const char *func, int line){
-  mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key);
-  
-  if(!check || check->holding_dim<1){
-    fprintf(stderr,"sushivision: locking error.\n"
-	    "\tTrying to unlock dimension when no dimension lock held\n"
-	    "\tin %s line %d.\n",
-	    func,line);
-  }else{
-
-    check->holding_dim--;
-    check->func_dim = "(unknown)";
-    check->line_dim = -1;
-    pthread_mutex_unlock(&dim_m);
-
-  }
-}
-
-void _sv_scale_lock_i(const char *func, int line){
-  mutexcheck *check = lockcheck();
-  
-  pthread_mutex_lock(&scale_m);
-  check->holding_scale++;
-  check->func_scale = func;
-  check->line_scale = line;
-
-}
-
-void _sv_scale_unlock_i(const char *func, int line){
-  mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key);
-  
-  if(!check || check->holding_scale<1){
-    fprintf(stderr,"sushivision: locking error.\n"
-	    "\tTrying to unlock scale when no scale lock held\n"
-	    "\tin %s line %d.\n",
-	    func,line);
-  }else{
-
-    check->holding_scale--;
-    check->func_scale = "(unknown)";
-    check->line_scale = -1;
-    pthread_mutex_unlock(&scale_m);
-
-  }
-}
-
-// mutex condm is only for protecting the condvar
+// mutex condm is only for protecting the worker condvar
 static pthread_mutex_t worker_condm = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t worker_cond = PTHREAD_COND_INITIALIZER;
 sig_atomic_t _sv_exiting=0;
@@ -338,12 +109,12 @@
   _sv_exiting = 1;
   _sv_wake_workers();
 
-  gdk_lock();
+  _gdk_lock();
   if(!gtk_main_iteration_do(FALSE)) // side effect: returns true if
 				    // there are no main loops active
     gtk_main_quit();
   
-  gdk_unlock();
+  _gdk_unlock();
 }
 
 static int num_proccies(){
@@ -485,11 +256,7 @@
   
   num_threads = ((num_proccies()*3)>>2);
 
-  pthread_mutexattr_init(&gdk_ma);
-  pthread_mutexattr_settype(&gdk_ma,PTHREAD_MUTEX_RECURSIVE);
-  pthread_mutex_init(&gdk_m,&gdk_ma);
-  gdk_threads_set_lock_functions(replacement_gdk_lock,
-				 replacement_gdk_unlock);
+  _gtk_mutex_fixup();
   gtk_init (NULL,NULL);
 
   return 0;

Modified: trunk/sushivision/panel-2d.c
===================================================================
--- trunk/sushivision/panel-2d.c	2007-09-13 23:05:16 UTC (rev 13796)
+++ trunk/sushivision/panel-2d.c	2007-09-13 23:29:43 UTC (rev 13797)
@@ -32,11 +32,40 @@
 #include <cairo-ft.h>
 #include "internal.h"
 
-/* helper functions for performing progressive computation and rendering */
+/* a panel is essentially four things:
+   
+   A collection of UI widgets
+   A collection of graphical planes
+   Code for managing concurrent data computation for planes
+   Code for managing concurrent rendering operations for planes
 
+*/
+
+
+
+/* from API or GTK thread */
+void _sv_panel_recompute(sv_panel_t *p){
+  gdk_lock(); 
+  
+  // collect and cache the data a panel needs to recompute 
+  // dimension value snapshots
+  // pending axes scalespaces
+
+  // collect and cache the data a panel needs to remap
+  // 
+
+  gdk_unlock();
+}
+
+
 static void _sv_plane2d_set_recompute(_sv_plane2d_t *z){
-  pthread_mutex_lock(z->data_m);
+  pthread_rwlock_wrlock(z->data_m);
+  pthread_rwlock_wrlock(z->image_m);
 
+
+
+  pthread_rwlock_unlock(z->data_m);
+  pthread_rwlock_unlock(z->image_m);
 }
 
 static void _sv_plane2d_set_remap(){

Modified: trunk/sushivision/panel-2d.h
===================================================================
--- trunk/sushivision/panel-2d.h	2007-09-13 23:05:16 UTC (rev 13796)
+++ trunk/sushivision/panel-2d.h	2007-09-13 23:29:43 UTC (rev 13797)
@@ -19,16 +19,8 @@
  * 
  */
 
-// plane mutex policy:  
-//
-//  gdk_m -> panel_m -> obj_m -> dim_m -> scale_m
-//  |
-//  -> z.data_m -> z.image_m -> bg.image_m 
-//  |
-//  -> z.status_m -> bg.status_m
+// plane mutex locking order: forward in plane list, down the plane struct
 
-#define PLANE_Z 1
- 
 typedef union  _sv_plane _sv_plane_t;
 typedef struct _sv_plane_proto _sv_plane_proto_t;
 typedef struct _sv_plane_bg _sv_plane_bg_t;
@@ -36,35 +28,34 @@
 
 struct _sv_plane_proto {
   // in common with all plane types
-  // common fields locked via panel
-  int plane_type;
-  sv_obj_t *o;
-  _sv_plane_t *share_next;
-  _sv_plane_t *share_prev;
+
+  // only GTK/API manipulates the common data
+  // GTK/API read access: GDK lock
+  // GTK/API write access: GDK lock -> panel.memlock(write);
+  // worker read access: panel.memlock(read)
+  int              plane_type;
+  sv_obj_t        *o;
+  _sv_plane_t     *share_next;
+  _sv_plane_t     *share_prev;
   _sv_panel2d_t   *panel;
 };
 
-// bg plane mutex policy: [mutexes from one other plane] -> image -> status -> [back to other plane]
 struct _sv_plane_bg {
-  // in common with all plane types
-  // common fields locked via panel
-  int             plane_type;
-  sv_obj_t       *o;
-  _sv_plane_t    *share_next;
-  _sv_plane_t    *share_prev;
-  _sv_panel2d_t  *panel;
+  int              plane_type;
+  sv_obj_t        *o;
+  _sv_plane_t     *share_next;
+  _sv_plane_t     *share_prev;
+  _sv_panel2d_t   *panel;
 
-  // image data
-   _sv_ucolor_t  *image; // panel size
-  int             image_serialno;
-  int             image_waiting;
-  int             image_incomplete;
-  int             image_nextline;
-  pthread_mutex_t image_m; 
+  // image data and concurrency tracking
+   _sv_ucolor_t   *image; // panel size
+  int              image_serialno;
+  int              image_waiting;
+  int              image_incomplete;
+  int              image_nextline;
+  unsigned char   *image_status; // rendering flags
+  pthread_rwlock_t image_m; 
 
-  // concurrency tracking
-  unsigned char  *line_status; // rendering flags
-  pthread_mutex_t status_m;
 };
 
 struct sv_zmap {
@@ -85,38 +76,42 @@
 struct _sv_plane_2d {
   // in common with all plane types
   // common fields locked via panel
-  int             plane_type; // == Z
-  sv_obj_t       *o;
-  _sv_plane_t    *share_next;
-  _sv_plane_t    *share_prev;
-  _sv_panel2d_t  *panel;
+  int              plane_type; // == Z
+  sv_obj_t        *o;
+  _sv_plane_t     *share_next;
+  _sv_plane_t     *share_prev;
+  _sv_panel2d_t   *panel;
 
   // subtype 
   // objective data
-  float          *data;              // data size
-  int             data_serialno;     
-  int             xscale_waiting; 
-  int             xscale_incomplete; 
-  int             yscale_waiting;   
-  int             yscale_incomplete;   
-  int             compute_waiting;
-  int             compute_incomplete;
-  int             data_nextline;
-  pthread_mutex_t data_m;
+  float           *data;              // data size
+  _sv_scalespace_t data_x;
+  _sv_scalespace_t data_y;
+  _sv_scalespace_t data_x_it;
+  _sv_scalespace_t data_y_it;
+  int              data_serialno;     
+  int              data_xscale_waiting; 
+  int              data_xscale_incomplete; 
+  int              data_yscale_waiting;   
+  int              data_yscale_incomplete;   
+  int              data_compute_waiting;
+  int              data_compute_incomplete;
+  int              data_nextline;
+  unsigned char   *data_flags;
+  pthread_mutex_t  data_m;
 
   // image plane
-  _sv_ucolor_t   *image; // panel size;
-  int             image_serialno;
-  struct sv_zmap  image_map;
-  int             image_waiting;
-  int             image_incomplete;
-  int             image_nextline;
-  pthread_mutex_t image_m;
+  _sv_ucolor_t    *image; // panel size;
+  int              image_serialno;
+  _sv_scalespace_t image_x;
+  _sv_scalespace_t image_y;
+  struct sv_zmap   image_map;
+  int              image_waiting;
+  int              image_incomplete;
+  int              image_nextline;
+  unsigned char   *image_flags;
+  pthread_mutex_t  image_m;
 
-  // concurrency tracking
-  unsigned char  *lineflags; // rendering flags
-  pthread_mutex_t status_m;
-
   // ui elements; use gdk lock
   _sv_mapping_t   *mapping;
   _sv_slider_t    *scale;
@@ -133,6 +128,8 @@
 } _sv_plane;
 
 typedef struct {
+  pthread_rwlock_t memlock;  
+  pthread_rwlock_t datalock; 
 
   GtkWidget *obj_table;
   GtkWidget *dim_table;



More information about the commits mailing list