Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qdbuspendingcall.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qdbuspendingcall.h"
7
8#include "qdbusconnection_p.h"
9#include "qdbusmetatype_p.h"
10#include "qdbusutil_p.h"
11#include "qcoreapplication.h"
12#include "qcoreevent.h"
13#include <private/qobject_p.h>
14#include <private/qlocking_p.h>
15
16#ifndef QT_NO_DBUS
17
19
20using namespace Qt::StringLiterals;
21
100
102{
103 if (pending) {
104 q_dbus_pending_call_cancel(pending);
105 q_dbus_pending_call_unref(pending);
106 }
107 delete watcherHelper;
108}
109
111{
114 methodIdx = -1;
115 if (!target)
116 return true;; // unsetting
117
118 if (!member || !*member) {
119 // would not be able to deliver a reply
120 qWarning("QDBusPendingCall::setReplyCallback: error: cannot deliver a reply to %s::%s (%s)",
121 target ? target->metaObject()->className() : "(null)",
122 member ? member + 1 : "(null)",
123 target ? qPrintable(target->objectName()) : "no name");
124 return false;
125 }
126
127 QString errorMsg;
129 if (methodIdx == -1) {
132 }
133 if (methodIdx == -1) {
134 // would not be able to deliver a reply
135 qWarning("QDBusPendingCall::setReplyCallback: error: cannot deliver a reply to %s::%s (%s) "
136 "because %s",
137 target->metaObject()->className(), member + 1, qPrintable(target->objectName()),
138 qPrintable(errorMsg));
139 return false;
140 }
141
142 // success
143 // construct the expected signature
144 int count = metaTypes.size() - 1;
145 if (count == 1 && metaTypes.at(1) == QDBusMetaTypeId::message()) {
146 // wildcard slot, can receive anything, so don't set the signature
147 return true;
148 }
149
151 --count;
152
153 setMetaTypes(count, count ? metaTypes.constData() + 1 : nullptr);
154 return true;
155}
156
158{
159 if (count == 0) {
160 expectedReplySignature = ""_L1; // not null
161 return;
162 }
163
164 QByteArray sig;
165 sig.reserve(count + count / 2);
166 for (int i = 0; i < count; ++i) {
167 const char *typeSig = QDBusMetaType::typeToSignature(types[i]);
168 if (Q_UNLIKELY(!typeSig))
169 qFatal("QDBusPendingReply: type %s is not registered with QtDBus", types[i].name());
170 sig += typeSig;
171 }
172
174}
175
177{
178 // MUST BE CALLED WITH A LOCKED MUTEX!
179
181 return; // not yet finished - no message to
182 // validate against
184 return; // we don't have to check the signature of an error reply
185
187 return; // no signature to validate against
188
189 // can't use startsWith here because a null string doesn't start or end with an empty string
191 const auto errorMsg = "Unexpected reply signature: got \"%1\", expected \"%2\""_L1;
195
196 }
197}
198
200{
201 const auto locker = qt_scoped_lock(mutex);
202
204 return; // already finished
205
207}
208
228
237
242 : d(dd)
243{
244 if (dd) {
245 bool r = dd->ref.deref();
246 Q_ASSERT(r);
247 }
248}
249
257{
258 // d deleted by QExplicitlySharedDataPointer
259}
260
261
273{
274 d = other.d;
275 return *this;
276}
277
315{
316 if (!d)
317 return true; // considered finished
318
319 const auto locker = qt_scoped_lock(d->mutex);
321}
322
327
338{
339 if (!d)
340 return false;
341 const auto locker = qt_scoped_lock(d->mutex);
343}
344
355{
356 if (!d)
357 return true; // considered finished and an error
358 const auto locker = qt_scoped_lock(d->mutex);
360}
361
371{
372 if (d) {
373 const auto locker = qt_scoped_lock(d->mutex);
374 return QDBusError(d->replyMessage);
375 }
376
377 // not connected, return an error
380 return err;
381}
382
395{
396 if (!d)
398 const auto locker = qt_scoped_lock(d->mutex);
399 return d->replyMessage;
400}
401
402#if 0
403/*
404 Sets the slot \a member in object \a target to be called when the
405 reply arrives. The slot's parameter list must match the reply
406 message's arguments for it to be called.
407
408 It may, optionally, contain a QDBusMessage final parameter. If it
409 is present, the parameter will contain the reply message object.
410
411 The callback will not be called if the reply is an error message.
412
413 This function returns \c true if it could set the callback, false
414 otherwise. It is not a guarantee that the callback will be
415 called.
416
417 \warning QDBusPendingCall only supports one callback per pending
418 asynchronous call, even if multiple QDBusPendingCall
419 objects are referencing the same pending call.
420*/
421bool QDBusPendingCall::setReplyCallback(QObject *target, const char *member)
422{
423 if (!d)
424 return false;
425
426 return d->setReplyCallback(target, member);
427}
428#endif
429
442
456{
457 QDBusPendingCallPrivate *d = nullptr;
458 if (msg.type() == QDBusMessage::ErrorMessage ||
460 d = new QDBusPendingCallPrivate(QDBusMessage(), nullptr);
461 d->replyMessage = msg;
462 d->ref.storeRelaxed(1);
463 }
464
465 return QDBusPendingCall(d);
466}
467
474 : QObject(parent), QDBusPendingCall(call)
475{
476 if (d) { // QDBusPendingCall::d
477 const auto locker = qt_scoped_lock(d->mutex);
478 if (!d->watcherHelper) {
481 // cause a signal emission anyways
485 }
486 }
487 d->watcherHelper->add(this);
488 }
489}
490
499
511{
512 if (d) {
514
515 // our signals were queued, so deliver them
518 }
519}
521
522#include "moc_qdbuspendingcall_p.cpp"
523
524#endif // QT_NO_DBUS
525
526#include "moc_qdbuspendingcall.cpp"
bool deref() noexcept
void storeRelaxed(T newValue) noexcept
\inmodule QtCore
Definition qbytearray.h:57
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
Definition qbytearray.h:634
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent(...
static int findSlot(QObject *obj, const QByteArray &normalizedName, QList< QMetaType > &params, QString &errorMsg)
\inmodule QtDBus
Definition qdbuserror.h:21
@ InvalidSignature
Definition qdbuserror.h:43
\inmodule QtDBus
static QDBusMessage createError(const QString &name, const QString &msg)
Constructs a new DBus message representing an error, with the given name and msg.
MessageType type() const
Returns the message type.
QString signature() const
Returns the signature of the signal that was received or for the output arguments of a method call.
static const char * typeToSignature(QMetaType type)
QPointer< QObject > receiver
QDBusPendingCallWatcherHelper * watcherHelper
QWaitCondition waitForFinishedCondition
bool setReplyCallback(QObject *target, const char *member)
QList< QMetaType > metaTypes
void setMetaTypes(int count, const QMetaType *types)
void error(const QDBusError &error, const QDBusMessage &msg)
void reply(const QDBusMessage &msg)
void add(QDBusPendingCallWatcher *watcher)
void waitForFinished()
Suspends the execution of the calling thread until the reply is received and processed.
~QDBusPendingCallWatcher()
Destroys this object.
\inmodule QtDBus
static QDBusPendingCall fromError(const QDBusError &error)
QExplicitlySharedDataPointer< QDBusPendingCallPrivate > d
QDBusPendingCall & operator=(QDBusPendingCall &&other) noexcept
QDBusPendingCall(const QDBusPendingCall &other)
Creates a copy of the other pending asynchronous call.
QDBusError error() const
QDBusMessage reply() const
~QDBusPendingCall()
Destroys this copy of the QDBusPendingCall object.
static QDBusPendingCall fromCompletedCall(const QDBusMessage &message)
friend class QDBusPendingCallWatcher
friend class QDBusPendingCallPrivate
\inmodule QtCore
Definition qeventloop.h:16
int exec(ProcessEventsFlags flags=AllEvents)
Enters the main event loop and waits until exit() is called.
@ WaitForMoreEvents
Definition qeventloop.h:29
@ ExcludeUserInputEvents
Definition qeventloop.h:27
void quit()
Tells the event loop to exit normally.
@ MetaCall
Definition qcoreevent.h:97
qsizetype size() const noexcept
Definition qlist.h:397
const_pointer constData() const noexcept
Definition qlist.h:433
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void clear()
Definition qlist.h:434
\inmodule QtCore
Definition qmetatype.h:341
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
QAtomicInt ref
Definition qshareddata.h:21
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4517
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:994
bool wait(QMutex *, QDeadlineTimer=QDeadlineTimer(QDeadlineTimer::Forever))
QMetaType message()
QString disconnectedErrorMessage()
Combined button and popup list for selecting options.
@ QueuedConnection
#define Q_UNLIKELY(x)
DBusConnection const char DBusError * error
static QByteArray normalizedName(QAnyStringView name)
#define qWarning
Definition qlogging.h:166
#define qFatal
Definition qlogging.h:168
GLboolean r
[2]
GLsizei GLenum GLenum * types
GLenum GLenum GLsizei count
GLenum target
GLuint name
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1531
#define Q_EMIT
QFutureWatcher< int > watcher
QSharedPointer< T > other(t)
[5]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
static QByteArray normalizedSignature(const char *method)
Normalizes the signature of the given method.