[Telepathy-commits] [telepathy-qt4/master] Make Channel keep track of an "owning" connection

Olli Salli olli.salli at collabora.co.uk
Mon Nov 3 06:44:48 PST 2008


---
 TelepathyQt4/cli-channel.cpp    |   61 ++++++++++++++++++++++++++------------
 TelepathyQt4/cli-channel.h      |   35 ++++++++++++----------
 TelepathyQt4/cli-connection.cpp |    3 +-
 TelepathyQt4/cli-connection.h   |    9 ++++-
 4 files changed, 69 insertions(+), 39 deletions(-)

diff --git a/TelepathyQt4/cli-channel.cpp b/TelepathyQt4/cli-channel.cpp
index 3d4d0b2..1fbadf9 100644
--- a/TelepathyQt4/cli-channel.cpp
+++ b/TelepathyQt4/cli-channel.cpp
@@ -41,6 +41,9 @@ struct Channel::Private
     // Public object
     Channel& parent;
 
+    // Owning connection
+    Connection* connection;
+
     // Optional interface proxies
     ChannelInterfaceGroupInterface* group;
     DBus::PropertiesInterface* properties;
@@ -77,7 +80,7 @@ struct Channel::Private
     // Group remove info
     GroupMemberChangeInfo groupSelfRemoveInfo;
 
-    Private(Channel& parent)
+    Private(Channel& parent, Connection* connection)
         : parent(parent)
     {
         debug() << "Creating new Channel";
@@ -94,11 +97,25 @@ struct Channel::Private
         groupIsSelfHandleTracked = false;
         groupSelfHandle = 0;
 
-        debug() << "Connecting to Channel::Closed()";
+        debug() << " Connecting to Channel::Closed()";
         parent.connect(&parent,
                        SIGNAL(Closed()),
                        SLOT(onClosed()));
 
+        debug() << " Connection to owning connection's lifetime signals";
+        parent.connect(connection,
+                       SIGNAL(readinessChanged(uint)),
+                       SLOT(onConnectionReadinessChanged(uint)));
+
+        parent.connect(connection,
+                       SIGNAL(destroyed()),
+                       SLOT(onConnectionDestroyed()));
+
+        if (connection->readiness() == Connection::ReadinessDead) {
+            warning() << "Connection given as the owner for a Channel was already dead! Channel will be stillborn.";
+            readiness = ReadinessDead;
+        }
+
         introspectQueue.enqueue(&Private::introspectMain);
     }
 
@@ -236,11 +253,12 @@ struct Channel::Private
 
     void continueIntrospection()
     {
-        if (introspectQueue.isEmpty()) {
-            if (readiness < ReadinessFull)
+        if (readiness < ReadinessFull) {
+            if (introspectQueue.isEmpty()) {
                 changeReadiness(ReadinessFull);
-        } else {
-            (this->*introspectQueue.dequeue())();
+            } else {
+                (this->*introspectQueue.dequeue())();
+            }
         }
     }
 
@@ -373,22 +391,14 @@ struct Channel::Private
     }
 };
 
-Channel::Channel(const QString& serviceName,
+Channel::Channel(Connection* connection,
                  const QString& objectPath,
                  QObject* parent)
-    : ChannelInterface(serviceName, objectPath, parent),
-      mPriv(new Private(*this))
-{
-    mPriv->continueIntrospection();
-}
-
-Channel::Channel(const QDBusConnection& connection,
-                 const QString& serviceName,
-                 const QString& objectPath,
-                 QObject* parent)
-    : ChannelInterface(connection, serviceName, objectPath, parent),
-      mPriv(new Private(*this))
+    : ChannelInterface(connection->service(), objectPath, parent),
+      mPriv(new Private(*this, connection))
 {
+    // Introspection continued here so mPriv will be initialized (unlike if we
+    // continued it from the Private constructor)
     mPriv->continueIntrospection();
 }
 
@@ -611,6 +621,19 @@ void Channel::onClosed()
         mPriv->changeReadiness(ReadinessDead);
 }
 
+void Channel::onConnectionReadinessChanged(uint readiness)
+{
+    if (readiness == Connection::ReadinessDead && mPriv->readiness != ReadinessDead) {
+        debug() << "Owning connection died leaving an orphan Channel, changing to ReadinessDead";
+        mPriv->changeReadiness(ReadinessDead);
+    }
+}
+
+void Channel::onConnectionDestroyed()
+{
+    return onConnectionReadinessChanged(Connection::ReadinessDead);
+}
+
 void Channel::gotGroupProperties(QDBusPendingCallWatcher* watcher)
 {
     QDBusPendingReply<QVariantMap> reply = *watcher;
diff --git a/TelepathyQt4/cli-channel.h b/TelepathyQt4/cli-channel.h
index fec766b..858c6ad 100644
--- a/TelepathyQt4/cli-channel.h
+++ b/TelepathyQt4/cli-channel.h
@@ -47,6 +47,13 @@
 
 #include <QDBusPendingCallWatcher>
 
+namespace Telepathy {
+namespace Client {
+class Channel;
+}
+}
+
+#include <TelepathyQt4/Client/Connection>
 #include <TelepathyQt4/Client/DBus>
 #include <TelepathyQt4/Client/OptionalInterfaceFactory>
 
@@ -80,6 +87,10 @@ namespace Client
  * Additionally, the state of the Group interface on the remote object (if
  * present) will be cached in the introspection process, and also tracked for
  * any changes.
+ *
+ * Each Channel is owned by a Connection. If the Connection becomes dead (as
+ * signaled by Connection::readinessChanged) or is deleted, the Channel object
+ * will transition to ReadinessDead too.
  */
 class Channel : public ChannelInterface, private OptionalInterfaceFactory
 {
@@ -123,30 +134,19 @@ public:
     };
 
     /**
-     * Creates a Channel associated with the given object on the session bus.
+     * Creates a Channel associated with the given object on the same service as
+     * the given connection.
      *
-     * \param serviceName Name of the service the object is on.
+     * \param connection  Connection owning this Channel, and specifying the
+     *                    service.
      * \param objectPath  Path to the object on the service.
      * \param parent      Passed to the parent class constructor.
      */
-    Channel(const QString& serviceName,
+    Channel(Connection* connection,
             const QString& objectPath,
             QObject* parent = 0);
 
     /**
-     * Creates a Channel associated with the given object on the given bus.
-     *
-     * \param connection  The bus via which the object can be reached.
-     * \param serviceName Name of the service the object is on.
-     * \param objectPath  Path to the object on the service.
-     * \param parent      Passed to the parent class constructor.
-     */
-    Channel(const QDBusConnection& connection,
-            const QString &serviceName,
-            const QString &objectPath,
-            QObject* parent = 0);
-
-    /**
      * Class destructor.
      */
     ~Channel();
@@ -745,6 +745,9 @@ private Q_SLOTS:
     void gotInterfaces(QDBusPendingCallWatcher* watcher);
     void onClosed();
 
+    void onConnectionReadinessChanged(uint readiness);
+    void onConnectionDestroyed();
+
     void gotGroupProperties(QDBusPendingCallWatcher* watcher);
     void gotGroupFlags(QDBusPendingCallWatcher* watcher);
     void gotAllMembers(QDBusPendingCallWatcher* watcher);
diff --git a/TelepathyQt4/cli-connection.cpp b/TelepathyQt4/cli-connection.cpp
index c7c60ff..cfc92f0 100644
--- a/TelepathyQt4/cli-connection.cpp
+++ b/TelepathyQt4/cli-connection.cpp
@@ -533,8 +533,7 @@ Channel* PendingChannel::channel(QObject* parent) const
     }
 
     Channel* channel =
-        new Channel(mPriv->connection->connection(),
-                    mPriv->connection->service(),
+        new Channel(mPriv->connection,
                     mPriv->objectPath.path(),
                     parent);
     return channel;
diff --git a/TelepathyQt4/cli-connection.h b/TelepathyQt4/cli-connection.h
index ae2fc38..8a51d69 100644
--- a/TelepathyQt4/cli-connection.h
+++ b/TelepathyQt4/cli-connection.h
@@ -46,6 +46,13 @@
 #include <QDBusPendingCallWatcher>
 #include <QStringList>
 
+namespace Telepathy {
+namespace Client {
+class Connection;
+class PendingChannel;
+}
+}
+
 #include <TelepathyQt4/Constants>
 #include <TelepathyQt4/Client/Channel>
 #include <TelepathyQt4/Client/DBus>
@@ -56,8 +63,6 @@ namespace Telepathy
 namespace Client
 {
 
-class PendingChannel;
-
 /**
  * \class Connection
  * \ingroup clientconn
-- 
1.5.6.5




More information about the Telepathy-commits mailing list