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
qfutureinterface.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QFUTUREINTERFACE_H
5#define QFUTUREINTERFACE_H
6
7#include <QtCore/qmutex.h>
8#include <QtCore/qresultstore.h>
9#ifndef QT_NO_EXCEPTIONS
10#include <exception>
11#endif
12
13#include <utility>
14
16
20
21
22template <typename T> class QFuture;
23class QThreadPool;
28
29namespace QtPrivate {
30template<typename Function, typename ResultType, typename ParentResultType>
31class Continuation;
32
33class ExceptionStore;
34
35template<class Function, class ResultType>
36class CanceledHandler;
37
38#ifndef QT_NO_EXCEPTIONS
39template<class Function, class ResultType>
40class FailureHandler;
41#endif
42
43void Q_CORE_EXPORT watchContinuationImpl(const QObject *context,
46}
47
48class Q_CORE_EXPORT QFutureInterfaceBase
49{
50public:
51 enum State {
52 NoState = 0x00,
53 Running = 0x01,
54 Started = 0x02,
55 Finished = 0x04,
56 Canceled = 0x08,
57 Suspending = 0x10,
58 Suspended = 0x20,
59 Throttled = 0x40,
60 // Pending means that the future depends on another one, which is not finished yet
61 Pending = 0x80,
62 };
63
64 QFutureInterfaceBase(State initialState = NoState);
67 : d(std::exchange(other.d, nullptr)) {}
69 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QFutureInterfaceBase)
70 virtual ~QFutureInterfaceBase();
71
72 // reporting functions available to the engine author:
73 void reportStarted();
74 void reportFinished();
75 void reportCanceled();
76#ifndef QT_NO_EXCEPTIONS
77 void reportException(const QException &e);
78#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
79 void reportException(std::exception_ptr e);
80#else
81 void reportException(const std::exception_ptr &e);
82#endif
83#endif
84 void reportResultsReady(int beginIndex, int endIndex);
85
86 void setRunnable(QRunnable *runnable);
87 void setThreadPool(QThreadPool *pool);
88 QThreadPool *threadPool() const;
89 void setFilterMode(bool enable);
90 void setProgressRange(int minimum, int maximum);
91 int progressMinimum() const;
92 int progressMaximum() const;
93 bool isProgressUpdateNeeded() const;
94 void setProgressValue(int progressValue);
95 int progressValue() const;
96 void setProgressValueAndText(int progressValue, const QString &progressText);
97 QString progressText() const;
98
99 void setExpectedResultCount(int resultCount);
100 int expectedResultCount();
101 int resultCount() const;
102
103 bool queryState(State state) const;
104 bool isRunning() const;
105 bool isStarted() const;
106 bool isCanceled() const;
107 bool isFinished() const;
108#if QT_DEPRECATED_SINCE(6, 0)
109 QT_DEPRECATED_VERSION_X_6_0("Use isSuspending() or isSuspended() instead.")
110 bool isPaused() const;
111
112 QT_DEPRECATED_VERSION_X_6_0("Use setSuspended() instead.")
113 void setPaused(bool paused) { setSuspended(paused); }
114
115 QT_DEPRECATED_VERSION_X_6_0("Use toggleSuspended() instead.")
116 void togglePaused() { toggleSuspended(); }
117#endif
118 bool isSuspending() const;
119 bool isSuspended() const;
120 bool isThrottled() const;
121 bool isResultReadyAt(int index) const;
122 bool isValid() const;
123 int loadState() const;
124
125 void cancel();
126 void cancelAndFinish() { cancel(CancelMode::CancelAndFinish); }
127
128 void setSuspended(bool suspend);
129 void toggleSuspended();
130 void reportSuspended() const;
131 void setThrottled(bool enable);
132
133 void waitForFinished();
134 bool waitForNextResult();
135 void waitForResult(int resultIndex);
136 void waitForResume();
137 void suspendIfRequested();
138
139 QMutex &mutex() const;
140 bool hasException() const;
141 QtPrivate::ExceptionStore &exceptionStore();
142 QtPrivate::ResultStoreBase &resultStoreBase();
143 const QtPrivate::ResultStoreBase &resultStoreBase() const;
144
145 inline bool operator==(const QFutureInterfaceBase &other) const { return d == other.d; }
146 inline bool operator!=(const QFutureInterfaceBase &other) const { return d != other.d; }
147
148 // ### Qt 7: inline
149 void swap(QFutureInterfaceBase &other) noexcept;
150
151 template<typename T>
152 static QFutureInterfaceBase get(const QFuture<T> &future); // implemented in qfuture.h
153
154 bool isChainCanceled() const;
155
156protected:
157 // ### Qt 7: remove const from refT/derefT
158 bool refT() const noexcept;
159 bool derefT() const noexcept;
160 void reset();
161 void rethrowPossibleException();
162public:
163
164#ifndef QFUTURE_TEST
165private:
166#endif
168
169private:
170 friend class QFutureWatcherBase;
172
173 template<typename Function, typename ResultType, typename ParentResultType>
175
176 template<class Function, class ResultType>
178
179#ifndef QT_NO_EXCEPTIONS
180 template<class Function, class ResultType>
182#endif
183
184 friend Q_CORE_EXPORT void QtPrivate::watchContinuationImpl(
186
187 template<class T>
188 friend class QPromise;
189
190protected:
191 void setContinuation(std::function<void(const QFutureInterfaceBase &)> func);
192 void setContinuation(std::function<void(const QFutureInterfaceBase &)> func,
193 QFutureInterfaceBasePrivate *continuationFutureData);
194 void cleanContinuation();
195 void runContinuation() const;
196
197 void setLaunchAsync(bool value);
198 bool launchAsync() const;
199
200 bool isRunningOrPending() const;
201
202 enum class CancelMode { CancelOnly, CancelAndFinish };
203 void cancel(CancelMode mode);
204};
205
206inline void swap(QFutureInterfaceBase &lhs, QFutureInterfaceBase &rhs) noexcept
207{
208 lhs.swap(rhs);
209}
210
211template <typename T>
213{
214public:
216 : QFutureInterfaceBase(initialState)
217 {
218 refT();
219 }
226 QFutureInterface(QFutureInterfaceBase &&dd) noexcept : QFutureInterfaceBase(std::move(dd)) { refT(); }
228 {
230 swap(copy);
231 return *this;
232 }
234 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QFutureInterface)
235
237 {
238 if (!derefT() && !hasException())
239 resultStoreBase().template clear<T>();
240 }
241
244
245 inline QFuture<T> future(); // implemented in qfuture.h
246
247 template <typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true>
248 inline bool reportAndEmplaceResult(int index, Args&&...args);
249 inline bool reportResult(const T *result, int index = -1);
250 inline bool reportAndMoveResult(T &&result, int index = -1);
251 inline bool reportResult(T &&result, int index = -1);
252 inline bool reportResult(const T &result, int index = -1);
253 inline bool reportResults(const QList<T> &results, int beginIndex = -1, int count = -1);
254 inline bool reportFinished(const T *result);
260
261 inline const T &resultReference(int index) const;
262 inline const T *resultPointer(int index) const;
263 inline QList<T> results();
264
266#if 0
267 // TODO: Enable and make it return a QList, when QList is fixed to support move-only types
268 std::vector<T> takeResults();
269#endif
270
271#ifndef QT_NO_EXCEPTIONS
272 void reportException(const std::exception_ptr &e)
273 {
274 if (hasException())
275 return;
276
277 resultStoreBase().template clear<T>();
279 }
281 {
282 if (hasException())
283 return;
284
285 resultStoreBase().template clear<T>();
287 }
288#endif
289};
290
291template <typename T>
293{
294 QMutexLocker<QMutex> locker{&mutex()};
295 if (this->queryState(Canceled) || this->queryState(Finished))
296 return false;
297
298 Q_ASSERT(!hasException());
299 QtPrivate::ResultStoreBase &store = resultStoreBase();
300
301 const int resultCountBefore = store.count();
302 const int insertIndex = store.addResult<T>(index, result);
303 if (insertIndex == -1)
304 return false;
305 if (store.filterMode()) {
306 this->reportResultsReady(resultCountBefore, store.count());
307 } else {
308 this->reportResultsReady(insertIndex, insertIndex + 1);
309 }
310 return true;
311}
312
313template<typename T>
314template<typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool>>
316{
317 QMutexLocker<QMutex> locker{&mutex()};
318 if (queryState(Canceled) || queryState(Finished))
319 return false;
320
321 Q_ASSERT(!hasException());
322 QtPrivate::ResultStoreBase &store = resultStoreBase();
323
324 const int oldResultCount = store.count();
325 const int insertIndex = store.emplaceResult<T>(index, std::forward<Args>(args)...);
326 // Let's make sure it's not in pending results.
327 if (insertIndex != -1 && (!store.filterMode() || oldResultCount < store.count()))
328 reportResultsReady(insertIndex, store.count());
329 return insertIndex != -1;
330}
331
332template<typename T>
334{
335 return reportAndEmplaceResult(index, std::move(result));
336}
337
338template<typename T>
340{
341 return reportAndMoveResult(std::move(result), index);
342}
343
344template <typename T>
346{
347 return reportResult(&result, index);
348}
349
350template<typename T>
351inline bool QFutureInterface<T>::reportResults(const QList<T> &_results, int beginIndex, int count)
352{
353 QMutexLocker<QMutex> locker{&mutex()};
354 if (this->queryState(Canceled) || this->queryState(Finished))
355 return false;
356
357 Q_ASSERT(!hasException());
358 auto &store = resultStoreBase();
359
360 const int resultCountBefore = store.count();
361 const int insertIndex = store.addResults(beginIndex, &_results, count);
362 if (insertIndex == -1)
363 return false;
364 if (store.filterMode()) {
365 this->reportResultsReady(resultCountBefore, store.count());
366 } else {
367 this->reportResultsReady(insertIndex, insertIndex + _results.size());
368 }
369 return true;
370}
371
372template <typename T>
374{
375 bool resultReported = false;
376 if (result)
377 resultReported = reportResult(result);
378 reportFinished();
379 return resultReported;
380}
381
382template <typename T>
384{
385 Q_ASSERT(!hasException());
386
387 QMutexLocker<QMutex> locker{&mutex()};
388 return resultStoreBase().resultAt(index).template value<T>();
389}
390
391template <typename T>
393{
394 Q_ASSERT(!hasException());
395
396 QMutexLocker<QMutex> locker{&mutex()};
397 return resultStoreBase().resultAt(index).template pointer<T>();
398}
399
400template <typename T>
402{
403 if (this->isCanceled()) {
404 rethrowPossibleException();
405 return QList<T>();
406 }
407
409
410 QList<T> res;
411 QMutexLocker<QMutex> locker{&mutex()};
412
413 QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
414 while (it != resultStoreBase().end()) {
415 res.append(it.value<T>());
416 ++it;
417 }
418
419 return res;
420}
421
422template<typename T>
424{
425 Q_ASSERT(isValid());
426
427 // Note: we wait for all, this is intentional,
428 // not to mess with other unready results.
429 waitForResult(-1);
430
431 Q_ASSERT(!hasException());
432
433 const QMutexLocker<QMutex> locker{&mutex()};
434 QtPrivate::ResultIteratorBase position = resultStoreBase().resultAt(0);
435 T ret(std::move_if_noexcept(position.value<T>()));
436 reset();
437 resultStoreBase().template clear<T>();
438
439 return ret;
440}
441
442#if 0
443template<typename T>
445{
446 Q_ASSERT(isValid());
447
448 waitForResult(-1);
449
450 Q_ASSERT(!hasException());
451
452 std::vector<T> res;
453 res.reserve(resultCount());
454
455 const QMutexLocker<QMutex> locker{&mutex()};
456
457 QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
458 for (auto endIt = resultStoreBase().end(); it != endIt; ++it)
459 res.push_back(std::move_if_noexcept(it.value<T>()));
460
461 reset();
462 resultStoreBase().template clear<T>();
463
464 return res;
465}
466#endif
467
468template <>
469class QFutureInterface<void> : public QFutureInterfaceBase
470{
471public:
472 explicit QFutureInterface(State initialState = NoState)
473 : QFutureInterfaceBase(initialState)
474 { }
475
477
478 static QFutureInterface<void> canceledResult()
479 { return QFutureInterface(State(Started | Finished | Canceled)); }
480
481
482 inline QFuture<void> future(); // implemented in qfuture.h
483
484 bool reportResult(const void *, int) { return false; }
485 bool reportResults(const QList<void> &, int) { return false; }
486 bool reportFinished(const void *)
487 {
488 reportFinished();
489 return false;
490 }
496};
497
498template<typename T>
499inline void swap(QFutureInterface<T> &a, QFutureInterface<T> &b) noexcept
500{
501 a.swap(b);
502}
503
505
506#endif // QFUTUREINTERFACE_H
\inmodule QtCore
Definition qexception.h:22
QtPrivate::ResultStoreBase & resultStoreBase()
void waitForResult(int resultIndex)
bool operator==(const QFutureInterfaceBase &other) const
QFutureInterfaceBase(State initialState=NoState)
bool operator!=(const QFutureInterfaceBase &other) const
bool derefT() const noexcept
void swap(QFutureInterfaceBase &other) noexcept
bool refT() const noexcept
void reportException(const QException &e)
QFutureInterfaceBase(QFutureInterfaceBase &&other) noexcept
QFutureInterface(const QFutureInterfaceBase &dd)
bool reportFinished(const void *)
bool reportResults(const QList< void > &, int)
bool reportResult(const void *, int)
QFutureInterface(State initialState=NoState)
static QFutureInterface< void > canceledResult()
QFutureInterface(QFutureInterface &&other)=default
bool reportAndEmplaceResult(int index, Args &&...args)
QFutureInterface(const QFutureInterfaceBase &dd)
bool reportResult(T &&result, int index=-1)
QFutureInterface & operator=(const QFutureInterface &other)
bool reportResults(const QList< T > &results, int beginIndex=-1, int count=-1)
QFuture< T > future()
Definition qfuture.h:324
const T * resultPointer(int index) const
QFutureInterface(State initialState=NoState)
bool reportResult(const T &result, int index=-1)
static QFutureInterface canceledResult()
void reportException(const std::exception_ptr &e)
QFutureInterface(const QFutureInterface &other)
bool reportFinished(const T *result)
void reportException(const QException &e)
bool reportResult(const T *result, int index=-1)
bool reportAndMoveResult(T &&result, int index=-1)
QFutureInterface(QFutureInterfaceBase &&dd) noexcept
const T & resultReference(int index) const
\inmodule QtCore
Definition qmutex.h:281
\inmodule QtCore
Definition qobject.h:103
\inmodule QtCore
Definition qrunnable.h:18
iterator begin()
Definition qset.h:136
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
Definition qthreadpool.h:22
int emplaceResult(int index, Args &&...args)
int addResult(int index, const void *result)
QSet< QString >::iterator it
else opt state
[0]
Combined button and popup list for selecting options.
\macro QT_NO_KEYWORDS >
void Q_CORE_EXPORT watchContinuationImpl(const QObject *context, QtPrivate::QSlotObjectBase *slotObj, QFutureInterfaceBase &fi)
static void * context
static jboolean copy(JNIEnv *, jobject)
QT_FORWARD_DECLARE_CLASS(QCocoaMenuItem)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
static QDBusError::ErrorType get(const char *name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
void swap(QFutureInterfaceBase &lhs, QFutureInterfaceBase &rhs) noexcept
return ret
GLboolean GLboolean GLboolean b
GLenum mode
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei count
GLboolean enable
GLboolean reset
GLenum func
Definition qopenglext.h:663
GLuint res
GLuint64EXT * result
[6]
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static bool isRunning()
Definition main.cpp:452
#define QT_REQUIRE_CONFIG(feature)
#define QT_DEPRECATED_VERSION_X_6_0(text)
bool reportResult(bool success, const void *lhs, const void *rhs, const char *(*lhsFormatter)(const void *), const char *(*rhsFormatter)(const void *), const char *lhsExpr, const char *rhsExpr, ComparisonOperation op, const char *file, int line)
QFuture< void > future
[5]
future cancel()
future suspend()
future waitForFinished()
QMutex mutex
[2]
QSharedPointer< T > other(t)
[5]
this swap(other)
QJSValueList args