[maemo-commits] [maemo-commits] r19469 - projects/haf/trunk/dbus-glib/debian/patches
From: subversion at stage.maemo.org subversion at stage.maemo.orgDate: Thu Oct 22 14:12:40 EEST 2009
- Previous message: [maemo-commits] r19468 - projects/haf/trunk/maemo-launcher/debian
- Next message: [maemo-commits] r19470 - projects/haf/trunk/dbus-glib/debian/patches
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Author: ststephe Date: 2009-10-22 14:12:04 +0300 (Thu, 22 Oct 2009) New Revision: 19469 Added: projects/haf/trunk/dbus-glib/debian/patches/80-DBusGProxy-signal-match.patch Log: NB#141956: DBusGProxy signal match rule optimization Added: projects/haf/trunk/dbus-glib/debian/patches/80-DBusGProxy-signal-match.patch =================================================================== --- projects/haf/trunk/dbus-glib/debian/patches/80-DBusGProxy-signal-match.patch 2009-10-21 06:37:19 UTC (rev 19468) +++ projects/haf/trunk/dbus-glib/debian/patches/80-DBusGProxy-signal-match.patch 2009-10-22 11:12:04 UTC (rev 19469) @@ -0,0 +1,459 @@ +Index: dbus-glib-0.78/dbus/dbus-gproxy.c +=================================================================== +--- dbus-glib-0.78.orig/dbus/dbus-gproxy.c ++++ dbus-glib-0.78/dbus/dbus-gproxy.c +@@ -125,6 +125,12 @@ + { + GSList *proxies; /**< The list of proxies */ + ++ /** ++ * Set of signals with the DBusGProxy which subscribes to the signals ++ * gchar *signal_name -> GHashTable* of (DBusGProxy *proxy -> guint count) ++ */ ++ GHashTable *signal_subscribed; ++ + char name[4]; /**< name (empty string for none), nul byte, + * path, nul byte, + * interface, nul byte +@@ -147,8 +153,14 @@ + + GHashTable *proxy_lists; /**< Hash used to route incoming signals + * and iterate over proxies ++ * tristring -> DBusGProxyList + */ ++ GHashTable *owner_match_rule; /**< Hash to keep trace of match rules of ++ * NameOwnerChanged. ++ * gchar *name -> guint refcount ++ */ + GHashTable *owner_names; /**< Hash to keep track of mapping from ++ * char * -> GSList of DBusGProxyNameOwnerInfo + * base name -> [name,name,...] for proxies which + * are for names. + */ +@@ -260,6 +272,16 @@ + + } + ++ if (manager->owner_match_rule) ++ { ++ /* Since we destroyed all proxies, none can be tracking ++ * name owners ++ */ ++ g_assert (g_hash_table_size (manager->owner_match_rule) == 0); ++ g_hash_table_destroy (manager->owner_match_rule); ++ manager->owner_match_rule = NULL; ++ } ++ + if (manager->owner_names) + { + /* Since we destroyed all proxies, none can be tracking +@@ -455,6 +477,7 @@ + priv->path, + priv->interface); + list->proxies = NULL; ++ list->signal_subscribed = NULL; + + return list; + } +@@ -466,37 +489,51 @@ + * as they ref the GProxyManager + */ + g_slist_free (list->proxies); ++ if (list->signal_subscribed != NULL) ++ { ++ g_hash_table_destroy (list->signal_subscribed); ++ } + + g_free (list); + } + + static char* +-g_proxy_get_signal_match_rule (DBusGProxy *proxy) ++g_proxy_get_signal_match_rule (DBusGProxy *proxy, const gchar *signal_name) + { + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); + /* FIXME Escaping is required here */ + + if (priv->name) +- return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'", ++ { ++ if (signal_name == NULL) ++ return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'", + priv->name, priv->path, priv->interface); ++ else ++ return g_strdup_printf ("type='signal',sender='%s',path='%s'," ++ "interface='%s',member='%s'", ++ priv->name, priv->path, priv->interface, ++ signal_name); ++ } + else +- return g_strdup_printf ("type='signal',path='%s',interface='%s'", +- priv->path, priv->interface); ++ { ++ if (signal_name == NULL) ++ return g_strdup_printf ("type='signal',path='%s',interface='%s'", ++ priv->path, priv->interface); ++ else ++ return g_strdup_printf ("type='signal',path='%s',interface='%s'," ++ "member='%s'", ++ priv->path, priv->interface, signal_name); ++ } + } + + static char * +-g_proxy_get_owner_match_rule (DBusGProxy *proxy) ++g_proxy_get_owner_match_rule (const gchar *name) + { +- DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); +- if (priv->name) +- { +- return g_strdup_printf ("type='signal',sender='" DBUS_SERVICE_DBUS +- "',path='" DBUS_PATH_DBUS +- "',interface='" DBUS_INTERFACE_DBUS +- "',member='NameOwnerChanged'" +- ",arg0='%s'", priv->name); +- } +- return NULL; ++ return g_strdup_printf ("type='signal',sender='" DBUS_SERVICE_DBUS ++ "',path='" DBUS_PATH_DBUS ++ "',interface='" DBUS_INTERFACE_DBUS ++ "',member='NameOwnerChanged'" ++ ",arg0='%s'", name); + } + + typedef struct +@@ -921,21 +958,24 @@ + + LOCK_MANAGER (manager); + +- if (manager->owner_names == NULL) +- { +- manager->owner_names = g_hash_table_new_full (g_str_hash, +- g_str_equal, +- g_free, +- NULL); +- } +- + if (manager->proxy_lists == NULL) + { ++ g_assert (manager->owner_names == NULL); ++ g_assert (manager->owner_match_rule == NULL); ++ + list = NULL; + manager->proxy_lists = g_hash_table_new_full (tristring_hash, + tristring_equal, + NULL, + (GFreeFunc) g_proxy_list_free); ++ manager->owner_names = g_hash_table_new_full (g_str_hash, ++ g_str_equal, ++ g_free, ++ NULL); ++ manager->owner_match_rule = g_hash_table_new_full (g_str_hash, ++ g_str_equal, ++ g_free, ++ NULL); + } + else + { +@@ -958,26 +998,32 @@ + + if (list->proxies == NULL && priv->name) + { +- /* We have to add match rules to the server, +- * but only if the server is a message bus, +- * not if it's a peer. +- */ +- char *rule; +- +- rule = g_proxy_get_signal_match_rule (proxy); +- +- /* We don't check for errors; it's not like anyone would handle them, and +- * we don't want a round trip here. +- */ +- dbus_bus_add_match (manager->connection, +- rule, NULL); +- g_free (rule); +- +- rule = g_proxy_get_owner_match_rule (proxy); +- if (rule) +- dbus_bus_add_match (manager->connection, +- rule, NULL); +- g_free (rule); ++ gpointer orig_key, value; ++ ++ g_assert (list->signal_subscribed == NULL); ++ list->signal_subscribed = g_hash_table_new_full (g_str_hash, ++ g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy); ++ ++ if (g_hash_table_lookup_extended (manager->owner_match_rule, ++ priv->name, &orig_key, &value)) ++ { ++ /* The owner match rule is already here. Increment the refcount */ ++ gint count = GPOINTER_TO_INT (value) + 1; ++ g_hash_table_steal (manager->owner_match_rule, orig_key); ++ g_hash_table_insert (manager->owner_match_rule, orig_key, ++ GINT_TO_POINTER (count)); ++ } ++ else ++ { ++ char *rule; ++ rule = g_proxy_get_owner_match_rule (priv->name); ++ dbus_bus_add_match (manager->connection, ++ rule, NULL); ++ g_free (rule); ++ g_hash_table_insert (manager->owner_match_rule, g_strdup (priv->name), ++ GINT_TO_POINTER (1)); ++ } ++ + } + + g_assert (g_slist_find (list->proxies, proxy) == NULL); +@@ -1074,22 +1120,54 @@ + } + } + ++ if (list->signal_subscribed != NULL) ++ { ++ GHashTableIter iter; ++ gpointer proxy_set; ++ gpointer signal_name; ++ ++ g_hash_table_iter_init (&iter, list->signal_subscribed); ++ while (g_hash_table_iter_next (&iter, &signal_name, &proxy_set)) ++ { ++ g_hash_table_remove (proxy_set, proxy); ++ if (g_hash_table_size (proxy_set) == 0) ++ { ++ char *rule; ++ ++ rule = g_proxy_get_signal_match_rule (proxy, (gchar *) signal_name); ++ dbus_bus_remove_match (priv->manager->connection, ++ rule, NULL); ++ g_free (rule); ++ } ++ } ++ } ++ + if (list->proxies == NULL) + { +- char *rule; ++ gpointer orig_key, value; ++ + g_hash_table_remove (manager->proxy_lists, + tri); +- list = NULL; +- +- rule = g_proxy_get_signal_match_rule (proxy); +- dbus_bus_remove_match (manager->connection, +- rule, NULL); +- g_free (rule); +- rule = g_proxy_get_owner_match_rule (proxy); +- if (rule) +- dbus_bus_remove_match (manager->connection, +- rule, NULL); +- g_free (rule); ++ if (priv->name && g_hash_table_lookup_extended ( ++ manager->owner_match_rule, priv->name, &orig_key, &value)) ++ { ++ gint count = GPOINTER_TO_INT (value) - 1; ++ if (count == 0) ++ { ++ char *rule; ++ rule = g_proxy_get_owner_match_rule (priv->name); ++ dbus_bus_remove_match (manager->connection, ++ rule, NULL); ++ g_free (rule); ++ g_hash_table_remove (manager->owner_match_rule, priv->name); ++ } ++ else ++ { ++ g_hash_table_steal (manager->owner_match_rule, orig_key); ++ g_hash_table_insert (manager->owner_match_rule, orig_key, ++ GINT_TO_POINTER (count)); ++ } ++ } + } + + if (g_hash_table_size (manager->proxy_lists) == 0) +@@ -1098,6 +1176,12 @@ + manager->proxy_lists = NULL; + } + ++ if (g_hash_table_size (manager->owner_match_rule) == 0) ++ { ++ g_hash_table_destroy (manager->owner_match_rule); ++ manager->owner_match_rule = NULL; ++ } ++ + g_free (tri); + + UNLOCK_MANAGER (manager); +@@ -2895,6 +2979,8 @@ + GClosure *closure; + GQuark q; + DBusGProxyPrivate *priv; ++ char *tri; ++ DBusGProxyList *list; + + g_return_if_fail (DBUS_IS_G_PROXY (proxy)); + g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); +@@ -2902,6 +2988,57 @@ + g_return_if_fail (handler != NULL); + + priv = DBUS_G_PROXY_GET_PRIVATE(proxy); ++ ++ tri = tristring_from_proxy (proxy); ++ list = g_hash_table_lookup (priv->manager->proxy_lists, tri); ++ g_free (tri); ++ /* We have to add match rules to the server, ++ * but only if the server is a message bus, ++ * not if it's a peer. ++ */ ++ if (priv->name && list->signal_subscribed != NULL) ++ { ++ gchar *orig_key; ++ GHashTable *proxy_set; ++ gboolean found = g_hash_table_lookup_extended (list->signal_subscribed, ++ signal_name, (gpointer *) &orig_key, (gpointer *) &proxy_set); ++ gint handler_count; ++ gpointer value; ++ ++ if (!found || g_hash_table_size (proxy_set) == 0) ++ { ++ char *rule; ++ ++ rule = g_proxy_get_signal_match_rule (proxy, signal_name); ++ /* We don't check for errors; it's not like anyone would handle ++ * them, and we don't want a round trip here. ++ */ ++ dbus_bus_add_match (priv->manager->connection, ++ rule, NULL); ++ g_free (rule); ++ } ++ ++ if (!found) ++ { ++ proxy_set = g_hash_table_new (NULL, NULL); ++ orig_key = g_strdup (signal_name); ++ } ++ ++ if (g_hash_table_lookup_extended (proxy_set, proxy, NULL, ++ &value)) ++ { ++ handler_count = GPOINTER_TO_UINT (value) + 1; ++ } ++ else ++ { ++ handler_count = 1; ++ } ++ g_hash_table_insert (proxy_set, proxy, GINT_TO_POINTER (handler_count)); ++ ++ g_hash_table_steal (list->signal_subscribed, signal_name); ++ g_hash_table_insert (list->signal_subscribed, orig_key, proxy_set); ++ } ++ + name = create_signal_name (priv->interface, signal_name); + + q = g_quark_try_string (name); +@@ -2941,9 +3078,14 @@ + GCallback handler, + void *data) + { ++ guint matched_count; ++ gint handler_count; + char *name; + GQuark q; + DBusGProxyPrivate *priv; ++ char *tri; ++ DBusGProxyList *list; ++ gchar *_signal_name; + + g_return_if_fail (DBUS_IS_G_PROXY (proxy)); + g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); +@@ -2954,25 +3096,72 @@ + name = create_signal_name (priv->interface, signal_name); + + q = g_quark_try_string (name); ++ g_free (name); + +- if (q != 0) +- { +- g_signal_handlers_disconnect_matched (G_OBJECT (proxy), +- G_SIGNAL_MATCH_DETAIL | +- G_SIGNAL_MATCH_FUNC | +- G_SIGNAL_MATCH_DATA, +- signals[RECEIVED], +- q, +- NULL, +- G_CALLBACK (handler), data); +- } +- else ++ if (q == 0) + { + g_warning ("Attempt to disconnect from signal '%s' which is not registered\n", +- name); ++ signal_name); ++ return; + } + +- g_free (name); ++ /* signal_name may be freed by g_signal_handlers_disconnect_matched() :'( ++ * Keep a copy while we need it ++ */ ++ _signal_name = g_strdup (signal_name); ++ matched_count = g_signal_handlers_disconnect_matched (G_OBJECT (proxy), ++ G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, ++ signals[RECEIVED], q, NULL, G_CALLBACK (handler), data); ++ ++ tri = tristring_from_proxy (proxy); ++ list = g_hash_table_lookup (priv->manager->proxy_lists, tri); ++ g_free (tri); ++ ++ /* Remove a match rule */ ++ if (list->signal_subscribed != NULL) ++ { ++ GHashTable *proxy_set = g_hash_table_lookup (list->signal_subscribed, ++ _signal_name); ++ gpointer value; ++ ++ if (proxy_set == NULL || !g_hash_table_lookup_extended (proxy_set, proxy, ++ NULL, &value)) ++ { ++ g_warning ("Attempt to disconnect from signal '%s' which is not" ++ " registered\n", _signal_name); ++ g_free (_signal_name); ++ return; ++ } ++ ++ handler_count = GPOINTER_TO_INT (value); ++ handler_count -= matched_count; ++ g_assert (handler_count >= 0); ++ if (handler_count == 0) ++ { ++ g_hash_table_remove (proxy_set, proxy); ++ } ++ else ++ { ++ g_hash_table_insert (proxy_set, proxy, ++ GINT_TO_POINTER (handler_count)); ++ } ++ ++ if (g_hash_table_size (proxy_set) == 0) ++ { ++ char *rule; ++ ++ rule = g_proxy_get_signal_match_rule (proxy, _signal_name); ++ /* We don't check for errors; it's not like anyone would handle them, ++ * and we don't want a round trip here. ++ */ ++ dbus_bus_remove_match (priv->manager->connection, ++ rule, NULL); ++ g_free (rule); ++ ++ g_hash_table_remove (list->signal_subscribed, _signal_name); ++ } ++ } ++ g_free (_signal_name); + } + + /**
- Previous message: [maemo-commits] r19468 - projects/haf/trunk/maemo-launcher/debian
- Next message: [maemo-commits] r19470 - projects/haf/trunk/dbus-glib/debian/patches
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]