Qt 6.x
The Qt SDK
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;
27
28namespace QtPrivate {
29template<typename Function, typename ResultType, typename ParentResultType>
30class Continuation;
31
32class ExceptionStore;
33
34template<class Function, class ResultType>
35class CanceledHandler;
36
37#ifndef QT_NO_EXCEPTIONS
38template<class Function, class ResultType>
39class FailureHandler;
40#endif
41
42class QBasicFutureWatcher;
43}
44
45class Q_CORE_EXPORT QFutureInterfaceBase
46{
47public:
48 enum State {
49 NoState = 0x00,
50 Running = 0x01,
51 Started = 0x02,
52 Finished = 0x04,
53 Canceled = 0x08,
54 Suspending = 0x10,
55 Suspended = 0x20,
56 Throttled = 0x40,
57 // Pending means that the future depends on another one, which is not finished yet
58 Pending = 0x80,
59 };
60
61 QFutureInterfaceBase(State initialState = NoState);
64 : d(std::exchange(other.d, nullptr)) {}
66 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QFutureInterfaceBase)
67 virtual ~QFutureInterfaceBase();
68
69 // reporting functions available to the engine author:
70 void reportStarted();
71 void reportFinished();
72 void reportCanceled();
73#ifndef QT_NO_EXCEPTIONS
74 void reportException(const QException &e);
75#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
76 void reportException(std::exception_ptr e);
77#else
78 void reportException(const std::exception_ptr &e);
79#endif
80#endif
81 void reportResultsReady(int beginIndex, int endIndex);
82
83 void setRunnable(QRunnable *runnable);
84 void setThreadPool(QThreadPool *pool);
85 QThreadPool *threadPool() const;
86 void setFilterMode(bool enable);
87 void setProgressRange(int minimum, int maximum);
88 int progressMinimum() const;
89 int progressMaximum() const;
90 bool isProgressUpdateNeeded() const;
91 void setProgressValue(int progressValue);
92 int progressValue() const;
93 void setProgressValueAndText(int progressValue, const QString &progressText);
94 QString progressText() const;
95
96 void setExpectedResultCount(int resultCount);
97 int expectedResultCount();
98 int resultCount() const;
99
100 bool queryState(State state) const;
101 bool isRunning() const;
102 bool isStarted() const;
103 bool isCanceled() const;
104 bool isFinished() const;
105#if QT_DEPRECATED_SINCE(6, 0)
106 QT_DEPRECATED_VERSION_X_6_0("Use isSuspending() or isSuspended() instead.")
107 bool isPaused() const;
108
109 QT_DEPRECATED_VERSION_X_6_0("Use setSuspended() instead.")
110 void setPaused(bool paused) { setSuspended(paused); }
111
112 QT_DEPRECATED_VERSION_X_6_0("Use toggleSuspended() instead.")
113 void togglePaused() { toggleSuspended(); }
114#endif
115 bool isSuspending() const;
116 bool isSuspended() const;
117 bool isThrottled() const;
118 bool isResultReadyAt(int index) const;
119 bool isValid() const;
120 int loadState() const;
121
122 void cancel();
123 void cancelAndFinish() { cancel(CancelMode::CancelAndFinish); }
124
125 void setSuspended(bool suspend);
126 void toggleSuspended();
127 void reportSuspended() const;
128 void setThrottled(bool enable);
129
130 void waitForFinished();
131 bool waitForNextResult();
132 void waitForResult(int resultIndex);
133 void waitForResume();
134 void suspendIfRequested();
135
136 QMutex &mutex() const;
137 bool hasException() const;
138 QtPrivate::ExceptionStore &exceptionStore();
139 QtPrivate::ResultStoreBase &resultStoreBase();
140 const QtPrivate::ResultStoreBase &resultStoreBase() const;
141
142 inline bool operator==(const QFutureInterfaceBase &other) const { return d == other.d; }
143 inline bool operator!=(const QFutureInterfaceBase &other) const { return d != other.d; }
144
145 // ### Qt 7: inline
146 void swap(QFutureInterfaceBase &other) noexcept;
147
148 template<typename T>
149 static QFutureInterfaceBase get(const QFuture<T> &future); // implemented in qfuture.h
150
151 bool isChainCanceled() const;
152
153protected:
154 // ### Qt 7: remove const from refT/derefT
155 bool refT() const noexcept;
156 bool derefT() const noexcept;
157 void reset();
158 void rethrowPossibleException();
159public:
160
161#ifndef QFUTURE_TEST
162private:
163#endif
165
166private:
167 friend class QFutureWatcherBase;
169
170 template<typename Function, typename ResultType, typename ParentResultType>
172
173 template<class Function, class ResultType>
175
176#ifndef QT_NO_EXCEPTIONS
177 template<class Function, class ResultType>
179#endif
180
182
183 template<class T>
184 friend class QPromise;
185
186protected:
187 void setContinuation(std::function<void(const QFutureInterfaceBase &)> func);
188 void setContinuation(std::function<void(const QFutureInterfaceBase &)> func,
189 QFutureInterfaceBasePrivate *continuationFutureData);
190 void cleanContinuation();
191 void runContinuation() const;
192
193 void setLaunchAsync(bool value);
194 bool launchAsync() const;
195
196 bool isRunningOrPending() const;
197
198 enum class CancelMode { CancelOnly, CancelAndFinish };
199 void cancel(CancelMode mode);
200};
201
202inline void swap(QFutureInterfaceBase &lhs, QFutureInterfaceBase &rhs) noexcept
203{
204 lhs.swap(rhs);
205}
206
207template <typename T>
209{
210public:
212 : QFutureInterfaceBase(initialState)
213 {
214 refT();
215 }
218 {
219 refT();
220 }
222 QFutureInterface(QFutureInterfaceBase &&dd) noexcept : QFutureInterfaceBase(std::move(dd)) { refT(); }
224 {
226 swap(copy);
227 return *this;
228 }
230 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QFutureInterface)
231
233 {
234 if (!derefT() && !hasException())
235 resultStoreBase().template clear<T>();
236 }
237
240
241 inline QFuture<T> future(); // implemented in qfuture.h
242
243 template <typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool> = true>
244 inline bool reportAndEmplaceResult(int index, Args&&...args);
245 inline bool reportResult(const T *result, int index = -1);
246 inline bool reportAndMoveResult(T &&result, int index = -1);
247 inline bool reportResult(T &&result, int index = -1);
248 inline bool reportResult(const T &result, int index = -1);
249 inline bool reportResults(const QList<T> &results, int beginIndex = -1, int count = -1);
250 inline bool reportFinished(const T *result);
252 {
255 }
256
257 inline const T &resultReference(int index) const;
258 inline const T *resultPointer(int index) const;
260
262#if 0
263 // TODO: Enable and make it return a QList, when QList is fixed to support move-only types
264 std::vector<T> takeResults();
265#endif
266
267#ifndef QT_NO_EXCEPTIONS
268 void reportException(const std::exception_ptr &e)
269 {
270 if (hasException())
271 return;
272
273 resultStoreBase().template clear<T>();
275 }
277 {
278 if (hasException())
279 return;
280
281 resultStoreBase().template clear<T>();
283 }
284#endif
285};
286
287template <typename T>
289{
290 QMutexLocker<QMutex> locker{&mutex()};
291 if (this->queryState(Canceled) || this->queryState(Finished))
292 return false;
293
294 Q_ASSERT(!hasException());
295 QtPrivate::ResultStoreBase &store = resultStoreBase();
296
297 const int resultCountBefore = store.count();
298 const int insertIndex = store.addResult<T>(index, result);
299 if (insertIndex == -1)
300 return false;
301 if (store.filterMode()) {
302 this->reportResultsReady(resultCountBefore, store.count());
303 } else {
304 this->reportResultsReady(insertIndex, insertIndex + 1);
305 }
306 return true;
307}
308
309template<typename T>
310template<typename...Args, std::enable_if_t<std::is_constructible_v<T, Args...>, bool>>
312{
313 QMutexLocker<QMutex> locker{&mutex()};
314 if (queryState(Canceled) || queryState(Finished))
315 return false;
316
317 Q_ASSERT(!hasException());
318 QtPrivate::ResultStoreBase &store = resultStoreBase();
319
320 const int oldResultCount = store.count();
321 const int insertIndex = store.emplaceResult<T>(index, std::forward<Args>(args)...);
322 // Let's make sure it's not in pending results.
323 if (insertIndex != -1 && (!store.filterMode() || oldResultCount < store.count()))
324 reportResultsReady(insertIndex, store.count());
325 return insertIndex != -1;
326}
327
328template<typename T>
330{
331 return reportAndEmplaceResult(index, std::move(result));
332}
333
334template<typename T>
336{
337 return reportAndMoveResult(std::move(result), index);
338}
339
340template <typename T>
342{
343 return reportResult(&result, index);
344}
345
346template<typename T>
347inline bool QFutureInterface<T>::reportResults(const QList<T> &_results, int beginIndex, int count)
348{
349 QMutexLocker<QMutex> locker{&mutex()};
350 if (this->queryState(Canceled) || this->queryState(Finished))
351 return false;
352
353 Q_ASSERT(!hasException());
354 auto &store = resultStoreBase();
355
356 const int resultCountBefore = store.count();
357 const int insertIndex = store.addResults(beginIndex, &_results, count);
358 if (insertIndex == -1)
359 return false;
360 if (store.filterMode()) {
361 this->reportResultsReady(resultCountBefore, store.count());
362 } else {
363 this->reportResultsReady(insertIndex, insertIndex + _results.size());
364 }
365 return true;
366}
367
368template <typename T>
370{
371 bool resultReported = false;
372 if (result)
373 resultReported = reportResult(result);
374 reportFinished();
375 return resultReported;
376}
377
378template <typename T>
380{
381 Q_ASSERT(!hasException());
382
383 QMutexLocker<QMutex> locker{&mutex()};
384 return resultStoreBase().resultAt(index).template value<T>();
385}
386
387template <typename T>
389{
390 Q_ASSERT(!hasException());
391
392 QMutexLocker<QMutex> locker{&mutex()};
393 return resultStoreBase().resultAt(index).template pointer<T>();
394}
395
396template <typename T>
398{
399 if (this->isCanceled()) {
400 rethrowPossibleException();
401 return QList<T>();
402 }
403
405
407 QMutexLocker<QMutex> locker{&mutex()};
408
409 QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
410 while (it != resultStoreBase().end()) {
411 res.append(it.value<T>());
412 ++it;
413 }
414
415 return res;
416}
417
418template<typename T>
420{
421 Q_ASSERT(isValid());
422
423 // Note: we wait for all, this is intentional,
424 // not to mess with other unready results.
425 waitForResult(-1);
426
427 Q_ASSERT(!hasException());
428
429 const QMutexLocker<QMutex> locker{&mutex()};
430 QtPrivate::ResultIteratorBase position = resultStoreBase().resultAt(0);
431 T ret(std::move_if_noexcept(position.value<T>()));
432 reset();
433 resultStoreBase().template clear<T>();
434
435 return ret;
436}
437
438#if 0
439template<typename T>
441{
442 Q_ASSERT(isValid());
443
444 waitForResult(-1);
445
446 Q_ASSERT(!hasException());
447
448 std::vector<T> res;
449 res.reserve(resultCount());
450
451 const QMutexLocker<QMutex> locker{&mutex()};
452
453 QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
454 for (auto endIt = resultStoreBase().end(); it != endIt; ++it)
455 res.push_back(std::move_if_noexcept(it.value<T>()));
456
457 reset();
458 resultStoreBase().template clear<T>();
459
460 return res;
461}
462#endif
463
464template <>
466{
467public:
468 explicit QFutureInterface<void>(State initialState = NoState)
469 : QFutureInterfaceBase(initialState)
470 { }
471
473
475 { return QFutureInterface(State(Started | Finished | Canceled)); }
476
477
478 inline QFuture<void> future(); // implemented in qfuture.h
479
480 bool reportResult(const void *, int) { return false; }
481 bool reportResults(const QList<void> &, int) { return false; }
482 bool reportFinished(const void *)
483 {
484 reportFinished();
485 return false;
486 }
488 {
491 }
492};
493
494template<typename T>
496{
497 a.swap(b);
498}
499
501
502#endif // QFUTUREINTERFACE_H
\inmodule QtCore
Definition qexception.h:22
QtPrivate::ResultStoreBase & resultStoreBase()
void waitForResult(int resultIndex)
bool operator==(const QFutureInterfaceBase &other) const
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)
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:320
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)
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
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
\inmodule QtCore
Definition qmutex.h:317
\inmodule QtCore
Definition qmutex.h:285
\inmodule QtCore
Definition qrunnable.h:18
iterator begin()
Definition qset.h:136
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
\inmodule QtCore
Definition qthreadpool.h:20
int emplaceResult(int index, Args &&...args)
int addResult(int index, const void *result)
double e
QSet< QString >::iterator it
else opt state
[0]
Combined button and popup list for selecting options.
\macro QT_NAMESPACE
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]
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
GLsizei const void * pointer
Definition qopenglext.h:384
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:358
#define QT_REQUIRE_CONFIG(feature)
#define QT_DEPRECATED_VERSION_X_6_0(text)
QFuture< void > future
[5]
future cancel()
future suspend()
future waitForFinished()
QMutex mutex
[2]
QSharedPointer< T > other(t)
[5]
this swap(other)
QJSValueList args