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
qtconcurrentthreadengine.h
Go to the documentation of this file.
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
4#ifndef QTCONCURRENT_THREADENGINE_H
5#define QTCONCURRENT_THREADENGINE_H
6
7#include <QtConcurrent/qtconcurrent_global.h>
8
9#if !defined(QT_NO_CONCURRENT) ||defined(Q_QDOC)
10
11#include <QtCore/qthreadpool.h>
12#include <QtCore/qfuture.h>
13#include <QtCore/qdebug.h>
14#include <QtCore/qexception.h>
15#include <QtCore/qwaitcondition.h>
16#include <QtCore/qatomic.h>
17#include <QtCore/qsemaphore.h>
18
20
21
22namespace QtConcurrent {
23
24// The ThreadEngineBarrier counts worker threads, and allows one
25// thread to wait for all others to finish. Tested for its use in
26// QtConcurrent, requires more testing for use as a general class.
28{
29private:
30 // The thread count is maintained as an integer in the count atomic
31 // variable. The count can be either positive or negative - a negative
32 // count signals that a thread is waiting on the barrier.
33
35 QSemaphore semaphore;
36public:
38 void acquire();
39 int release();
40 void wait();
41 int currentCount();
42 bool releaseUnlessLast();
43};
44
46
47// The ThreadEngine controls the threads used in the computation.
48// Can be run in three modes: single threaded, multi-threaded blocking
49// and multi-threaded asynchronous.
50// The code for the single threaded mode is
51class Q_CONCURRENT_EXPORT ThreadEngineBase: public QRunnable
52{
53public:
54 // Public API:
56 virtual ~ThreadEngineBase();
57 void startSingleThreaded();
58 void startThread();
59 bool isCanceled();
60 void waitForResume();
61 bool isProgressReportingEnabled();
62 void setProgressValue(int progress);
63 void setProgressRange(int minimum, int maximum);
64 void acquireBarrierSemaphore();
65 void reportIfSuspensionDone() const;
66
67protected: // The user overrides these:
68 virtual void start() {}
69 virtual void finish() {}
71 virtual bool shouldStartThread() { return !shouldThrottleThread(); }
72 virtual bool shouldThrottleThread()
73 {
74 return futureInterface ? (futureInterface->isSuspending() || futureInterface->isSuspended())
75 : false;
76 }
77
78private:
79 bool startThreadInternal();
80 void startThreads();
81 void threadExit();
82 bool threadThrottleExit();
83 void run() override;
84 virtual void asynchronousFinish() = 0;
85#ifndef QT_NO_EXCEPTIONS
86 void handleException(const QException &exception);
87#endif
88protected:
94};
95
96
97template <typename T>
99{
100public:
101 typedef T ResultType;
102
104
105 virtual T *result() { return nullptr; }
106
107 QFutureInterface<T> *futureInterfaceTyped()
108 {
109 return static_cast<QFutureInterface<T> *>(futureInterface);
110 }
111
112 // Runs the user algorithm using a single thread.
118
119 // Runs the user algorithm using multiple threads.
120 // Does not block, returns a future.
122 {
123 futureInterface = new QFutureInterface<T>();
124
125 // reportStart() must be called before starting threads, otherwise the
126 // user algorithm might finish while reportStart() is running, which
127 // is very bad.
129 QFuture<T> future = QFuture<T>(futureInterfaceTyped());
130 start();
131
133 threadPool->start(this);
134 return future;
135 }
136
137 void asynchronousFinish() override
138 {
139 finish();
140 futureInterfaceTyped()->reportFinished(result());
141 delete futureInterfaceTyped();
142 delete this;
143 }
144
145
146 void reportResult(const T *_result, int index = -1)
147 {
148 if (futureInterface)
149 futureInterfaceTyped()->reportResult(_result, index);
150 }
151
152 void reportResults(const QList<T> &_result, int index = -1, int count = -1)
153 {
154 if (futureInterface)
155 futureInterfaceTyped()->reportResults(_result, index, count);
156 }
157};
158
159// The ThreadEngineStarter class ecapsulates the return type
160// from the thread engine.
161// Depending on how the it is used, it will run
162// the engine in either blocking mode or asynchronous mode.
163template <typename T>
165{
166public:
167 ThreadEngineStarterBase(ThreadEngine<T> *_threadEngine)
168 : threadEngine(_threadEngine) { }
169
172
174 {
175 return threadEngine->startAsynchronously();
176 }
177
178 operator QFuture<T>()
179 {
180 return startAsynchronously();
181 }
182
183protected:
184 ThreadEngine<T> *threadEngine;
185};
186
187
188// We need to factor out the code that dereferences the T pointer,
189// with a specialization where T is void. (code that dereferences a void *
190// won't compile)
191template <typename T>
193{
194 typedef ThreadEngineStarterBase<T> Base;
195 typedef ThreadEngine<T> TypedThreadEngine;
196public:
197 ThreadEngineStarter(TypedThreadEngine *eng)
198 : Base(eng) { }
199};
200
201// Full template specialization where T is void.
202template <>
204{
205public:
206 ThreadEngineStarter(ThreadEngine<void> *_threadEngine)
207 : ThreadEngineStarterBase<void>(_threadEngine) {}
208};
209
211template <typename ThreadEngine>
212inline ThreadEngineStarter<typename ThreadEngine::ResultType> startThreadEngine(ThreadEngine *threadEngine)
213{
214 return ThreadEngineStarter<typename ThreadEngine::ResultType>(threadEngine);
215}
216
217} // namespace QtConcurrent
218
219
221
222#endif // QT_NO_CONCURRENT
223
224#endif
\inmodule QtCore
Definition qatomic.h:112
\inmodule QtCore
Definition qexception.h:22
\inmodule QtCore
Definition qmutex.h:281
\inmodule QtCore
Definition qrunnable.h:18
\inmodule QtCore
Definition qsemaphore.h:18
\inmodule QtCore
Definition qthreadpool.h:22
void start(QRunnable *runnable, int priority=0)
Reserves a thread and uses it to run runnable, unless this thread will make the current thread count ...
virtual ThreadFunctionResult threadFunction()
virtual void asynchronousFinish()=0
QtPrivate::ExceptionStore exceptionStore
ThreadEngineStarterBase(ThreadEngine< T > *_threadEngine)
ThreadEngineStarterBase(const ThreadEngineStarterBase &other)
ThreadEngineStarter(ThreadEngine< void > *_threadEngine)
QFutureInterface< T > * futureInterfaceTyped()
void reportResult(const T *_result, int index=-1)
void reportResults(const QList< T > &_result, int index=-1, int count=-1)
Combined button and popup list for selecting options.
\inmodule QtConcurrent
QTCONCURRENT_RUN_NODISCARD auto run(QThreadPool *pool, Function &&f, Args &&...args)
ThreadEngineStarter< typename ThreadEngine::ResultType > startThreadEngine(ThreadEngine *threadEngine)
[qtconcurrentthreadengine-1]
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
GLuint index
[2]
GLenum GLenum GLsizei count
QFuture< void > future
[5]
QSharedPointer< T > other(t)
[5]