[gupnp] Survive ServiceProxy callback-list changes from callbacks



commit bf151a712020250461ceb1f43e7bcf949466800c
Author: Jussi Kukkonen <jussi kukkonen intel com>
Date:   Sun Jan 19 01:50:02 2014 +0200

    Survive ServiceProxy callback-list changes from callbacks
    
    Make notify-callback code more robust, so that removing a
    notify-callback from a notify-callback works.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=690400

 libgupnp/gupnp-service-proxy.c |   21 ++++++++++++++++-----
 1 files changed, 16 insertions(+), 5 deletions(-)
---
diff --git a/libgupnp/gupnp-service-proxy.c b/libgupnp/gupnp-service-proxy.c
index 3272723..ec76277 100644
--- a/libgupnp/gupnp-service-proxy.c
+++ b/libgupnp/gupnp-service-proxy.c
@@ -97,6 +97,7 @@ typedef struct {
         GType type;
 
         GList *callbacks;
+        GList *next_emit;
 } NotifyData;
 
 typedef struct {
@@ -1602,6 +1603,7 @@ gupnp_service_proxy_add_notify (GUPnPServiceProxy              *proxy,
 
                 data->type       = type;
                 data->callbacks  = NULL;
+                data->next_emit   = NULL;
 
                 g_hash_table_insert (proxy->priv->notify_hash,
                                      g_strdup (variable),
@@ -1627,6 +1629,9 @@ gupnp_service_proxy_add_notify (GUPnPServiceProxy              *proxy,
 
         data->callbacks = g_list_append (data->callbacks, callback_data);
 
+        if (data->next_emit == NULL)
+                data->next_emit = g_list_last (data->callbacks);
+
         return TRUE;
 }
 
@@ -1639,9 +1644,10 @@ gupnp_service_proxy_add_notify (GUPnPServiceProxy              *proxy,
  *
  * Cancels the variable change notification for @callback and @user_data.
  *
- * This function must not be called directly or indirectly from a
- * #GUPnPServiceProxyNotifyCallback associated with this service proxy, even
- * if it is for another variable.
+ * In version 20.9 and earlier this function must not be called directly
+ * or indirectly from a #GUPnPServiceProxyNotifyCallback associated with
+ * this service proxy, even if it is for another variable. In later
+ * versions such calls are allowed.
  *
  * Return value: %TRUE on success.
  **/
@@ -1681,6 +1687,9 @@ gupnp_service_proxy_remove_notify (GUPnPServiceProxy              *proxy,
                         /* Gotcha! */
                         g_slice_free (CallbackData, callback_data);
 
+                        if (data->next_emit == l)
+                                data->next_emit = data->next_emit->next;
+
                         data->callbacks =
                                 g_list_delete_link (data->callbacks, l);
                         if (data->callbacks == NULL) {
@@ -1722,11 +1731,13 @@ emit_notification (GUPnPServiceProxy *proxy,
                 return;
         }
 
-        /* Call callbacks */
-        for (l = data->callbacks; l; l = l->next) {
+        /* Call callbacks. Note that data->next_emit may change if
+         * callback calls remove_notify() or add_notify() */
+        for (l = data->callbacks; l; l = data->next_emit) {
                 CallbackData *callback_data;
 
                 callback_data = l->data;
+                data->next_emit = l->next;
 
                 callback_data->callback (proxy,
                                          (const char *) var_node->name,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]