diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2009-10-14 22:20:20 +0800 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2009-10-15 00:01:28 +0800 |
commit | c8d648fff1a1f130baab6838a4aab2c6f2162d66 (patch) | |
tree | 3d85405f1ba3e6c7759f4ee243a0794e71bb8ab2 /libempathy/empathy-utils.c | |
parent | a99138d9d745e0269f9a9a8182f8df92dcb61bda (diff) | |
download | gsoc2013-empathy-c8d648fff1a1f130baab6838a4aab2c6f2162d66.tar.gz gsoc2013-empathy-c8d648fff1a1f130baab6838a4aab2c6f2162d66.tar.zst gsoc2013-empathy-c8d648fff1a1f130baab6838a4aab2c6f2162d66.zip |
copy empathy_signal_connect_weak from telepathy-gabble
Diffstat (limited to 'libempathy/empathy-utils.c')
-rw-r--r-- | libempathy/empathy-utils.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/libempathy/empathy-utils.c b/libempathy/empathy-utils.c index 243b4b040..3b14b0028 100644 --- a/libempathy/empathy-utils.c +++ b/libempathy/empathy-utils.c @@ -403,3 +403,88 @@ empathy_protocol_name_to_display_name (const gchar *proto_name) return NULL; } +typedef struct { + GObject *instance; + GObject *user_data; + gulong handler_id; +} WeakHandlerCtx; + +static WeakHandlerCtx * +whc_new (GObject *instance, + GObject *user_data) +{ + WeakHandlerCtx *ctx = g_slice_new0 (WeakHandlerCtx); + + ctx->instance = instance; + ctx->user_data = user_data; + + return ctx; +} + +static void +whc_free (WeakHandlerCtx *ctx) +{ + g_slice_free (WeakHandlerCtx, ctx); +} + +static void user_data_destroyed_cb (gpointer, GObject *); + +static void +instance_destroyed_cb (gpointer ctx_, + GObject *where_the_instance_was) +{ + WeakHandlerCtx *ctx = ctx_; + + DEBUG ("instance for %p destroyed; cleaning up", ctx); + + /* No need to disconnect the signal here, the instance has gone away. */ + g_object_weak_unref (ctx->user_data, user_data_destroyed_cb, ctx); + whc_free (ctx); +} + +static void +user_data_destroyed_cb (gpointer ctx_, + GObject *where_the_user_data_was) +{ + WeakHandlerCtx *ctx = ctx_; + + DEBUG ("user_data for %p destroyed; disconnecting", ctx); + + g_signal_handler_disconnect (ctx->instance, ctx->handler_id); + g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx); + whc_free (ctx); +} + +/* This function is copied from telepathy-gabble: util.c */ +/** + * empathy_signal_connect_weak: + * @instance: the instance to connect to. + * @detailed_signal: a string of the form "signal-name::detail". + * @c_handler: the GCallback to connect. + * @user_data: an object to pass as data to c_handler calls. + * + * Connects a #GCallback function to a signal for a particular object, as if + * with g_signal_connect(). Additionally, arranges for the signal handler to be + * disconnected if @user_data is destroyed. + * + * This is intended to be a convenient way for objects to use themselves as + * user_data for callbacks without having to explicitly disconnect all the + * handlers in their finalizers. + */ +void +empathy_signal_connect_weak (gpointer instance, + const gchar *detailed_signal, + GCallback c_handler, + GObject *user_data) +{ + GObject *instance_obj = G_OBJECT (instance); + WeakHandlerCtx *ctx = whc_new (instance_obj, user_data); + + DEBUG ("connecting to %p:%s with context %p", instance, detailed_signal, ctx); + + ctx->handler_id = g_signal_connect (instance, detailed_signal, c_handler, + user_data); + + g_object_weak_ref (instance_obj, instance_destroyed_cb, ctx); + g_object_weak_ref (user_data, user_data_destroyed_cb, ctx); +} |