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

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