summaryrefslogtreecommitdiffstats
path: root/src/concurrent/qtconcurrentrun.cpp
blob: 8347440b66e208b199080a2f8c11ec4d81668fe7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtConcurrent module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
    \page qtconcurrentrun.html
    \title Concurrent Run
    \ingroup thread

    The QtConcurrent::run() function runs a function in a separate thread.
    The return value of the function is made available through the QFuture API.

    QtConcurrent::run() is an overloaded method. You can think of these overloads as slightly
    different \e modes.
    In \l {Concurrent Run (basic mode)} {basic mode}, the function passed to QtConcurrent::run()
    is able to report merely a single computation result to its caller.
    In \l {Concurrent Run With Promise} {run with promise mode}, the function passed to
    QtConcurrent::run() can make use of the additional
    QPromise API, which enables multiple result reporting, progress reporting,
    suspending the computation when requested by the caller, or stopping
    the computation on the caller's demand.

    This function is a part of the Qt Concurrent framework.

    \section1 Concurrent Run (basic mode)

    The function passed to QtConcurrent::run() may report the result
    through its return value.

    \section2 Running a Function in a Separate Thread

    To run a function in another thread, use QtConcurrent::run():

    \snippet code/src_concurrent_qtconcurrentrun.cpp 0

    This will run \c aFunction in a separate thread obtained from the default
    QThreadPool. You can use the QFuture and QFutureWatcher classes to monitor
    the status of the function.

    To use a dedicated thread pool, you can pass the QThreadPool as
    the first argument:

    \snippet code/src_concurrent_qtconcurrentrun.cpp explicit-pool-0

    \section2 Passing Arguments to the Function

    Passing arguments to the function is done by adding them to the
    QtConcurrent::run() call immediately after the function name. For example:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 1

    A copy of each argument is made at the point where QtConcurrent::run() is
    called, and these values are passed to the thread when it begins executing
    the function. Changes made to the arguments after calling
    QtConcurrent::run() are \e not visible to the thread.

    Note that QtConcurrent::run does not support calling overloaded functions
    directly. For example, the code below won't compile:

//! [run-with-overload-calls]
    \snippet code/src_concurrent_qtconcurrentrun.cpp 15

    The easiest workaround is to call the overloaded function through lambda:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 16

    Or you can tell the compiler which overload to choose by using a
    \c static_cast:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 17

    Or qOverload:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 18
//! [run-with-overload-calls]

    \section2 Returning Values from the Function

    Any return value from the function is available via QFuture:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 2

    As documented above, passing arguments is done like this:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 3

    Note that the QFuture::result() function blocks and waits for the result
    to become available. Use QFutureWatcher to get notification when the
    function has finished execution and the result is available.

    \section2 Additional API Features

    \section3 Using Member Functions

    QtConcurrent::run() also accepts pointers to member functions. The first
    argument must be either a const reference or a pointer to an instance of
    the class. Passing by const reference is useful when calling const member
    functions; passing by pointer is useful for calling non-const member
    functions that modify the instance.

    For example, calling QByteArray::split() (a const member function) in a
    separate thread is done like this:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 4

    Calling a non-const member function is done like this:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 5

    \section3 Using Lambda Functions

    Calling a lambda function is done like this:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 6

    Calling a function modifies an object passed by reference is done like this:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 7

    Using callable object is done like this:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 8

    \section1 Concurrent Run With Promise

    The \e {Run With Promise} mode enables more control for the running
    task compared to \e basic mode of QtConcurrent::run().
    It allows progress reporting of the running task,
    reporting multiple results, suspending the execution
    if it was requested, or canceling the task on caller's
    demand.

    \section2 The mandatory QPromise argument

    The function passed to QtConcurrent::run() in \e {Run With Promise} mode is expected
    to have an additional argument of \c {QPromise<T> &} type, where
    T is the type of the computation result (it should match the type T
    of QFuture<T> returned by the QtConcurrent::runWithPromise()), like e.g.:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 9

    The \c promise argument is instantiated inside the
    QtConcurrent::run() function, and its reference
    is passed to the invoked \c aFunction, so the user
    doesn't need to instantiate it by himself, nor pass it explicitly
    when calling QtConcurrent::runWithPromise().

    The additional argument of QPromise type always needs to appear
    as a first argument on function's arguments list, like:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 10

    \section2 Reporting results

    In contrast to \e basic mode of QtConcurrent::run(), the function passed to
    QtConcurrent::run() in \e {Run With Promise} mode is expected to always return void type.
    Result reporting is done through the additional argument of QPromise type.
    It also enables multiple result reporting, like:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 11

    \section2 Suspending and canceling the execution

    The QPromise API also enables suspending and canceling the computation, if requested:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 12

    The call to \c future.suspend() requests the running task to
    hold its execution. After calling this method, the running task
    will suspend after the next call to \c promise.suspendIfRequested()
    in its iteration loop. In this case the running task will
    block on a call to \c promise.suspendIfRequested(). The blocked
    call will unblock after the \c future.resume() is called.
    Note, that internally suspendIfRequested() uses wait condition
    in order to unblock, so the running thread goes into an idle state
    instead of wasting its resources when blocked in order to periodically
    check if the resume request came from the caller's thread.

    The call to \c future.cancel() from the last line causes that the next
    call to \c promise.isCanceled() will return \c true and
    \c aFunction will return immediately without any further result reporting.

    \section2 Progress reporting

    It's also possible to report the progress of a task
    independently of result reporting, like:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 13

    The caller installs the \c QFutureWatcher for the \c QFuture
    returned by QtConcurrent::run() in order to
    connect to its \c progressValueChanged() signal and update
    e.g. the graphical user interface accordingly.

    \section2 Invoking functions with overloaded operator()()

    By default, QtConcurrent::run() doesn't support functors with
    overloaded operator()() in \e {Run With Promise} mode. In case of overloaded
    functors the user needs to explicitly specify the result type
    as a template parameter passed to QtConcurrent::run(), like:

    \snippet code/src_concurrent_qtconcurrentrun.cpp 14
*/

/*!
  \typedef Function
  \internal

  This typedef is a dummy required to make the \c Function
  type name known so that clang doesn't reject functions
  that use it.
*/

/*!
    \fn QFuture<T> QtConcurrent::run(Function function, ...);

    Equivalent to
    \code
    QtConcurrent::run(QThreadPool::globalInstance(), function, ...);
    \endcode

    Runs \a function in a separate thread. The thread is taken from the global
    QThreadPool. Note that \a function may not run immediately; \a function
    will only be run once a thread becomes available.

//! [run-description]
    In \l {Concurrent Run (basic mode)} {basic mode} T is the same type as the return value
    of \a function. Non-void return values can be accessed via the QFuture::result() function.

    In \l {Concurrent Run (basic mode)} {basic mode} the QFuture returned can only be used to
    query for the running/finished status and the return value of the function. In particular,
    canceling or pausing can be issued only if the computations behind the future
    has not been started.

    In \l {Concurrent Run With Promise} {run with promise mode}, the \a function is expected
    to return void and must take an additional argument of \c {QPromise<T> &} type,
    placed as a first argument in function's argument list. T is the result type
    and it is the same for the returned \c QFuture<T>.

    In \l {Concurrent Run With Promise} {run with promise mode}, similar to \e basic mode, the
    QFuture returned can be used to query for the running/finished status and the value reported
    by the function. In addition, it may be used for suspending or canceling the
    running task, fetching multiple results from the called \a function or
    monitoring progress reported by the \a function.

    \sa {Concurrent Run (basic mode)}, {Concurrent Run With Promise}
//! [run-description]
*/

/*!
    \since 5.4
    \fn QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...);

    Runs \a function in a separate thread. The thread is taken from the
    QThreadPool \a pool. Note that \a function may not run immediately; \a function
    will only be run once a thread becomes available.

    \include qtconcurrentrun.cpp run-description
*/