From 0f389b62b619ab35a5e2f6f2921ff202eb10e97d Mon Sep 17 00:00:00 2001 From: Yevgen Muntyan <17531749+muntyan@users.noreply.github.com> Date: Wed, 27 Aug 2008 23:03:37 -0500 Subject: [PATCH] MooAsyncJob --- moo/mooutils/Makefile.ug | 8 +- moo/mooutils/mdhistorymgr.c | 62 ++++++++++++ moo/mooutils/mooutils-thread.c | 170 +++++++++++++++++++++++++++++++++ moo/mooutils/mooutils-thread.h | 10 ++ 4 files changed, 244 insertions(+), 6 deletions(-) diff --git a/moo/mooutils/Makefile.ug b/moo/mooutils/Makefile.ug index 00b619eb..c4369671 100644 --- a/moo/mooutils/Makefile.ug +++ b/moo/mooutils/Makefile.ug @@ -29,6 +29,7 @@ thread_sources = \ mooutils-thread.h mooutils_sources = \ + $(thread_sources) \ mdhistorymgr.c \ mdhistorymgr.h \ moo-environ.h \ @@ -147,11 +148,7 @@ mooutils_sources = \ moopython.lo: mooutils-fli.lo if MOO_OS_MINGW -mooutils_sources += $(thread_sources) $(win32_sources) -else -if MOO_ENABLE_TESTS -mooutils_sources += $(thread_sources) -endif +mooutils_sources += $(win32_sources) endif if MOO_ENABLE_UNIT_TESTS mooutils_sources += $(test_sources) @@ -160,7 +157,6 @@ endif EXTRA_DIST += \ moo-intltool-merge \ py2h.sh \ - $(thread_sources) \ $(win32_sources) \ $(test_sources) \ moowin32/mingw/fnmatch.h \ diff --git a/moo/mooutils/mdhistorymgr.c b/moo/mooutils/mdhistorymgr.c index d063c4ab..c6122b31 100644 --- a/moo/mooutils/mdhistorymgr.c +++ b/moo/mooutils/mdhistorymgr.c @@ -20,6 +20,7 @@ #include "mooutils/mooutils-treeview.h" #include "mooutils/moomarkup.h" #include "mooutils/mooprefs.h" +#include "mooutils/mooutils-thread.h" #include "marshals.h" #include @@ -1157,6 +1158,56 @@ create_tree_view (void) return tree_view; } +// typedef struct { +// GtkWidget *tree_view; +// GtkListStore *store; +// GQueue *files; +// GList *link; +// } Data; +// +// typedef struct { +// GdkPixbuf *pixbuf; +// char *display_basename; +// char *display_name; +// char *uri; +// } Entry; + +// static gboolean +// thread_func (gpointer user_data) +// { +// Data *data = user_data; +// int i; +// +// for (i = 0; i < 100 && data->link != data->files->tail; ++i, data->link = data->link->next) +// { +// MdHistoryItem *item = data->link->data; +// char *display_name, *display_basename; +// GdkPixbuf *pixbuf; +// GtkTreeIter iter; +// +// display_basename = uri_get_basename (item->uri); +// display_name = uri_get_display_name (item->uri); +// +// gdk_threads_enter (); +// /* XXX */ +// pixbuf = _moo_get_icon_for_path (display_name, data->tree_view, GTK_ICON_SIZE_MENU); +// gdk_threads_leave (); +// +// gtk_list_store_append (data->store, &iter); +// gtk_list_store_set (data->store, &iter, +// COLUMN_PIXBUF, pixbuf, +// COLUMN_NAME, display_basename, +// COLUMN_TOOLTIP, display_name, +// COLUMN_URI, md_history_item_get_uri (item), +// -1); +// +// g_free (display_basename); +// g_free (display_name); +// } +// +// return data->link != data->files->tail; +// } + static void populate_tree_view (MdHistoryMgr *mgr, GtkWidget *tree_view) @@ -1170,6 +1221,17 @@ populate_tree_view (MdHistoryMgr *mgr, model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); store = GTK_LIST_STORE (model); +// { +// Data *data = g_new0 (Data, 1); +// data->tree_view = tree_view; +// data->store = store; +// data->files = mgr->priv->files; +// data->link = mgr->priv->files->head; +// MooAsyncJob *job = moo_async_job_new (thread_func, data, g_free); +// moo_async_job_start (job); +// moo_async_job_unref (job); +// } + for (l = mgr->priv->files->head; l != NULL; l = l->next) { MdHistoryItem *item = l->data; diff --git a/moo/mooutils/mooutils-thread.c b/moo/mooutils/mooutils-thread.c index 4e6f2367..e266aad3 100644 --- a/moo/mooutils/mooutils-thread.c +++ b/moo/mooutils/mooutils-thread.c @@ -14,6 +14,7 @@ #include "mooutils/mooutils-thread.h" #include "mooutils/mooutils-misc.h" #include "mooutils/mooutils-debug.h" +#include "mooutils/mootype-macros.h" #include #include @@ -372,3 +373,172 @@ _moo_message_async (const char *format, _moo_event_queue_push (message_event_id, msg, g_free); } } + + +struct MooAsyncJob { + GObject base; + + MooAsyncJobCallback callback; + gpointer data; + GDestroyNotify data_notify; + + GThread *thread; + GMutex *mutex; + guint cancelled : 1; +}; + +typedef struct { + GObjectClass base_class; +} MooAsyncJobClass; + +MOO_DEFINE_TYPE_STATIC (MooAsyncJob, moo_async_job, G_TYPE_OBJECT) + +static void +moo_async_job_dispose (GObject *object) +{ + MooAsyncJob *job = (MooAsyncJob*) object; + + if (job->data_notify) + { + GDestroyNotify notify = job->data_notify; + job->data_notify = NULL; + notify (job->data); + job->data = NULL; + } + + g_assert (!job->thread); + + if (job->mutex) + { + g_mutex_free (job->mutex); + job->mutex = NULL; + } + + G_OBJECT_CLASS (moo_async_job_parent_class)->dispose (object); +} + +static void +moo_async_job_class_init (MooAsyncJobClass *klass) +{ + G_OBJECT_CLASS (klass)->dispose = moo_async_job_dispose; +} + +static void +moo_async_job_init (MooAsyncJob *job) +{ + job->callback = NULL; + job->data = NULL; + job->data_notify = NULL; + + job->thread = NULL; + job->mutex = g_mutex_new (); + job->cancelled = FALSE; +} + +MooAsyncJob * +moo_async_job_new (MooAsyncJobCallback callback, + gpointer data, + GDestroyNotify data_notify) +{ + MooAsyncJob *job; + + g_return_val_if_fail (callback != NULL, NULL); + + job = g_object_new (moo_async_job_get_type (), NULL); + job->callback = callback; + job->data = data; + job->data_notify = data_notify; + + return job; +} + +static gpointer +moo_async_job_thread_func (MooAsyncJob *job) +{ + gboolean proceed = TRUE; + + while (proceed) + { + g_mutex_lock (job->mutex); + + if (job->cancelled) + { + _moo_print_async ("%s: job cancelled\n", G_STRFUNC); + g_mutex_unlock (job->mutex); + break; + } + + g_mutex_unlock (job->mutex); + + proceed = job->callback (job->data); + + if (!proceed) + _moo_print_async ("%s: job finished\n", G_STRFUNC); + + if (proceed) + g_usleep (1000); + } + + g_mutex_lock (job->mutex); + + if (job->data_notify) + { + GDestroyNotify notify = job->data_notify; + job->data_notify = NULL; + notify (job->data); + } + + job->thread = NULL; + + g_mutex_unlock (job->mutex); + + g_object_unref (job); + return NULL; +} + +void +moo_async_job_start (MooAsyncJob *job) +{ + GError *error = NULL; + + g_return_if_fail (job != NULL); + g_return_if_fail (job->thread == NULL); + + g_mutex_lock (job->mutex); + + job->thread = g_thread_create ((GThreadFunc) moo_async_job_thread_func, + g_object_ref (job), + FALSE, &error); + if (!job->thread) + { + g_critical ("%s: could not start thread: %s", G_STRLOC, error->message); + g_error_free (error); + goto out; + } + +out: + g_mutex_unlock (job->mutex); +} + +void +moo_async_job_cancel (MooAsyncJob *job) +{ + g_return_if_fail (job != NULL); + g_mutex_lock (job->mutex); + job->cancelled = TRUE; + g_mutex_unlock (job->mutex); +} + +void +moo_async_job_ref (MooAsyncJob *job) +{ + g_return_if_fail (job != NULL); + g_object_ref (job); +} + +void +moo_async_job_unref (MooAsyncJob *job) +{ + g_return_if_fail (job != NULL); + g_object_unref (job); +} diff --git a/moo/mooutils/mooutils-thread.h b/moo/mooutils/mooutils-thread.h index 856721bd..fc98d8b1 100644 --- a/moo/mooutils/mooutils-thread.h +++ b/moo/mooutils/mooutils-thread.h @@ -21,6 +21,16 @@ G_BEGIN_DECLS typedef void (*MooEventQueueCallback) (GList *events, gpointer data); +typedef struct MooAsyncJob MooAsyncJob; +typedef gboolean (*MooAsyncJobCallback) (gpointer data); + +MooAsyncJob *moo_async_job_new (MooAsyncJobCallback callback, + gpointer data, + GDestroyNotify data_notify); +void moo_async_job_start (MooAsyncJob *job); +void moo_async_job_cancel (MooAsyncJob *job); +void moo_async_job_ref (MooAsyncJob *job); +void moo_async_job_unref (MooAsyncJob *job); guint _moo_event_queue_connect (MooEventQueueCallback callback, gpointer data,