1// Copyright (C) 2016 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// Qt-Security score:significant reason:default
4
5#ifndef QFUTUREINTERFACE_P_H
6#define QFUTUREINTERFACE_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/private/qglobal_p.h>
20#include <QtCore/qelapsedtimer.h>
21#include <QtCore/qcoreevent.h>
22#include <QtCore/qlist.h>
23#include <QtCore/qwaitcondition.h>
24#include <QtCore/qrunnable.h>
25#include <QtCore/qthreadpool.h>
26#include <QtCore/qfutureinterface.h>
27#include <QtCore/qexception.h>
28
29QT_REQUIRE_CONFIG(future);
30
31QT_BEGIN_NAMESPACE
32
33// Although QFutureCallOutEvent and QFutureCallOutInterface are private,
34// for historical reasons they were used externally (in QtJambi, see
35// https://github.com/OmixVisualization/qtjambi), so we export them to
36// not break the pre-existing code.
37class Q_CORE_EXPORT QFutureCallOutEvent : public QEvent
38{
39 Q_DECL_EVENT_COMMON(QFutureCallOutEvent)
40public:
41 enum CallOutType {
42 Started,
43 Finished,
44 Canceled,
45 Suspending,
46 Suspended,
47 Resumed,
48 Progress,
49 ProgressRange,
50 ResultsReady
51 };
52
53 QFutureCallOutEvent()
54 : QEvent(QEvent::FutureCallOut), callOutType(CallOutType(0)), index1(-1), index2(-1)
55 { }
56 explicit QFutureCallOutEvent(CallOutType callOutType, int index1 = -1)
57 : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(-1)
58 { }
59 QFutureCallOutEvent(CallOutType callOutType, int index1, int index2)
60 : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(index2)
61 { }
62
63 QFutureCallOutEvent(CallOutType callOutType, int index1, const QString &text)
64 : QEvent(QEvent::FutureCallOut),
65 callOutType(callOutType),
66 index1(index1),
67 index2(-1),
68 text(text)
69 { }
70
71 CallOutType callOutType;
72 int index1;
73 int index2;
74 QString text;
75};
76
77class Q_CORE_EXPORT QFutureCallOutInterface
78{
79public:
80 virtual ~QFutureCallOutInterface();
81 virtual void postCallOutEvent(const QFutureCallOutEvent &) = 0;
82 virtual void callOutInterfaceDisconnected() = 0;
83};
84
85class QFutureInterfaceBasePrivate
86{
87public:
88 QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState);
89 ~QFutureInterfaceBasePrivate();
90
91 // When the last QFuture<T> reference is removed, we need to make
92 // sure that data stored in the ResultStore is cleaned out.
93 // Since QFutureInterfaceBasePrivate can be shared between QFuture<T>
94 // and QFuture<void> objects, we use a separate ref. counter
95 // to keep track of QFuture<T> objects.
96 class RefCount
97 {
98 public:
99 inline RefCount(int r = 0, int rt = 0)
100 : m_refCount(r), m_refCountT(rt) {}
101 // Default ref counter for QFIBP
102 inline bool ref() { return m_refCount.ref(); }
103 inline bool deref() { return m_refCount.deref(); }
104 inline int load() const { return m_refCount.loadRelaxed(); }
105 // Ref counter for type T
106 inline bool refT() { return m_refCountT.ref(); }
107 inline bool derefT() { return m_refCountT.deref(); }
108 inline int loadT() const { return m_refCountT.loadRelaxed(); }
109
110 private:
111 QAtomicInt m_refCount;
112 QAtomicInt m_refCountT;
113 };
114
115 // T: accessed from executing thread
116 // Q: accessed from the waiting/querying thread
117 mutable QMutex m_mutex;
118 QBasicMutex continuationMutex;
119 QList<QFutureCallOutInterface *> outputConnections;
120 QElapsedTimer progressTime;
121 QWaitCondition waitCondition;
122 QWaitCondition pausedWaitCondition;
123
124 union Data {
125 QtPrivate::ResultStoreBase m_results;
126 QtPrivate::ExceptionStore m_exceptionStore;
127
128#ifndef QT_NO_EXCEPTIONS
129 void setException(const std::exception_ptr &e)
130 {
131 m_results.~ResultStoreBase();
132 new (&m_exceptionStore) QtPrivate::ExceptionStore();
133 m_exceptionStore.setException(e);
134 }
135#endif
136
137 ~Data() { }
138 };
139 Data data = { .m_results: QtPrivate::ResultStoreBase() };
140
141 QRunnable *runnable = nullptr;
142 QThreadPool *m_pool = nullptr;
143 // Wrapper for continuation
144 std::function<void(const QFutureInterfaceBase &)> continuation;
145 QFutureInterfaceBasePrivate *continuationData = nullptr;
146 // will reset back to nullptr when the parent future is done
147 // (finished, canceled, failed etc)
148 QFutureInterfaceBasePrivate *nonConcludedParent = nullptr;
149
150 RefCount refCount = 1;
151 QAtomicInt state; // reads and writes can happen unprotected, both must be atomic
152
153 int m_progressValue = 0; // TQ
154 struct ProgressData
155 {
156 int minimum = 0; // TQ
157 int maximum = 0; // TQ
158 QString text;
159 };
160 QScopedPointer<ProgressData> m_progress;
161
162 int m_expectedResultCount = 0;
163 bool launchAsync = false;
164 bool isValid = false;
165 bool hasException = false;
166
167 enum ContinuationState : quint8 { Default, Canceled, Cleaned };
168 std::atomic<ContinuationState> continuationState { Default };
169 bool continuationExecuted = false;
170
171 QFutureInterfaceBase::ContinuationType continuationType = QFutureInterfaceBase::ContinuationType::Unknown;
172
173 inline QThreadPool *pool() const
174 { return m_pool ? m_pool : QThreadPool::globalInstance(); }
175
176 // Internal functions that does not change the mutex state.
177 // The mutex must be locked when calling these.
178 int internal_resultCount() const;
179 bool internal_isResultReadyAt(int index) const;
180 bool internal_waitForNextResult();
181 bool internal_updateProgressValue(int progress);
182 bool internal_updateProgress(int progress, const QString &progressText = QString());
183 void internal_setThrottled(bool enable);
184 void sendCallOut(const QFutureCallOutEvent &callOut);
185 void sendCallOuts(const QFutureCallOutEvent &callOut1, const QFutureCallOutEvent &callOut2);
186 void connectOutputInterface(QFutureCallOutInterface *iface);
187 void disconnectOutputInterface(QFutureCallOutInterface *iface);
188
189 void setState(QFutureInterfaceBase::State state);
190
191 enum class CancelOption : quint32
192 {
193 None = 0x00,
194 CancelContinuations = 0x01,
195 };
196 Q_DECLARE_FLAGS(CancelOptions, CancelOption)
197 void cancelImpl(QFutureInterfaceBase::CancelMode mode, CancelOptions options);
198};
199
200QT_END_NAMESPACE
201
202#endif
203

source code of qtbase/src/corelib/thread/qfutureinterface_p.h