1// Copyright (C) 2017 Ford Motor Company
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qremoteobjectpendingcall.h"
6#include "qremoteobjectpendingcall_p.h"
7
8#include "qremoteobjectreplica_p.h"
9
10#include <QtCore/qcoreapplication.h>
11
12#include <private/qobject_p.h>
13
14QT_BEGIN_NAMESPACE
15
16QT_IMPL_METATYPE_EXTERN(QRemoteObjectPendingCall)
17
18QRemoteObjectPendingCallData::QRemoteObjectPendingCallData(int serialId, QRemoteObjectReplicaImplementation *replica)
19 : replica(replica)
20 , serialId(serialId)
21 , error(QRemoteObjectPendingCall::InvalidMessage)
22 , watcherHelper(nullptr)
23{
24}
25
26QRemoteObjectPendingCallData::~QRemoteObjectPendingCallData()
27{
28}
29
30void QRemoteObjectPendingCallWatcherHelper::add(QRemoteObjectPendingCallWatcher *watcher)
31{
32 connect(sender: this, signal: &QRemoteObjectPendingCallWatcherHelper::finished, context: watcher, slot: [watcher]() {
33 emit watcher->finished(self: watcher);
34 }, type: Qt::QueuedConnection);
35}
36
37void QRemoteObjectPendingCallWatcherHelper::emitSignals()
38{
39 emit finished();
40}
41
42/*!
43 \class QRemoteObjectPendingCall
44 \inmodule QtRemoteObjects
45 \brief Encapsulates the result of an asynchronous method call.
46*/
47
48QRemoteObjectPendingCall::QRemoteObjectPendingCall()
49 : d(new QRemoteObjectPendingCallData)
50{
51}
52
53QRemoteObjectPendingCall::~QRemoteObjectPendingCall()
54{
55}
56
57QRemoteObjectPendingCall::QRemoteObjectPendingCall(const QRemoteObjectPendingCall& other)
58 : d(other.d)
59{
60}
61
62QRemoteObjectPendingCall::QRemoteObjectPendingCall(QRemoteObjectPendingCallData *dd)
63 : d(dd)
64{
65}
66
67QRemoteObjectPendingCall &QRemoteObjectPendingCall::operator=(const QRemoteObjectPendingCall &other)
68{
69 d = other.d;
70 return *this;
71}
72
73/*!
74 Returns the return value of the remote call.
75
76 returnValue will only be valid when the remote call has finished and there
77 are no \l {error}s.
78*/
79QVariant QRemoteObjectPendingCall::returnValue() const
80{
81 if (!d)
82 return QVariant();
83
84 QMutexLocker locker(&d->mutex);
85 return d->returnValue;
86}
87
88/*!
89 \enum QRemoteObjectPendingCall::Error
90
91 This enum type specifies the possible error values for a remote call:
92
93 \value NoError
94 No error occurred.
95 \value InvalidMessage
96 The default error state prior to the remote call finishing.
97*/
98
99/*!
100 Returns the error, if any, from the remote call.
101*/
102QRemoteObjectPendingCall::Error QRemoteObjectPendingCall::error() const
103{
104 if (!d)
105 return QRemoteObjectPendingCall::InvalidMessage;
106
107 QMutexLocker locker(&d->mutex);
108 return d->error;
109}
110
111/*!
112 Returns true if the remote call has finished, false otherwise.
113
114 A finished call will include a returnValue or \l error.
115*/
116bool QRemoteObjectPendingCall::isFinished() const
117{
118 if (!d)
119 return true; // considered finished
120
121 QMutexLocker locker(&d->mutex);
122 return d->error != InvalidMessage;
123}
124
125/*!
126 Blocks for up to \a timeout milliseconds, until the remote call has finished.
127
128 Returns \c true on success, \c false otherwise.
129*/
130bool QRemoteObjectPendingCall::waitForFinished(int timeout)
131{
132 if (!d)
133 return false;
134
135 if (d->error != QRemoteObjectPendingCall::InvalidMessage)
136 return true; // already finished
137
138 QMutexLocker locker(&d->mutex);
139 if (!d->replica)
140 return false;
141
142 return d->replica->waitForFinished(*this, timeout);
143}
144
145QRemoteObjectPendingCall QRemoteObjectPendingCall::fromCompletedCall(const QVariant &returnValue)
146{
147 QRemoteObjectPendingCallData *data = new QRemoteObjectPendingCallData;
148 data->returnValue = returnValue;
149 data->error = NoError;
150 return QRemoteObjectPendingCall(data);
151}
152
153class QRemoteObjectPendingCallWatcherPrivate: public QObjectPrivate
154{
155public:
156 Q_DECLARE_PUBLIC(QRemoteObjectPendingCallWatcher)
157};
158
159/*!
160 \class QRemoteObjectPendingCallWatcher
161 \inmodule QtRemoteObjects
162 \brief Provides a QObject-based API for watching a QRemoteObjectPendingCall.
163
164 QRemoteObjectPendingCallWatcher provides a signal indicating when a QRemoteObjectPendingCall
165 has finished, allowing for convenient, non-blocking handling of the call.
166*/
167
168QRemoteObjectPendingCallWatcher::QRemoteObjectPendingCallWatcher(const QRemoteObjectPendingCall &call, QObject *parent)
169 : QObject(*new QRemoteObjectPendingCallWatcherPrivate, parent)
170 , QRemoteObjectPendingCall(call)
171{
172 if (d) {
173 QMutexLocker locker(&d->mutex);
174 if (!d->watcherHelper) {
175 d->watcherHelper.reset(other: new QRemoteObjectPendingCallWatcherHelper);
176 if (d->error != QRemoteObjectPendingCall::InvalidMessage) {
177 // cause a signal emission anyways
178 QMetaObject::invokeMethod(obj: d->watcherHelper.data(), member: "finished", c: Qt::QueuedConnection);
179 }
180 }
181 d->watcherHelper->add(watcher: this);
182 }
183}
184
185QRemoteObjectPendingCallWatcher::~QRemoteObjectPendingCallWatcher()
186{
187}
188
189/*!
190 Returns true if the remote call has finished, false otherwise.
191
192 A finished call will include a returnValue or error.
193*/
194bool QRemoteObjectPendingCallWatcher::isFinished() const
195{
196 if (!d)
197 return true; // considered finished
198
199 QMutexLocker locker(&d->mutex);
200 return d->error != QRemoteObjectPendingCall::InvalidMessage;
201}
202
203/*!
204 Blocks until the remote call has finished.
205*/
206void QRemoteObjectPendingCallWatcher::waitForFinished()
207{
208 if (d) {
209 QRemoteObjectPendingCall::waitForFinished();
210
211 // our signals were queued, so deliver them
212 QCoreApplication::sendPostedEvents(receiver: d->watcherHelper.data(), event_type: QEvent::MetaCall);
213 QCoreApplication::sendPostedEvents(receiver: this, event_type: QEvent::MetaCall);
214 }
215}
216
217/*!
218 \fn QRemoteObjectPendingCallWatcher::finished(QRemoteObjectPendingCallWatcher *self)
219
220 This signal is emitted when the remote call has finished. \a self is the pointer to
221 the watcher object that emitted the signal. A finished call will include a
222 returnValue or error.
223*/
224
225/*!
226 \class QRemoteObjectPendingReply
227 \inmodule QtRemoteObjects
228 \brief A templated version of QRemoteObjectPendingCall.
229*/
230
231/*! \fn template <typename T> T QRemoteObjectPendingReply<T>::returnValue() const
232
233 Returns a strongly typed version of the return value of the remote call.
234*/
235
236QT_END_NAMESPACE
237
238#include "moc_qremoteobjectpendingcall.cpp"
239

source code of qtremoteobjects/src/remoteobjects/qremoteobjectpendingcall.cpp