[grits] Switch map and sat plugins to using thread pools



commit 80f10eefae0a443d3440dba2548a5184d62e7e9c
Author: Andy Spencer <andy753421 gmail com>
Date:   Tue May 24 05:59:48 2011 +0000

    Switch map and sat plugins to using thread pools
    
    TODO: switch evel as well

 src/plugins/map.c |  125 +++++++++++++++++++++++++++--------------------------
 src/plugins/map.h |    3 +-
 src/plugins/sat.c |  116 +++++++++++++++++++++++++------------------------
 src/plugins/sat.h |    3 +-
 4 files changed, 127 insertions(+), 120 deletions(-)
---
diff --git a/src/plugins/map.c b/src/plugins/map.c
index b1363e4..f9d1b67 100644
--- a/src/plugins/map.c
+++ b/src/plugins/map.c
@@ -24,7 +24,6 @@
  */
 
 #include <time.h>
-#include <stdlib.h>
 #include <glib/gstdio.h>
 #include <GL/gl.h>
 
@@ -47,46 +46,15 @@ static const guchar colormap[][2][4] = {
 struct _LoadTileData {
 	GritsPluginMap *map;
 	GritsTile      *tile;
-	gchar          *path;
+	guint8         *pixels;
+	gboolean        alpha;
+	gint            width;
+	gint            height;
 };
 static gboolean _load_tile_cb(gpointer _data)
 {
 	struct _LoadTileData *data = _data;
-	GritsPluginMap *map  = data->map;
-	GritsTile      *tile = data->tile;
-	gchar          *path = data->path;
-	g_free(data);
-
-	/* Load pixbuf */
 	g_debug("GritsPluginMap: _load_tile_cb start");
-	GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, NULL);
-	if (!pixbuf) {
-		g_warning("GritsPluginMap: _load_tile - Error loading pixbuf %s", path);
-		g_remove(path);
-		g_free(path);
-		return FALSE;
-	}
-	g_free(path);
-
-	/* Create Texture */
-	guchar   *pixels = gdk_pixbuf_get_pixels(pixbuf);
-	gboolean  alpha  = gdk_pixbuf_get_has_alpha(pixbuf);
-	gint      width  = gdk_pixbuf_get_width(pixbuf);
-	gint      height = gdk_pixbuf_get_height(pixbuf);
-
-	for (int i = 0; i < width*height; i++) {
-		for (int j = 0; j < G_N_ELEMENTS(colormap); j++) {
-			if (pixels[i*4+0] == colormap[j][0][0] &&
-			    pixels[i*4+1] == colormap[j][0][1] &&
-			    pixels[i*4+2] == colormap[j][0][2]) {
-				pixels[i*4+0] = colormap[j][1][0];
-				pixels[i*4+1] = colormap[j][1][1];
-				pixels[i*4+2] = colormap[j][1][2];
-				pixels[i*4+3] = colormap[j][1][3];
-				break;
-			}
-		}
-	}
 
 	guint *tex = g_new0(guint, 1);
 	glGenTextures(1, tex);
@@ -94,17 +62,18 @@ static gboolean _load_tile_cb(gpointer _data)
 
 	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 	glPixelStorei(GL_PACK_ALIGNMENT, 1);
-	glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0,
-			(alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, pixels);
+	glTexImage2D(GL_TEXTURE_2D, 0, 4, data->width, data->height, 0,
+			(data->alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, data->pixels);
 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 	glFlush();
 
-	tile->data = tex;
-	gtk_widget_queue_draw(GTK_WIDGET(map->viewer));
-	g_object_unref(pixbuf);
+	data->tile->data = tex;
+	gtk_widget_queue_draw(GTK_WIDGET(data->map->viewer));
+	g_free(data->pixels);
+	g_free(data);
 	return FALSE;
 }
 
@@ -112,10 +81,53 @@ static void _load_tile(GritsTile *tile, gpointer _map)
 {
 	GritsPluginMap *map = _map;
 	g_debug("GritsPluginMap: _load_tile start %p", g_thread_self());
+	if (map->aborted) {
+		g_debug("GritsPluginMap: _load_tile - aborted");
+		return;
+	}
+
+	/* Download tile */
+	gchar *path = grits_wms_fetch(map->wms, tile, GRITS_ONCE, NULL, NULL);
+	if (!path) return; // Canceled/error
+
+	/* Load pixbuf */
+	GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, NULL);
+	if (!pixbuf) {
+		g_warning("GritsPluginMap: _load_tile - Error loading pixbuf %s", path);
+		g_remove(path);
+		g_free(path);
+		return;
+	}
+	g_free(path);
+
+	/* Copy pixbuf data for callback */
 	struct _LoadTileData *data = g_new0(struct _LoadTileData, 1);
-	data->map  = map;
-	data->tile = tile;
-	data->path = grits_wms_fetch(map->wms, tile, GRITS_ONCE, NULL, NULL);
+	data->map    = map;
+	data->tile   = tile;
+	data->pixels = gdk_pixbuf_get_pixels(pixbuf);
+	data->alpha  = gdk_pixbuf_get_has_alpha(pixbuf);
+	data->width  = gdk_pixbuf_get_width(pixbuf);
+	data->height = gdk_pixbuf_get_height(pixbuf);
+	data->pixels = g_memdup(data->pixels,
+			data->width * data->height * (data->alpha ? 4 : 3));
+	g_object_unref(pixbuf);
+
+	/* Map texture colors, if needed */
+	for (int i = 0; i < data->width * data->height; i++) {
+		for (int j = 0; j < G_N_ELEMENTS(colormap); j++) {
+			if (data->pixels[i*4+0] == colormap[j][0][0] &&
+			    data->pixels[i*4+1] == colormap[j][0][1] &&
+			    data->pixels[i*4+2] == colormap[j][0][2]) {
+				data->pixels[i*4+0] = colormap[j][1][0];
+				data->pixels[i*4+1] = colormap[j][1][1];
+				data->pixels[i*4+2] = colormap[j][1][2];
+				data->pixels[i*4+3] = colormap[j][1][3];
+				break;
+			}
+		}
+	}
+
+	/* Load the GL texture from the main thread */
 	g_idle_add_full(G_PRIORITY_LOW, _load_tile_cb, data, NULL);
 	g_debug("GritsPluginMap: _load_tile end %p", g_thread_self());
 }
@@ -133,12 +145,10 @@ static void _free_tile(GritsTile *tile, gpointer _map)
 		g_idle_add_full(G_PRIORITY_LOW, _free_tile_cb, tile->data, NULL);
 }
 
-static gpointer _update_tiles(gpointer _map)
+static void _update_tiles(gpointer _, gpointer _map)
 {
 	g_debug("GritsPluginMap: _update_tiles");
 	GritsPluginMap *map = _map;
-	if (!g_mutex_trylock(map->mutex))
-		return NULL;
 	GritsPoint eye;
 	grits_viewer_get_location(map->viewer, &eye.lat, &eye.lon, &eye.elev);
 	grits_tile_update(map->tiles, &eye,
@@ -146,8 +156,6 @@ static gpointer _update_tiles(gpointer _map)
 			_load_tile, map);
 	grits_tile_gc(map->tiles, time(NULL)-10,
 			_free_tile, map);
-	g_mutex_unlock(map->mutex);
-	return NULL;
 }
 
 /*************
@@ -156,14 +164,7 @@ static gpointer _update_tiles(gpointer _map)
 static void _on_location_changed(GritsViewer *viewer,
 		gdouble lat, gdouble lon, gdouble elev, GritsPluginMap *map)
 {
-	g_thread_create(_update_tiles, map, FALSE, NULL);
-}
-
-static gpointer _threaded_init(GritsPluginMap *map)
-{
-	_load_tile(map->tiles, map);
-	_update_tiles(map);
-	return NULL;
+	g_thread_pool_push(map->threads, NULL+1, NULL);
 }
 
 /***********
@@ -184,7 +185,8 @@ GritsPluginMap *grits_plugin_map_new(GritsViewer *viewer)
 	map->viewer = g_object_ref(viewer);
 
 	/* Load initial tiles */
-	g_thread_create((GThreadFunc)_threaded_init, map, FALSE, NULL);
+	_load_tile(map->tiles, map);
+	_update_tiles(NULL, map);
 
 	/* Connect signals */
 	map->sigid = g_signal_connect(map->viewer, "location-changed",
@@ -215,7 +217,7 @@ static void grits_plugin_map_init(GritsPluginMap *map)
 {
 	g_debug("GritsPluginMap: init");
 	/* Set defaults */
-	map->mutex = g_mutex_new();
+	map->threads = g_thread_pool_new(_update_tiles, map, 1, FALSE, NULL);
 	map->tiles = grits_tile_new(NULL, NORTH, SOUTH, EAST, WEST);
 	map->wms   = grits_wms_new(
 		"http://labs.metacarta.com/wms/vmap0";, "basic", "image/png",
@@ -226,11 +228,13 @@ static void grits_plugin_map_dispose(GObject *gobject)
 {
 	g_debug("GritsPluginMap: dispose");
 	GritsPluginMap *map = GRITS_PLUGIN_MAP(gobject);
+	map->aborted = TRUE;
 	/* Drop references */
 	if (map->viewer) {
 		g_signal_handler_disconnect(map->viewer, map->sigid);
 		grits_viewer_remove(map->viewer, map->tiles);
 		soup_session_abort(map->wms->http->soup);
+		g_thread_pool_free(map->threads, TRUE, TRUE);
 		while (gtk_events_pending())
 			gtk_main_iteration();
 		g_object_unref(map->viewer);
@@ -243,9 +247,8 @@ static void grits_plugin_map_finalize(GObject *gobject)
 	g_debug("GritsPluginMap: finalize");
 	GritsPluginMap *map = GRITS_PLUGIN_MAP(gobject);
 	/* Free data */
-	grits_tile_free(map->tiles, _free_tile, map);
 	grits_wms_free(map->wms);
-	g_mutex_free(map->mutex);
+	grits_tile_free(map->tiles, _free_tile, map);
 	G_OBJECT_CLASS(grits_plugin_map_parent_class)->finalize(gobject);
 
 }
diff --git a/src/plugins/map.h b/src/plugins/map.h
index 91741e2..ff4a9ac 100644
--- a/src/plugins/map.h
+++ b/src/plugins/map.h
@@ -37,8 +37,9 @@ struct _GritsPluginMap {
 	GritsViewer *viewer;
 	GritsTile   *tiles;
 	GritsWms    *wms;
-	GMutex      *mutex;
+	GThreadPool *threads;
 	gulong       sigid;
+	gboolean     aborted;
 };
 
 struct _GritsPluginMapClass {
diff --git a/src/plugins/sat.c b/src/plugins/sat.c
index ebcc838..f19df1c 100644
--- a/src/plugins/sat.c
+++ b/src/plugins/sat.c
@@ -24,7 +24,6 @@
  */
 
 #include <time.h>
-#include <string.h>
 #include <glib/gstdio.h>
 #include <GL/gl.h>
 
@@ -39,32 +38,71 @@
 struct _LoadTileData {
 	GritsPluginSat *sat;
 	GritsTile      *tile;
-	gchar          *path;
+	guint8         *pixels;
+	gboolean        alpha;
+	gint            width;
+	gint            height;
 };
 static gboolean _load_tile_cb(gpointer _data)
 {
 	struct _LoadTileData *data = _data;
-	GritsPluginSat *sat  = data->sat;
-	GritsTile      *tile = data->tile;
-	gchar          *path = data->path;
+	g_debug("GritsPluginSat: _load_tile_cb start");
+
+	guint *tex = g_new0(guint, 1);
+	glGenTextures(1, tex);
+	glBindTexture(GL_TEXTURE_2D, *tex);
+
+	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+	glPixelStorei(GL_PACK_ALIGNMENT, 1);
+	glTexImage2D(GL_TEXTURE_2D, 0, 4, data->width, data->height, 0,
+			(data->alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, data->pixels);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+	glFlush();
+
+	data->tile->data = tex;
+	gtk_widget_queue_draw(GTK_WIDGET(data->sat->viewer));
+	g_free(data->pixels);
 	g_free(data);
+	return FALSE;
+}
+
+static void _load_tile(GritsTile *tile, gpointer _sat)
+{
+	GritsPluginSat *sat = _sat;
+	g_debug("GritsPluginSat: _load_tile start %p", g_thread_self());
+	if (sat->aborted) {
+		g_debug("GritsPluginSat: _load_tile - aborted");
+		return;
+	}
+
+	/* Download tile */
+	gchar *path = grits_wms_fetch(sat->wms, tile, GRITS_ONCE, NULL, NULL);
+	if (!path) return; // Canceled/error
 
 	/* Load pixbuf */
-	g_debug("GritsPluginSat: _load_tile_cb start");
 	GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, NULL);
 	if (!pixbuf) {
 		g_warning("GritsPluginSat: _load_tile - Error loading pixbuf %s", path);
 		g_remove(path);
 		g_free(path);
-		return FALSE;
+		return;
 	}
 	g_free(path);
 
-	/* Create Texture */
-	guchar   *pixels = gdk_pixbuf_get_pixels(pixbuf);
-	gboolean  alpha  = gdk_pixbuf_get_has_alpha(pixbuf);
-	gint      width  = gdk_pixbuf_get_width(pixbuf);
-	gint      height = gdk_pixbuf_get_height(pixbuf);
+	/* Copy pixbuf data for callback */
+	struct _LoadTileData *data = g_new0(struct _LoadTileData, 1);
+	data->sat    = sat;
+	data->tile   = tile;
+	data->pixels = gdk_pixbuf_get_pixels(pixbuf);
+	data->alpha  = gdk_pixbuf_get_has_alpha(pixbuf);
+	data->width  = gdk_pixbuf_get_width(pixbuf);
+	data->height = gdk_pixbuf_get_height(pixbuf);
+	data->pixels = g_memdup(data->pixels,
+			data->width * data->height * (data->alpha ? 4 : 3));
+	g_object_unref(pixbuf);
 
 	/* Draw a border */
 	//gint border = 10;
@@ -78,34 +116,7 @@ static gboolean _load_tile_cb(gpointer _data)
 	//	memset(&pixels[(i*stride)+((width-border)*4)], 0xff, border*4);
 	//}
 
-	guint *tex = g_new0(guint, 1);
-	glGenTextures(1, tex);
-	glBindTexture(GL_TEXTURE_2D, *tex);
-
-	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-	glPixelStorei(GL_PACK_ALIGNMENT, 1);
-	glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0,
-			(alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, pixels);
-	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-	glFlush();
-
-	tile->data = tex;
-	gtk_widget_queue_draw(GTK_WIDGET(sat->viewer));
-	g_object_unref(pixbuf);
-	return FALSE;
-}
-
-static void _load_tile(GritsTile *tile, gpointer _sat)
-{
-	GritsPluginSat *sat = _sat;
-	g_debug("GritsPluginSat: _load_tile start %p", g_thread_self());
-	struct _LoadTileData *data = g_new0(struct _LoadTileData, 1);
-	data->sat  = sat;
-	data->tile = tile;
-	data->path = grits_wms_fetch(sat->wms, tile, GRITS_ONCE, NULL, NULL);
+	/* Load the GL texture from the main thread */
 	g_idle_add_full(G_PRIORITY_LOW, _load_tile_cb, data, NULL);
 	g_debug("GritsPluginSat: _load_tile end %p", g_thread_self());
 }
@@ -123,12 +134,10 @@ static void _free_tile(GritsTile *tile, gpointer _sat)
 		g_idle_add_full(G_PRIORITY_LOW, _free_tile_cb, tile->data, NULL);
 }
 
-static gpointer _update_tiles(gpointer _sat)
+static void _update_tiles(gpointer _, gpointer _sat)
 {
 	g_debug("GritsPluginSat: _update_tiles");
 	GritsPluginSat *sat = _sat;
-	if (!g_mutex_trylock(sat->mutex))
-		return NULL;
 	GritsPoint eye;
 	grits_viewer_get_location(sat->viewer, &eye.lat, &eye.lon, &eye.elev);
 	grits_tile_update(sat->tiles, &eye,
@@ -136,8 +145,6 @@ static gpointer _update_tiles(gpointer _sat)
 			_load_tile, sat);
 	grits_tile_gc(sat->tiles, time(NULL)-10,
 			_free_tile, sat);
-	g_mutex_unlock(sat->mutex);
-	return NULL;
 }
 
 /*************
@@ -146,14 +153,7 @@ static gpointer _update_tiles(gpointer _sat)
 static void _on_location_changed(GritsViewer *viewer,
 		gdouble lat, gdouble lon, gdouble elev, GritsPluginSat *sat)
 {
-	g_thread_create(_update_tiles, sat, FALSE, NULL);
-}
-
-static gpointer _threaded_init(GritsPluginSat *sat)
-{
-	_load_tile(sat->tiles, sat);
-	_update_tiles(sat);
-	return NULL;
+	g_thread_pool_push(sat->threads, NULL+1, NULL);
 }
 
 /***********
@@ -174,7 +174,8 @@ GritsPluginSat *grits_plugin_sat_new(GritsViewer *viewer)
 	sat->viewer = g_object_ref(viewer);
 
 	/* Load initial tiles */
-	g_thread_create((GThreadFunc)_threaded_init, sat, FALSE, NULL);
+	_load_tile(sat->tiles, sat);
+	_update_tiles(NULL, sat);
 
 	/* Connect signals */
 	sat->sigid = g_signal_connect(sat->viewer, "location-changed",
@@ -205,7 +206,7 @@ static void grits_plugin_sat_init(GritsPluginSat *sat)
 {
 	g_debug("GritsPluginSat: init");
 	/* Set defaults */
-	sat->mutex = g_mutex_new();
+	sat->threads = g_thread_pool_new(_update_tiles, sat, 1, FALSE, NULL);
 	sat->tiles = grits_tile_new(NULL, NORTH, SOUTH, EAST, WEST);
 	sat->wms   = grits_wms_new(
 		"http://www.nasa.network.com/wms";, "bmng200406", "image/jpeg",
@@ -216,11 +217,13 @@ static void grits_plugin_sat_dispose(GObject *gobject)
 {
 	g_debug("GritsPluginSat: dispose");
 	GritsPluginSat *sat = GRITS_PLUGIN_SAT(gobject);
+	sat->aborted = TRUE;
 	/* Drop references */
 	if (sat->viewer) {
 		g_signal_handler_disconnect(sat->viewer, sat->sigid);
 		grits_viewer_remove(sat->viewer, sat->tiles);
 		soup_session_abort(sat->wms->http->soup);
+		g_thread_pool_free(sat->threads, TRUE, TRUE);
 		while (gtk_events_pending())
 			gtk_main_iteration();
 		g_object_unref(sat->viewer);
@@ -233,9 +236,8 @@ static void grits_plugin_sat_finalize(GObject *gobject)
 	g_debug("GritsPluginSat: finalize");
 	GritsPluginSat *sat = GRITS_PLUGIN_SAT(gobject);
 	/* Free data */
-	grits_tile_free(sat->tiles, _free_tile, sat);
 	grits_wms_free(sat->wms);
-	g_mutex_free(sat->mutex);
+	grits_tile_free(sat->tiles, _free_tile, sat);
 	G_OBJECT_CLASS(grits_plugin_sat_parent_class)->finalize(gobject);
 
 }
diff --git a/src/plugins/sat.h b/src/plugins/sat.h
index b871741..d22d14a 100644
--- a/src/plugins/sat.h
+++ b/src/plugins/sat.h
@@ -37,8 +37,9 @@ struct _GritsPluginSat {
 	GritsViewer *viewer;
 	GritsTile   *tiles;
 	GritsWms    *wms;
-	GMutex      *mutex;
+	GThreadPool *threads;
 	gulong       sigid;
+	gboolean     aborted;
 };
 
 struct _GritsPluginSatClass {



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