summaryrefslogtreecommitdiffstats
path: root/src/dbus/qdbusabstractinterface.h
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2016-09-01 20:37:12 +0200
committerMarc Mutz <marc.mutz@kdab.com>2019-06-21 09:18:13 +0200
commit08103d3a527d32c782ba9e3f6701e6676ac81a57 (patch)
treedd8baf691bd62e2c19dd31c6bc887228046fe12a /src/dbus/qdbusabstractinterface.h
parent6bcfe0453597c81573bbfb838b5ec087d74f07de (diff)
QDBusAbstractInterface: make call() and asyncCall() variadic templates
... and use a variant of the QString::multiArg() trick to pass the variable number of arguments into an out-of-line function. The idea of this patch is to make the lowly asyncCall() and call() functions the principal interface for DBus calls again. Currently, it is more efficient to build up a QList<QVariant> and pass that to the *WithArgumentList() methods. With more efficient, I mean that the equivalent calls with QList expand to less client code, probably because of the need to construct eight QVariant instances, destroy them again, and then take the hit for a function call with so many arguments, which can all but be efficient. Consequently, when porting the NM bearer plugin to use call() instead of callWithArgumentList(), text size increased by ~3KiB on my machine. So, looking for a way to avoid the overhead of so many default arguments, while at the same time allowing to pass even more arguments than the predefined eight, I considered the QString::arg() method, but discarded it because it does not scale to arbitrarily (ie. SEP-limited) many arguments. Variadic templates scale to SEP-limited many arguments, but they are templates and deduce the exact type, so constraining the template to only QVariants would have broken all users of the API which pass non-QVariants and expect an implicit con- version to resolve the call. So I decided to make a virtue of necessity, accept all argument types and convert them to QVariant when constructing the QString::multiArg()-inspired QVariant array. To bring this patch to its consequential end would require to pass the arguments as arrays instead of QLists, but to get a feeling of how much impact this new API has, I backed the new implementation by converting the array to a QList and calling the *WithArgumentList() methods. The result is, if I may say so, satisfying. Said bearer plugin drops from +3KiB (baseline: callWithArgumentList()) to -5KiB (2.0% and 3.2%, resp.); the (unmodified) connman bearer plugin, which already used call(), dropped by almost 6KiB (2.5%). While GCC can deal with the zero-sized array in a nullary call to the variadic templates, MSVC cannot, so an extra overload provides an alternative for zero arguments. [ChangeLog][QtDBus][QDBusAbstractInterface] The call() and asyncCall() methods now accept more than eight QVariant arguments. Change-Id: Ic85faca40949f9bb8c08756be3bfe945c9cdd952 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/dbus/qdbusabstractinterface.h')
-rw-r--r--src/dbus/qdbusabstractinterface.h94
1 files changed, 70 insertions, 24 deletions
diff --git a/src/dbus/qdbusabstractinterface.h b/src/dbus/qdbusabstractinterface.h
index d6b0870787..4f4c7430a5 100644
--- a/src/dbus/qdbusabstractinterface.h
+++ b/src/dbus/qdbusabstractinterface.h
@@ -49,6 +49,7 @@
#include <QtDBus/qdbusmessage.h>
#include <QtDBus/qdbusextratypes.h>
#include <QtDBus/qdbusconnection.h>
+#include <QtDBus/qdbuspendingcall.h>
#ifdef interface
#undef interface
@@ -98,26 +99,52 @@ public:
void setTimeout(int timeout);
int timeout() const;
+ QDBusMessage call(const QString &method)
+ {
+ return doCall(QDBus::AutoDetect, method, nullptr, 0);
+ }
+
+ template <typename...Args>
+ QDBusMessage call(const QString &method, Args &&...args)
+ {
+ const QVariant variants[] = { QVariant(std::forward<Args>(args))... };
+ return doCall(QDBus::AutoDetect, method, variants, sizeof...(args));
+ }
+
+ QDBusMessage call(QDBus::CallMode mode, const QString &method)
+ {
+ return doCall(mode, method, nullptr, 0);
+ }
+
+ template <typename...Args>
+ QDBusMessage call(QDBus::CallMode mode, const QString &method, Args &&...args)
+ {
+ const QVariant variants[] = { QVariant(std::forward<Args>(args))... };
+ return doCall(mode, method, variants, sizeof...(args));
+ }
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QDBusMessage call(const QString &method,
- const QVariant &arg1 = QVariant(),
- const QVariant &arg2 = QVariant(),
- const QVariant &arg3 = QVariant(),
- const QVariant &arg4 = QVariant(),
- const QVariant &arg5 = QVariant(),
- const QVariant &arg6 = QVariant(),
- const QVariant &arg7 = QVariant(),
- const QVariant &arg8 = QVariant());
+ const QVariant &arg1,
+ const QVariant &arg2,
+ const QVariant &arg3,
+ const QVariant &arg4,
+ const QVariant &arg5,
+ const QVariant &arg6,
+ const QVariant &arg7,
+ const QVariant &arg8);
QDBusMessage call(QDBus::CallMode mode,
const QString &method,
- const QVariant &arg1 = QVariant(),
- const QVariant &arg2 = QVariant(),
- const QVariant &arg3 = QVariant(),
- const QVariant &arg4 = QVariant(),
- const QVariant &arg5 = QVariant(),
- const QVariant &arg6 = QVariant(),
- const QVariant &arg7 = QVariant(),
- const QVariant &arg8 = QVariant());
+ const QVariant &arg1,
+ const QVariant &arg2,
+ const QVariant &arg3,
+ const QVariant &arg4,
+ const QVariant &arg5,
+ const QVariant &arg6,
+ const QVariant &arg7,
+ const QVariant &arg8);
+#endif // Qt 5
QDBusMessage callWithArgumentList(QDBus::CallMode mode,
const QString &method,
@@ -130,15 +157,30 @@ public:
const QList<QVariant> &args,
QObject *receiver, const char *member);
+ QDBusPendingCall asyncCall(const QString &method)
+ {
+ return doAsyncCall(method, nullptr, 0);
+ }
+
+ template <typename...Args>
+ QDBusPendingCall asyncCall(const QString &method, Args&&...args)
+ {
+ const QVariant variants[] = { QVariant(std::forward<Args>(args))... };
+ return doAsyncCall(method, variants, sizeof...(args));
+ }
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QDBusPendingCall asyncCall(const QString &method,
- const QVariant &arg1 = QVariant(),
- const QVariant &arg2 = QVariant(),
- const QVariant &arg3 = QVariant(),
- const QVariant &arg4 = QVariant(),
- const QVariant &arg5 = QVariant(),
- const QVariant &arg6 = QVariant(),
- const QVariant &arg7 = QVariant(),
- const QVariant &arg8 = QVariant());
+ const QVariant &arg1,
+ const QVariant &arg2,
+ const QVariant &arg3,
+ const QVariant &arg4,
+ const QVariant &arg5,
+ const QVariant &arg6,
+ const QVariant &arg7,
+ const QVariant &arg8);
+#endif // Qt 5
+
QDBusPendingCall asyncCallWithArgumentList(const QString &method,
const QList<QVariant> &args);
@@ -156,6 +198,10 @@ protected:
const QList<QVariant> &args = QList<QVariant>()) const;
private:
+ QDBusMessage doCall(QDBus::CallMode mode, const QString &method, const QVariant *args, size_t numArgs);
+ QDBusPendingCall doAsyncCall(const QString &method, const QVariant *args, size_t numArgs);
+
+private:
Q_DECLARE_PRIVATE(QDBusAbstractInterface)
Q_PRIVATE_SLOT(d_func(), void _q_serviceOwnerChanged(QString,QString,QString))
};