[telepathy-mission-control/master] McdDispatchOperation: track channels' life-cycles here, not in McdDispatcherContext
Simon McVittie
simon.mcvittie at collabora.co.uk
Mon Nov 2 06:41:33 PST 2009
This is a step towards having mcd_dispatcher_context_unref not have
unwanted side-effects.
---
src/mcd-dispatch-operation.c | 40 +++++++++++++++++++++++++++++-
src/mcd-dispatcher.c | 56 +----------------------------------------
2 files changed, 41 insertions(+), 55 deletions(-)
diff --git a/src/mcd-dispatch-operation.c b/src/mcd-dispatch-operation.c
index edc92d5..34ae9c5 100644
--- a/src/mcd-dispatch-operation.c
+++ b/src/mcd-dispatch-operation.c
@@ -578,6 +578,32 @@ error:
}
static void
+mcd_dispatch_operation_channel_aborted_cb (McdChannel *channel,
+ McdDispatchOperation *self)
+{
+ const GError *error;
+
+ g_object_ref (self); /* FIXME: use a GObject closure or something */
+
+ DEBUG ("Channel %p aborted while in a dispatch operation", channel);
+
+ /* if it was a channel request, and it was cancelled, then the whole
+ * context should be aborted */
+ error = mcd_channel_get_error (channel);
+ if (error && error->code == TP_ERROR_CANCELLED)
+ _mcd_dispatch_operation_set_cancelled (self);
+
+ _mcd_dispatch_operation_lose_channel (self, channel);
+
+ if (_mcd_dispatch_operation_peek_channels (self) == NULL)
+ {
+ DEBUG ("Nothing left in this context");
+ }
+
+ g_object_unref (self);
+}
+
+static void
mcd_dispatch_operation_set_property (GObject *obj, guint prop_id,
const GValue *val, GParamSpec *pspec)
{
@@ -626,9 +652,16 @@ mcd_dispatch_operation_set_property (GObject *obj, guint prop_id,
"Account?!");
}
- /* reference the channels */
+ /* reference the channels and connect to their signals */
for (list = priv->channels; list != NULL; list = list->next)
+ {
g_object_ref (list->data);
+
+ g_signal_connect_after (list->data, "abort",
+ G_CALLBACK (mcd_dispatch_operation_channel_aborted_cb),
+ operation);
+
+ }
}
break;
@@ -706,7 +739,12 @@ mcd_dispatch_operation_dispose (GObject *object)
if (priv->channels)
{
for (list = priv->channels; list != NULL; list = list->next)
+ {
+ g_signal_handlers_disconnect_by_func (list->data,
+ mcd_dispatch_operation_channel_aborted_cb, object);
g_object_unref (list->data);
+ }
+
g_list_free (priv->channels);
priv->channels = NULL;
}
diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index 7798e2e..e5e81f1 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -1237,33 +1237,6 @@ _mcd_dispatcher_context_abort (McdDispatcherContext *context,
}
static void
-on_channel_abort_context (McdChannel *channel, McdDispatcherContext *context)
-{
- const GError *error;
-
- DEBUG ("Channel %p aborted while in a dispatcher context", channel);
-
- /* if it was a channel request, and it was cancelled, then the whole
- * context should be aborted */
- error = mcd_channel_get_error (channel);
- if (error && error->code == TP_ERROR_CANCELLED)
- _mcd_dispatch_operation_set_cancelled (context->operation);
-
- /* Losing the channel might mean we get freed, which would make some of
- * the operations below very unhappy */
- mcd_dispatcher_context_ref (context, "CTXREF08");
-
- _mcd_dispatch_operation_lose_channel (context->operation, channel);
-
- if (_mcd_dispatch_operation_peek_channels (context->operation) == NULL)
- {
- DEBUG ("Nothing left in this context");
- }
-
- mcd_dispatcher_context_unref (context, "CTXREF08");
-}
-
-static void
on_operation_finished (McdDispatchOperation *operation,
McdDispatcherContext *context)
{
@@ -1339,8 +1312,6 @@ _mcd_dispatcher_enter_state_machine (McdDispatcher *dispatcher,
{
McdDispatcherContext *context;
McdDispatcherPrivate *priv;
- GList *list;
- McdChannel *channel;
McdAccount *account;
g_return_if_fail (MCD_IS_DISPATCHER (dispatcher));
@@ -1377,9 +1348,8 @@ _mcd_dispatcher_enter_state_machine (McdDispatcher *dispatcher,
* bundle? */
context->operation = _mcd_dispatch_operation_new (priv->clients,
- !requested, g_list_copy (channels),
- (const gchar * const *) possible_handlers);
- /* the copy of @channels is stolen, but the GObject references are not */
+ !requested, channels, (const gchar * const *) possible_handlers);
+ /* ownership of @channels is stolen, but the GObject references are not */
if (!requested)
{
@@ -1395,17 +1365,6 @@ _mcd_dispatcher_enter_state_machine (McdDispatcher *dispatcher,
G_CALLBACK (on_operation_finished), context);
}
- for (list = channels; list != NULL; list = list->next)
- {
- channel = MCD_CHANNEL (list->data);
-
- g_signal_connect_after (channel, "abort",
- G_CALLBACK (on_channel_abort_context),
- context);
- }
-
- g_list_free (channels);
-
DEBUG ("entering state machine for context %p", context);
sp_timestamp ("invoke internal filters");
@@ -2053,7 +2012,6 @@ mcd_dispatcher_context_unref (McdDispatcherContext * context,
const gchar *tag)
{
McdDispatcherPrivate *priv;
- GList *list;
/* FIXME: check for leaks */
g_return_if_fail (context);
@@ -2065,16 +2023,6 @@ mcd_dispatcher_context_unref (McdDispatcherContext * context,
{
DEBUG ("freeing the context %p", context);
- for (list = _mcd_dispatch_operation_dup_channels (context->operation);
- list != NULL;
- list = g_list_delete_link (list, list))
- {
- McdChannel *channel = MCD_CHANNEL (list->data);
-
- g_signal_handlers_disconnect_by_func (channel,
- G_CALLBACK (on_channel_abort_context), context);
- g_object_unref (channel);
- }
g_signal_handlers_disconnect_by_func (context->operation,
on_operation_finished,
context);
--
1.5.6.5
More information about the telepathy-commits
mailing list