on xenial help sign in
DashCommunicator: replace QDBusInterface with a non-blocking simplification which does not introspect the service on creation Fixes: #1403508
107822fGerry Boland
plugins/Unity/DashCommunicator/dashconnection.cpp+30
@@ -19,12 +19,42 @@
19#include <QDBusInterface>
19#include <QDBusInterface>
20#include <QDBusPendingCall>
20#include <QDBusPendingCall>
21
21
22+/* The default implementation of AbstractDBusServiceMonitor creates a QDBusInterface when the service
23+ * appears on the bus.
24+ *
25+ * On construction QDBusInterface synchronously introspects the service, which will block the GUI
26+ * thread of this process if the service is busy. QDBusAbstractInterface does not perform this
27+ * introspection, so let's subclass that and avoid the blocking scenario.
28+ *
29+ * However we lose Qt's wrapping of the DBus service with a MetaObject, with the result that we
30+ * cannot easily connect to DBus signals with the usual connect() calls. So this approach only
31+ * suited to push communication with the DBus service.
32+ */
33+class AsyncDBusInterface : public QDBusAbstractInterface
34+{
35+public:
36+ AsyncDBusInterface(const QString &service, const QString &path,
37+ const QString &interface, const QDBusConnection &connection,
38+ QObject *parent = 0)
39+ : QDBusAbstractInterface(service, path, interface.toLatin1().data(), connection, parent)
40+ {}
41+ ~AsyncDBusInterface() = default;
42+};
43+
44+
22DashConnection::DashConnection(const QString &service, const QString &path, const QString &interface, QObject *parent):
45DashConnection::DashConnection(const QString &service, const QString &path, const QString &interface, QObject *parent):
23 AbstractDBusServiceMonitor(service, path, interface, SessionBus, parent)
46 AbstractDBusServiceMonitor(service, path, interface, SessionBus, parent)
24{
47{
25
48
26}
49}
27
50
51+/* Override the default implementation to create a non-blocking DBus interface (see note above). */
52+QDBusAbstractInterface* DashConnection::createInterface(const QString &service, const QString &path,
53+ const QString &interface, const QDBusConnection &connection)
54+{
55+ return new AsyncDBusInterface(service, path, interface, connection);
56+}
57+
28void DashConnection::setCurrentScope(int index, bool animate, bool isSwipe)
58void DashConnection::setCurrentScope(int index, bool animate, bool isSwipe)
29{
59{
30 if (dbusInterface()) {
60 if (dbusInterface()) {
plugins/Unity/DashCommunicator/dashconnection.h+4−1
@@ -20,7 +20,6 @@
20// local
20// local
21#include "abstractdbusservicemonitor.h"
21#include "abstractdbusservicemonitor.h"
22
22
23−
24class DashConnection: public AbstractDBusServiceMonitor
23class DashConnection: public AbstractDBusServiceMonitor
25{
24{
26 Q_OBJECT
25 Q_OBJECT
@@ -29,6 +28,10 @@ public:
29
28
30public Q_SLOTS:
29public Q_SLOTS:
31 void setCurrentScope(int index, bool animate, bool isSwipe);
30 void setCurrentScope(int index, bool animate, bool isSwipe);
31+
32+private:
33+ QDBusAbstractInterface* createInterface(const QString &service, const QString &path,
34+ const QString &interface, const QDBusConnection &connection) override;
32};
35};
33
36
34#endif
37#endif
src/libunity8-private/abstractdbusservicemonitor.cpp+21−8
@@ -32,19 +32,20 @@ AbstractDBusServiceMonitor::AbstractDBusServiceMonitor(const QString &service, c
32 , m_service(service)
32 , m_service(service)
33 , m_path(path)
33 , m_path(path)
34 , m_interface(interface)
34 , m_interface(interface)
35+ , m_bus(bus)
35 , m_watcher(new QDBusServiceWatcher(service,
36 , m_watcher(new QDBusServiceWatcher(service,
36 (bus == SystemBus) ? QDBusConnection::systemBus()
37 (bus == SystemBus) ? QDBusConnection::systemBus()
37 : QDBusConnection::sessionBus()))
38 : QDBusConnection::sessionBus()))
38 , m_dbusInterface(nullptr)
39 , m_dbusInterface(nullptr)
39{
40{
40− connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, this, &AbstractDBusServiceMonitor::createInterface);
41+ connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, this, &AbstractDBusServiceMonitor::onServiceRegistered);
41− connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, &AbstractDBusServiceMonitor::destroyInterface);
42+ connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, &AbstractDBusServiceMonitor::onServiceUnregistered);
42
43
43 // Connect to the service if it's up already
44 // Connect to the service if it's up already
44 QDBusConnectionInterface* sessionBus = QDBusConnection::sessionBus().interface();
45 QDBusConnectionInterface* sessionBus = QDBusConnection::sessionBus().interface();
45 QDBusReply<bool> reply = sessionBus->isServiceRegistered(m_service);
46 QDBusReply<bool> reply = sessionBus->isServiceRegistered(m_service);
46 if (reply.isValid() && reply.value()) {
47 if (reply.isValid() && reply.value()) {
47− createInterface(m_service);
48+ onServiceRegistered(m_service);
48 }
49 }
49}
50}
50
51
@@ -54,19 +55,31 @@ AbstractDBusServiceMonitor::~AbstractDBusServiceMonitor()
54 delete m_dbusInterface;
55 delete m_dbusInterface;
55}
56}
56
57
57−void AbstractDBusServiceMonitor::createInterface(const QString &)
58+void AbstractDBusServiceMonitor::onServiceRegistered(const QString &)
58{
59{
59 if (m_dbusInterface != nullptr) {
60 if (m_dbusInterface != nullptr) {
60 delete m_dbusInterface;
61 delete m_dbusInterface;
61 m_dbusInterface = nullptr;
62 m_dbusInterface = nullptr;
62 }
63 }
63
64
64− m_dbusInterface = new QDBusInterface(m_service, m_path, m_interface,
65+ m_dbusInterface = createInterface(m_service, m_path, m_interface,
66+ (m_bus == SystemBus) ? QDBusConnection::systemBus()
65− QDBusConnection::sessionBus());
67+ : QDBusConnection::sessionBus());
66 Q_EMIT serviceAvailableChanged(true);
68 Q_EMIT serviceAvailableChanged(true);
67}
69}
68
70
71+/*
72+ * Default implementation creates a QDBusInterface. This performs blocking introspection of the
73+ * service at initialization, which may be undesirable if the service is slow/blocked.
74+ */
75+QDBusAbstractInterface*
76+AbstractDBusServiceMonitor::createInterface(const QString &service, const QString &path,
77+ const QString &interface, const QDBusConnection &connection)
78+{
79+ return new QDBusInterface(service, path, interface, connection);
80+}
81+
69−void AbstractDBusServiceMonitor::destroyInterface(const QString &)
82+void AbstractDBusServiceMonitor::onServiceUnregistered(const QString &)
70{
83{
71 if (m_dbusInterface != nullptr) {
84 if (m_dbusInterface != nullptr) {
72 delete m_dbusInterface;
85 delete m_dbusInterface;
@@ -76,7 +89,7 @@ void AbstractDBusServiceMonitor::destroyInterface(const QString &)
76 Q_EMIT serviceAvailableChanged(false);
89 Q_EMIT serviceAvailableChanged(false);
77}
90}
78
91
79−QDBusInterface* AbstractDBusServiceMonitor::dbusInterface() const
92+QDBusAbstractInterface* AbstractDBusServiceMonitor::dbusInterface() const
80{
93{
81 return m_dbusInterface;
94 return m_dbusInterface;
82}
95}
src/libunity8-private/abstractdbusservicemonitor.h+9−5
@@ -24,7 +24,7 @@
24#include <QString>
24#include <QString>
25#include <QDBusConnection>
25#include <QDBusConnection>
26
26
27−class QDBusInterface;
27+class QDBusAbstractInterface;
28class QDBusServiceWatcher;
28class QDBusServiceWatcher;
29
29
30class Q_DECL_EXPORT AbstractDBusServiceMonitor : public QObject
30class Q_DECL_EXPORT AbstractDBusServiceMonitor : public QObject
@@ -44,7 +44,7 @@ public:
44 QObject *parent = 0);
44 QObject *parent = 0);
45 ~AbstractDBusServiceMonitor();
45 ~AbstractDBusServiceMonitor();
46
46
47− QDBusInterface* dbusInterface() const;
47+ QDBusAbstractInterface* dbusInterface() const;
48
48
49 bool serviceAvailable() const;
49 bool serviceAvailable() const;
50
50
@@ -52,15 +52,19 @@ Q_SIGNALS:
52 void serviceAvailableChanged(bool available);
52 void serviceAvailableChanged(bool available);
53
53
54private Q_SLOTS:
54private Q_SLOTS:
55− void createInterface(const QString &service);
55+ void onServiceRegistered(const QString &service);
56− void destroyInterface(const QString &service);
56+ void onServiceUnregistered(const QString &service);
57
57
58protected:
58protected:
59+ virtual QDBusAbstractInterface* createInterface(const QString &service, const QString &path,
60+ const QString &interface, const QDBusConnection &connection);
61+
59 const QString m_service;
62 const QString m_service;
60 const QString m_path;
63 const QString m_path;
61 const QString m_interface;
64 const QString m_interface;
65+ const Bus m_bus;
62 QDBusServiceWatcher* m_watcher;
66 QDBusServiceWatcher* m_watcher;
63− QDBusInterface* m_dbusInterface;
67+ QDBusAbstractInterface* m_dbusInterface;
64};
68};
65
69
66#endif // ABSTRACTDBUSSERVICEMONITOR_H
70#endif // ABSTRACTDBUSSERVICEMONITOR_H