changeset 1015:2cdcf67e9300

run image loader in separate thread this feature is disabled by default for now, it must be enabled by configure --enable-threads
author nadvornik
date Sat, 30 Aug 2008 20:15:47 +0000
parents 4d3c98219246
children 9865e22d05f3
files configure.in src/Makefile.am src/image-load.c src/image-load.h src/main.c
diffstat 5 files changed, 154 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Sat Aug 30 13:04:06 2008 +0000
+++ b/configure.in	Sat Aug 30 20:15:47 2008 +0000
@@ -167,21 +167,6 @@
 AM_CONDITIONAL(HAVE_WINDRES, test "x$WINDRES" != "x:")
 AC_SUBST(WINDRES)
 
-have_libpthread=no
-AC_CHECK_LIB([pthread], [main],
-  [AC_CHECK_HEADER([pthread.h],
-     have_libpthread=yes,
-     have_libpthread=no)],
-  [AC_MSG_ERROR([Can't find the POSIX thread libraries])], [-lpthread])
-if test "x${have_libpthread}" = "xyes"; then
-        LIBPTHREAD='-lpthread'
-        AC_DEFINE(HAVE_LIBPTHREAD, 1, [Define if pthread is available])
-else
-  AC_MSG_WARN([POSIX thread header not installed])
-fi
-AC_MSG_CHECKING(for libpthread)
-AC_MSG_RESULT([${have_libpthread}])
-
 dnl reasonable guesses for where stuff is installed
 if test "x$prefix" = "xNONE"; then
   prefix="/usr/local"
@@ -189,7 +174,26 @@
   prefix=$prefix
 fi
 
+AM_PATH_GLIB_2_0(2.4.0,,AC_MSG_ERROR(GLIB >= 2.4.0 not installed.))
 AM_PATH_GTK_2_0(2.4.0,,AC_MSG_ERROR(GTK+ >= 2.4.0 not installed.))
+
+have_gthread="no"
+AC_ARG_ENABLE([threads],
+  AC_HELP_STRING([--enable-threads], [enable thread support]),
+[
+if test "x${enableval}" = "xyes"; then
+  PKG_CHECK_MODULES(GTHREAD, [gthread-2.0], have_gthread="yes", [AC_MSG_WARN("No thread support in glib")])
+fi
+], )
+
+
+if test "x$have_gthread" != "xno"; then
+        AC_DEFINE(HAVE_GTHREAD, 1, Define if you have gthread library)
+        GLIB_CFLAGS="$GTHREAD_CFLAGS"
+        GLIB_LIBS="$GTHREAD_LIBS"
+fi
+
+
 AC_PATH_PROGS(GDK_PIXBUF_CSOURCE, "gdk-pixbuf-csource")
 AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
 
@@ -376,7 +380,7 @@
   CXXFLAGS:      $CXXFLAGS
   Gtk:           $GTK_CFLAGS
   Glib:          $GLIB_CFLAGS
-  Thread:        $LIBPTHREAD
+  Thread:        $GTHREAD_LIBS
   Others:	 $LCMS_LIBS $EXIV2_LIBS
 
 Localization:
--- a/src/Makefile.am	Sat Aug 30 13:04:06 2008 +0000
+++ b/src/Makefile.am	Sat Aug 30 20:15:47 2008 +0000
@@ -123,6 +123,7 @@
 	filefilter.h	\
 	gq-marshal.c	\
 	gq-marshal.h	\
+	gq-marshal.list \
 	format_canon.c	\
 	format_canon.h	\
 	format_fuji.c	\
--- a/src/image-load.c	Sat Aug 30 13:04:06 2008 +0000
+++ b/src/image-load.c	Sat Aug 30 20:15:47 2008 +0000
@@ -85,6 +85,10 @@
 	il->requested_width = 0;
 	il->requested_height = 0;
 	il->shrunk = FALSE;
+
+#ifdef HAVE_GTHREAD
+	il->data_mutex = g_mutex_new();
+#endif
 	DEBUG_1("new image loader %p, bufsize=%u idle_loop=%u", il, il->read_buffer_size, il->idle_read_loop_count);
 }
 
@@ -167,6 +171,9 @@
 
 	if (il->pixbuf) gdk_pixbuf_unref(il->pixbuf);
 	file_data_unref(il->fd);
+#ifdef HAVE_GTHREAD
+	g_mutex_free(il->data_mutex);
+#endif
 }
 
 void image_loader_free(ImageLoader *il)
@@ -207,8 +214,10 @@
 	ImageLoaderAreaParam *par = data;
 	ImageLoader *il = par->il;
 	g_signal_emit(il, signals[SIGNAL_AREA_READY], 0, par->x, par->y, par->w, par->h);
+	g_mutex_lock(il->data_mutex);
 	il->area_param_list = g_list_remove(il->area_param_list, par);
 	g_free(par);
+	g_mutex_unlock(il->data_mutex);
 	
 	return FALSE;
 }
@@ -230,7 +239,7 @@
 static gint image_loader_emit_percent_cb(gpointer data)
 {
 	ImageLoader *il = data;
-	g_signal_emit(il, signals[SIGNAL_PERCENT], 0, (gdouble)il->bytes_read / il->bytes_total);
+	g_signal_emit(il, signals[SIGNAL_PERCENT], 0, image_loader_get_percent(il));
 	return FALSE;
 }
 
@@ -262,7 +271,10 @@
 	par->w = w;
 	par->h = h;
 	
+	g_mutex_lock(il->data_mutex);
 	il->area_param_list = g_list_prepend(il->area_param_list, par);
+	g_mutex_unlock(il->data_mutex);
+	
 	g_idle_add_full(G_PRIORITY_HIGH, image_loader_emit_area_ready_cb, par, NULL);
 }
 
@@ -272,16 +284,27 @@
 static void image_loader_sync_pixbuf(ImageLoader *il)
 {
 	GdkPixbuf *pb;
-
-	if (!il->loader) return;
+	
+	g_mutex_lock(il->data_mutex);
+	
+	if (!il->loader) 
+		{
+		g_mutex_unlock(il->data_mutex);
+		return;
+		}
 
 	pb = gdk_pixbuf_loader_get_pixbuf(il->loader);
 
-	if (pb == il->pixbuf) return;
+	if (pb == il->pixbuf)
+		{
+		g_mutex_unlock(il->data_mutex);
+		return;
+		}
 
 	if (il->pixbuf) gdk_pixbuf_unref(il->pixbuf);
 	il->pixbuf = pb;
 	if (il->pixbuf) gdk_pixbuf_ref(il->pixbuf);
+	g_mutex_unlock(il->data_mutex);
 }
 
 static void image_loader_area_updated_cb(GdkPixbufLoader *loader,
@@ -290,10 +313,10 @@
 {
 	ImageLoader *il = data;
 
-	if (!il->pixbuf)
+	if (!image_loader_get_pixbuf(il))
 		{
 		image_loader_sync_pixbuf(il);
-		if (!il->pixbuf)
+		if (!image_loader_get_pixbuf(il))
 			{
 			log_printf("critical: area_ready signal with NULL pixbuf (out of mem?)\n");
 			}
@@ -336,7 +359,13 @@
 	gint scale = FALSE;
 	gint n;
 
-	if (il->requested_width < 1 || il->requested_height < 1) return;
+	g_mutex_lock(il->data_mutex);
+	if (il->requested_width < 1 || il->requested_height < 1) 
+		{
+		g_mutex_unlock(il->data_mutex);
+		return;
+		}
+	g_mutex_unlock(il->data_mutex);
 
 	format = gdk_pixbuf_loader_get_format(loader);
 	if (!format) return;
@@ -352,6 +381,8 @@
 
 	if (!scale) return;
 
+	g_mutex_lock(il->data_mutex);
+
 	if (width > il->requested_width || height > il->requested_height)
 		{
 		gint nw, nh;
@@ -372,6 +403,8 @@
 		gdk_pixbuf_loader_set_size(loader, nw, nh);
 		il->shrunk = TRUE;
 		}
+	g_mutex_unlock(il->data_mutex);
+
 }
 
 static void image_loader_stop_loader(ImageLoader *il)
@@ -392,7 +425,10 @@
 
 static void image_loader_setup_loader(ImageLoader *il)
 {
+	g_mutex_lock(il->data_mutex);
 	il->loader = gdk_pixbuf_loader_new();
+	g_mutex_unlock(il->data_mutex);
+
 	g_signal_connect(G_OBJECT(il->loader), "area_updated",
 			 G_CALLBACK(image_loader_area_updated_cb), il);
 	g_signal_connect(G_OBJECT(il->loader), "size_prepared",
@@ -606,6 +642,11 @@
 		il->idle_id = -1;
 		}
 		
+	if (il->thread)
+		{
+		il->stopping = TRUE;
+		g_thread_join(il->thread);
+		}
 
 	image_loader_stop_loader(il);
 	image_loader_stop_source(il);
@@ -647,6 +688,36 @@
 }
 
 /**************************************************************************************/
+/* execution via thread */
+
+gpointer image_loader_thread_run(gpointer data)
+{
+	ImageLoader *il = data;
+	gint cont = image_loader_begin(il);
+	
+	while (cont && !il->done && !il->stopping)
+		{
+		cont = image_loader_continue(il);
+		}
+	return NULL;
+}
+
+gint image_loader_start_thread(ImageLoader *il)
+{
+	if (!il) return FALSE;
+
+	if (!il->fd) return FALSE;
+
+	if (!image_loader_setup_source(il)) return FALSE;
+
+	il->thread = g_thread_create(image_loader_thread_run, il, TRUE, NULL);
+	if (!il->thread) return FALSE;
+		
+	return TRUE;
+}
+
+
+/**************************************************************************************/
 /* public interface */
 
 
@@ -656,16 +727,24 @@
 
 	if (!il->fd) return FALSE;
 
+#ifdef HAVE_GTHREAD
+	return image_loader_start_thread(il);
+#else
 	return image_loader_start_idle(il);
+#endif
 }
 
 
 /* don't forget to gdk_pixbuf_ref() it if you want to use it after image_loader_free() */
 GdkPixbuf *image_loader_get_pixbuf(ImageLoader *il)
 {
+	GdkPixbuf *ret;
 	if (!il) return NULL;
-
-	return il->pixbuf;
+	
+	g_mutex_lock(il->data_mutex);
+	ret = il->pixbuf;
+	g_mutex_unlock(il->data_mutex);
+	return ret;
 }
 
 gchar *image_loader_get_format(ImageLoader *il)
@@ -693,53 +772,82 @@
 {
 	if (!il) return;
 
+	g_mutex_lock(il->data_mutex);
 	il->requested_width = width;
 	il->requested_height = height;
+	g_mutex_unlock(il->data_mutex);
 }
 
 void image_loader_set_buffer_size(ImageLoader *il, guint count)
 {
 	if (!il) return;
 
+	g_mutex_lock(il->data_mutex);
 	il->idle_read_loop_count = count ? count : 1;
+	g_mutex_unlock(il->data_mutex);
 }
 
 void image_loader_set_priority(ImageLoader *il, gint priority)
 {
 	if (!il) return;
 
+	g_mutex_lock(il->data_mutex);
 	il->idle_priority = priority;
+	g_mutex_unlock(il->data_mutex);
 }
 
 
 gdouble image_loader_get_percent(ImageLoader *il)
 {
-	if (!il || il->bytes_total == 0) return 0.0;
-
-	return (gdouble)il->bytes_read / il->bytes_total;
+	gdouble ret;
+	if (!il) return 0.0;
+	
+	g_mutex_lock(il->data_mutex);
+	if (il->bytes_total == 0) 
+		{
+		ret = 0.0;
+		}
+	else
+		{
+		ret = (gdouble)il->bytes_read / il->bytes_total;
+		}
+	g_mutex_unlock(il->data_mutex);
+	return ret;
 }
 
 gint image_loader_get_is_done(ImageLoader *il)
 {
+	gint ret;
 	if (!il) return FALSE;
 
-	return il->done;
+	g_mutex_lock(il->data_mutex);
+	ret = il->done;
+	g_mutex_unlock(il->data_mutex);
+
+	return ret;
 }
 
 FileData *image_loader_get_fd(ImageLoader *il)
 {
+	FileData *ret;
 	if (!il) return NULL;
 
-	return il->fd;
-	
+	g_mutex_lock(il->data_mutex);
+	ret = il->fd;
+	g_mutex_unlock(il->data_mutex);
+
+	return ret;
 }
 
 gint image_loader_get_shrunk(ImageLoader *il)
 {
+	gint ret;
 	if (!il) return FALSE;
 
-	return il->shrunk;
-	
+	g_mutex_lock(il->data_mutex);
+	ret = il->shrunk;
+	g_mutex_unlock(il->data_mutex);
+	return ret;
 }
 
 
--- a/src/image-load.h	Sat Aug 30 13:04:06 2008 +0000
+++ b/src/image-load.h	Sat Aug 30 20:15:47 2008 +0000
@@ -45,6 +45,10 @@
 
 	gint idle_done_id;
 	GList *area_param_list;
+	
+	GThread *thread;
+	GMutex *data_mutex;
+	gint stopping;
 
 	guchar *mapped_file;
 	gint read_buffer_size;
--- a/src/main.c	Sat Aug 30 13:04:06 2008 +0000
+++ b/src/main.c	Sat Aug 30 20:15:47 2008 +0000
@@ -669,6 +669,10 @@
 	gchar *bufl;
 	CollectionData *cd = NULL;
 
+#ifdef HAVE_GTHREAD
+	g_thread_init (NULL);
+#endif
+	
 	/* init execution time counter (debug only) */
 	init_exec_time();