[folks] telepathy: Yield subsequent Logger.prepare() calls if one is pending



commit ce55fa2bf2f5f8cf95532da585d835bafeeb3347
Author: Philip Withnall <philip tecnocode co uk>
Date:   Fri Dec 28 13:47:50 2012 +0000

    telepathy: Yield subsequent Logger.prepare() calls if one is pending
    
    If one PersonaStore began to prepare its Logger, then yielded on a D-Bus
    call, another PersonaStore could begin to prepare its Logger and also
    try to create a static D-Bus proxy (which is only supposed to be created
    once). This is because the original async call hasnât returned and set
    Logger._logger by that point.
    
    Fix this by keeping a queue of pending prepare() calls which is signalled
    by the initial prepare() call once it finishes yielding.
    
    Closes: https://bugzilla.gnome.org/show_bug.cgi?id=677633

 NEWS                                   |    1 +
 backends/telepathy/lib/tpf-logger.vala |   47 +++++++++++++++++++++++++++----
 2 files changed, 42 insertions(+), 6 deletions(-)
---
diff --git a/NEWS b/NEWS
index 108ea74..15f0f76 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,7 @@ Bugs fixed:
 â Bug 688923 â remove URLs (blog, free/busy, video, home page)
 â Bug 689146 â disabling EDS address books does not remove personas
 â Bug 689859 â core folks does not depend on telepathy
+â Bug 677633 â Cannot delete favourite
 
 API changes:
 â Add Backend.enable_persona_store and disable_persona_store.
diff --git a/backends/telepathy/lib/tpf-logger.vala b/backends/telepathy/lib/tpf-logger.vala
index 5489f9b..2dccb67 100644
--- a/backends/telepathy/lib/tpf-logger.vala
+++ b/backends/telepathy/lib/tpf-logger.vala
@@ -43,10 +43,19 @@ private interface LoggerIface : Object
       ObjectPath account_path, string[] added, string[] removed);
 }
 
+/* See: https://mail.gnome.org/archives/vala-list/2011-June/msg00008.html */
+[Compact]
+private class DelegateWrapper
+{
+  public SourceFunc cb;
+}
+
 internal class Logger : GLib.Object
 {
   private static DBusConnection _dbus_conn;
   private static LoggerIface _logger;
+  private static DelegateWrapper[] _prepare_waiters = null;
+
   private uint _logger_watch_id;
 
   public signal void invalidated ();
@@ -77,22 +86,48 @@ internal class Logger : GLib.Object
 
   public async void prepare () throws GLib.Error
     {
-      if (Logger._logger == null)
+      if (Logger._logger == null && Logger._prepare_waiters == null)
         {
+          /* If this is the first call to prepare(), start some async calls. We
+           * then yield to the main thread. Any subsequent calls to prepare()
+           * will have their continuations added to the _prepare_waiters list,
+           * and will be signalled once the first call returns.
+           * See: https://bugzilla.gnome.org/show_bug.cgi?id=677633 */
+          Logger._prepare_waiters = new DelegateWrapper[0];
+
           /* Create a logger proxy for favourites support */
           var dbus_conn = yield Bus.get (BusType.SESSION);
           Logger._logger = yield dbus_conn.get_proxy<LoggerIface> (
               "org.freedesktop.Telepathy.Logger",
               "/org/freedesktop/Telepathy/Logger");
 
-          /* Failure? */
-          if (Logger._logger == null)
+          if (Logger._logger != null)
             {
-              this.invalidated ();
-              return;
+              Logger._dbus_conn = dbus_conn;
             }
 
-          Logger._dbus_conn = dbus_conn;
+          /* Wake up any waiters. */
+          foreach (unowned DelegateWrapper wrapper in Logger._prepare_waiters)
+            {
+              wrapper.cb ();
+            }
+
+          Logger._prepare_waiters = null;
+        }
+      else if (Logger._logger == null && Logger._prepare_waiters != null)
+        {
+          /* Yield until the first ongoing prepare() call finishes. */
+          var wrapper = new DelegateWrapper ();
+          wrapper.cb = prepare.callback;
+          Logger._prepare_waiters += (owned) wrapper;
+          yield;
+        }
+
+      /* Failure? */
+      if (Logger._logger == null)
+        {
+          this.invalidated ();
+          return;
         }
 
       this._logger_watch_id = Bus.watch_name_on_connection (Logger._dbus_conn,



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