From a875a1fad9f65b59c57198c72e83373840823304 Mon Sep 17 00:00:00 2001 From: Travis Reitter Date: Wed, 6 Jul 2011 17:39:40 -0700 Subject: [PATCH] Cut unnecessary Tpf.PersonaStore._is_prepared locking. Helps: bgo#652637 - Don't hold locks across async calls --- backends/telepathy/lib/tpf-persona-store.vala | 207 +++++++++++++------------- 1 file changed, 102 insertions(+), 105 deletions(-) diff --git a/backends/telepathy/lib/tpf-persona-store.vala b/backends/telepathy/lib/tpf-persona-store.vala index 8afe084..fc6486d 100644 --- a/backends/telepathy/lib/tpf-persona-store.vala +++ b/backends/telepathy/lib/tpf-persona-store.vala @@ -448,130 +448,127 @@ public class Tpf.PersonaStore : Folks.PersonaStore { Internal.profiling_start ("preparing Tpf.PersonaStore (ID: %s)", this.id); - lock (this._is_prepared) + if (this._is_prepared || this._prepare_pending) { - if (this._is_prepared || this._prepare_pending) - { - return; - } + return; + } - try + try + { + this._prepare_pending = true; + + this._account_manager = AccountManager.dup (); + + /* FIXME: Add all contact features on AM's factory. We should not + * force preparing all features but let app define what it needs, + * but this is for backward compatibility. + * Note that if application already prepared TpContacts before + * preparing this store, this will have no effect on existing + * contacts. */ + var factory = this._account_manager.get_factory (); + factory.add_contact_features ({ + ContactFeature.ALIAS, + ContactFeature.AVATAR_DATA, + ContactFeature.AVATAR_TOKEN, + ContactFeature.CAPABILITIES, + ContactFeature.CLIENT_TYPES, + ContactFeature.PRESENCE, + ContactFeature.CONTACT_INFO, + ContactFeature.CONTACT_GROUPS + }); + + this._account_manager.invalidated.connect ( + this._account_manager_invalidated_cb); + + /* Note: For the three signal handlers below, we do *not* need to + * store personas to the cache before removing the store, as + * _remove_store() deletes the cache file. */ + this._account_manager.account_removed.connect ((a) => { - this._prepare_pending = true; - - this._account_manager = AccountManager.dup (); - - /* FIXME: Add all contact features on AM's factory. We should not - * force preparing all features but let app define what it needs, - * but this is for backward compatibility. - * Note that if application already prepared TpContacts before - * preparing this store, this will have no effect on existing - * contacts. */ - var factory = this._account_manager.get_factory (); - factory.add_contact_features ({ - ContactFeature.ALIAS, - ContactFeature.AVATAR_DATA, - ContactFeature.AVATAR_TOKEN, - ContactFeature.CAPABILITIES, - ContactFeature.CLIENT_TYPES, - ContactFeature.PRESENCE, - ContactFeature.CONTACT_INFO, - ContactFeature.CONTACT_GROUPS - }); - - this._account_manager.invalidated.connect ( - this._account_manager_invalidated_cb); - - /* Note: For the three signal handlers below, we do *not* need to - * store personas to the cache before removing the store, as - * _remove_store() deletes the cache file. */ - this._account_manager.account_removed.connect ((a) => + if (this.account == a) { - if (this.account == a) - { - debug ("Account %p (‘%s’) removed.", a, a.display_name); - this._remove_store (); - } - }); - this._account_manager.account_validity_changed.connect ( - (a, valid) => - { - if (!valid && this.account == a) - { - debug ("Account %p (‘%s’) invalid.", a, - a.display_name); - this._remove_store (); - } - }); - this._account_manager.account_disabled.connect ((a) => + debug ("Account %p (‘%s’) removed.", a, a.display_name); + this._remove_store (); + } + }); + this._account_manager.account_validity_changed.connect ( + (a, valid) => { - if (this.account == a) + if (!valid && this.account == a) { - debug ("Account %p (‘%s’) disabled.", a, a.display_name); + debug ("Account %p (‘%s’) invalid.", a, + a.display_name); this._remove_store (); } }); - - Internal.profiling_point ("created account manager in " + - "Tpf.PersonaStore (ID: %s)", this.id); - - this._avatars.clear (); - - this._favourite_ids.clear (); - this._logger = new Logger (this.id); - this._logger.invalidated.connect ( - this._logger_invalidated_cb); - this._logger.favourite_contacts_changed.connect ( - this._favourite_contacts_changed_cb); - Internal.profiling_start ("initialising favourite contacts in " + - "Tpf.PersonaStore (ID: %s)", this.id); - this._initialise_favourite_contacts.begin ((o, r) => + this._account_manager.account_disabled.connect ((a) => + { + if (this.account == a) { - try - { - this._initialise_favourite_contacts.end (r); - Internal.profiling_end ("initialising favourite " + - "contacts in Tpf.PersonaStore (ID: %s)", this.id); - } - catch (GLib.Error e) - { - debug ("Failed to initialise favourite contacts: %s", - e.message); - this._logger = null; - } - }); - - Internal.profiling_point ("created logger in Tpf.PersonaStore " + - "(ID: %s)", this.id); - - this.account.notify["connection"].connect ( - this._notify_connection_cb); - - /* immediately handle accounts which are not currently being - * disconnected */ - if (this.account.connection != null) + debug ("Account %p (‘%s’) disabled.", a, a.display_name); + this._remove_store (); + } + }); + + Internal.profiling_point ("created account manager in " + + "Tpf.PersonaStore (ID: %s)", this.id); + + this._avatars.clear (); + + this._favourite_ids.clear (); + this._logger = new Logger (this.id); + this._logger.invalidated.connect ( + this._logger_invalidated_cb); + this._logger.favourite_contacts_changed.connect ( + this._favourite_contacts_changed_cb); + Internal.profiling_start ("initialising favourite contacts in " + + "Tpf.PersonaStore (ID: %s)", this.id); + this._initialise_favourite_contacts.begin ((o, r) => + { + try { - this._notify_connection_cb (this.account, null); + this._initialise_favourite_contacts.end (r); + Internal.profiling_end ("initialising favourite " + + "contacts in Tpf.PersonaStore (ID: %s)", this.id); } - else + catch (GLib.Error e) { - /* If we're disconnected, advertise personas from the cache - * instead. */ - yield this._load_cache (null); - this._force_quiescent (); + debug ("Failed to initialise favourite contacts: %s", + e.message); + this._logger = null; } + }); + + Internal.profiling_point ("created logger in Tpf.PersonaStore " + + "(ID: %s)", this.id); - Internal.profiling_point ("loaded cache in Tpf.PersonaStore " + - "(ID: %s)", this.id); + this.account.notify["connection"].connect ( + this._notify_connection_cb); - this._is_prepared = true; - this._prepare_pending = false; - this.notify_property ("is-prepared"); + /* immediately handle accounts which are not currently being + * disconnected */ + if (this.account.connection != null) + { + this._notify_connection_cb (this.account, null); } - finally + else { - this._prepare_pending = false; + /* If we're disconnected, advertise personas from the cache + * instead. */ + yield this._load_cache (null); + this._force_quiescent (); } + + Internal.profiling_point ("loaded cache in Tpf.PersonaStore " + + "(ID: %s)", this.id); + + this._is_prepared = true; + this._prepare_pending = false; + this.notify_property ("is-prepared"); + } + finally + { + this._prepare_pending = false; } Internal.profiling_end ("preparing Tpf.PersonaStore (ID: %s)", this.id); -- 2.7.4