Mercurial > geeqie
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; }