[gimp] app: add gimp_async_add_callback_for_object()
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add gimp_async_add_callback_for_object()
- Date: Fri, 30 Nov 2018 09:16:41 +0000 (UTC)
commit 49fd2847ac6ed02963a3feed31f3e704ee217d55
Author: Ell <ell_se yahoo com>
Date: Fri Nov 30 03:28:18 2018 -0500
app: add gimp_async_add_callback_for_object()
... which is similar to gimp_async_add_callback(), taking an
additional GObject argument. The object is kept alive for the
duration of the callback, and the callback is automatically removed
when the object is destroyed (if it hasn't been already called).
This is analogous to g_signal_connect_object(), compared to
g_signal_connect().
app/core/gimpasync.c | 130 +++++++++++++++++++++++++++++++++++++++++++++------
app/core/gimpasync.h | 46 +++++++++---------
2 files changed, 142 insertions(+), 34 deletions(-)
---
diff --git a/app/core/gimpasync.c b/app/core/gimpasync.c
index 7a57f0f674..322d57d317 100644
--- a/app/core/gimpasync.c
+++ b/app/core/gimpasync.c
@@ -73,8 +73,10 @@ typedef struct _GimpAsyncCallbackInfo GimpAsyncCallbackInfo;
struct _GimpAsyncCallbackInfo
{
- GimpAsyncCallback callback;
- gpointer data;
+ GimpAsync *async;
+ GimpAsyncCallback callback;
+ gpointer data;
+ gpointer gobject;
};
struct _GimpAsyncPrivate
@@ -102,23 +104,26 @@ struct _GimpAsyncPrivate
/* local function prototypes */
-static void gimp_async_waitable_iface_init (GimpWaitableInterface *iface);
+static void gimp_async_waitable_iface_init (GimpWaitableInterface *iface);
static void gimp_async_cancelable_iface_init (GimpCancelableInterface *iface);
-static void gimp_async_finalize (GObject *object);
+static void gimp_async_finalize (GObject *object);
-static void gimp_async_wait (GimpWaitable *waitable);
-static gboolean gimp_async_try_wait (GimpWaitable *waitable);
-static gboolean gimp_async_wait_until (GimpWaitable *waitable,
- gint64 end_time);
+static void gimp_async_wait (GimpWaitable *waitable);
+static gboolean gimp_async_try_wait (GimpWaitable *waitable);
+static gboolean gimp_async_wait_until (GimpWaitable *waitable,
+ gint64 end_time);
-static void gimp_async_cancel (GimpCancelable *cancelable);
+static void gimp_async_cancel (GimpCancelable *cancelable);
-static gboolean gimp_async_idle (GimpAsync *async);
+static gboolean gimp_async_idle (GimpAsync *async);
-static void gimp_async_stop (GimpAsync *async);
-static void gimp_async_run_callbacks (GimpAsync *async);
+static void gimp_async_callback_weak_notify (GimpAsyncCallbackInfo *callback_info,
+ GObject *gobject);
+
+static void gimp_async_stop (GimpAsync *async);
+static void gimp_async_run_callbacks (GimpAsync *async);
G_DEFINE_TYPE_WITH_CODE (GimpAsync, gimp_async, G_TYPE_OBJECT,
@@ -330,6 +335,33 @@ gimp_async_idle (GimpAsync *async)
return G_SOURCE_REMOVE;
}
+static void
+gimp_async_callback_weak_notify (GimpAsyncCallbackInfo *callback_info,
+ GObject *gobject)
+{
+ GimpAsync *async = callback_info->async;
+ gboolean unref_async = FALSE;
+
+ g_mutex_lock (&async->priv->mutex);
+
+ g_queue_remove (&async->priv->callbacks, callback_info);
+
+ g_slice_free (GimpAsyncCallbackInfo, callback_info);
+
+ if (g_queue_is_empty (&async->priv->callbacks) && async->priv->idle_id)
+ {
+ g_source_remove (async->priv->idle_id);
+ async->priv->idle_id = 0;
+
+ unref_async = TRUE;
+ }
+
+ g_mutex_unlock (&async->priv->mutex);
+
+ if (unref_async)
+ g_object_unref (async);
+}
+
static void
gimp_async_stop (GimpAsync *async)
{
@@ -377,8 +409,20 @@ gimp_async_run_callbacks (GimpAsync *async)
while ((callback_info = g_queue_pop_head (&async->priv->callbacks)))
{
+ if (callback_info->gobject)
+ {
+ g_object_ref (callback_info->gobject);
+
+ g_object_weak_unref (callback_info->gobject,
+ (GWeakNotify) gimp_async_callback_weak_notify,
+ callback_info);
+ }
+
callback_info->callback (async, callback_info->data);
+ if (callback_info->gobject)
+ g_object_unref (callback_info->gobject);
+
g_slice_free (GimpAsyncCallbackInfo, callback_info);
}
@@ -447,12 +491,64 @@ gimp_async_add_callback (GimpAsync *async,
return;
}
- callback_info = g_slice_new (GimpAsyncCallbackInfo);
+ callback_info = g_slice_new0 (GimpAsyncCallbackInfo);
+ callback_info->async = async;
+ callback_info->callback = callback;
+ callback_info->data = data;
+
+ g_queue_push_tail (&async->priv->callbacks, callback_info);
+
+ g_mutex_unlock (&async->priv->mutex);
+}
+
+/* same as 'gimp_async_add_callback()', however, takes an additional 'gobject'
+ * argument, which should be a GObject.
+ *
+ * 'gobject' is guaranteed to remain alive for the duration of the callback.
+ *
+ * When 'gobject' is destroyed, the callback is automatically removed.
+ */
+void
+gimp_async_add_callback_for_object (GimpAsync *async,
+ GimpAsyncCallback callback,
+ gpointer data,
+ gpointer gobject)
+{
+ GimpAsyncCallbackInfo *callback_info;
+
+ g_return_if_fail (GIMP_IS_ASYNC (async));
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (G_IS_OBJECT (gobject));
+
+ g_mutex_lock (&async->priv->mutex);
+
+ if (async->priv->stopped && g_queue_is_empty (&async->priv->callbacks))
+ {
+ async->priv->synced = TRUE;
+
+ g_mutex_unlock (&async->priv->mutex);
+
+ g_object_ref (gobject);
+
+ callback (async, data);
+
+ g_object_unref (gobject);
+
+ return;
+ }
+
+ callback_info = g_slice_new0 (GimpAsyncCallbackInfo);
+ callback_info->async = async;
callback_info->callback = callback;
callback_info->data = data;
+ callback_info->gobject = gobject;
g_queue_push_tail (&async->priv->callbacks, callback_info);
+ g_object_weak_ref (gobject,
+ (GWeakNotify) gimp_async_callback_weak_notify,
+ callback_info);
+
g_mutex_unlock (&async->priv->mutex);
}
@@ -485,6 +581,14 @@ gimp_async_remove_callback (GimpAsync *async,
if (callback_info->callback == callback &&
callback_info->data == data)
{
+ if (callback_info->gobject)
+ {
+ g_object_weak_unref (
+ callback_info->gobject,
+ (GWeakNotify) gimp_async_callback_weak_notify,
+ callback_info);
+ }
+
g_queue_delete_link (&async->priv->callbacks, iter);
g_slice_free (GimpAsyncCallbackInfo, callback_info);
diff --git a/app/core/gimpasync.h b/app/core/gimpasync.h
index 5a7510fb90..0c2a671c94 100644
--- a/app/core/gimpasync.h
+++ b/app/core/gimpasync.h
@@ -53,39 +53,43 @@ struct _GimpAsyncClass
};
-GType gimp_async_get_type (void) G_GNUC_CONST;
+GType gimp_async_get_type (void) G_GNUC_CONST;
-GimpAsync * gimp_async_new (void);
+GimpAsync * gimp_async_new (void);
-gboolean gimp_async_is_synced (GimpAsync *async);
+gboolean gimp_async_is_synced (GimpAsync *async);
-void gimp_async_add_callback (GimpAsync *async,
- GimpAsyncCallback callback,
- gpointer data);
-void gimp_async_remove_callback (GimpAsync *async,
- GimpAsyncCallback callback,
- gpointer data);
+void gimp_async_add_callback (GimpAsync *async,
+ GimpAsyncCallback callback,
+ gpointer data);
+void gimp_async_add_callback_for_object (GimpAsync *async,
+ GimpAsyncCallback callback,
+ gpointer data,
+ gpointer gobject);
+void gimp_async_remove_callback (GimpAsync *async,
+ GimpAsyncCallback callback,
+ gpointer data);
-gboolean gimp_async_is_stopped (GimpAsync *async);
+gboolean gimp_async_is_stopped (GimpAsync *async);
-void gimp_async_finish (GimpAsync *async,
- gpointer result);
-void gimp_async_finish_full (GimpAsync *async,
- gpointer result,
- GDestroyNotify result_destroy_func);
-gboolean gimp_async_is_finished (GimpAsync *async);
-gpointer gimp_async_get_result (GimpAsync *async);
+void gimp_async_finish (GimpAsync *async,
+ gpointer result);
+void gimp_async_finish_full (GimpAsync *async,
+ gpointer result,
+ GDestroyNotify result_destroy_func);
+gboolean gimp_async_is_finished (GimpAsync *async);
+gpointer gimp_async_get_result (GimpAsync *async);
-void gimp_async_abort (GimpAsync *async);
+void gimp_async_abort (GimpAsync *async);
-gboolean gimp_async_is_canceled (GimpAsync *async);
+gboolean gimp_async_is_canceled (GimpAsync *async);
-void gimp_async_cancel_and_wait (GimpAsync *async);
+void gimp_async_cancel_and_wait (GimpAsync *async);
/* stats */
-gint gimp_async_get_n_running (void);
+gint gimp_async_get_n_running (void);
#endif /* __GIMP_ASYNC_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]