1/****************************************************************************
2**
3** Copyright (C) 2020 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the documentation of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:FDL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Free Documentation License Usage
18** Alternatively, this file may be used under the terms of the GNU Free
19** Documentation License version 1.3 as published by the Free Software
20** Foundation and appearing in the file included in the packaging of
21** this file. Please review the following information to ensure
22** the GNU Free Documentation License version 1.3 requirements
23** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29 \page qtconcurrenttask.html
30 \title Concurrent Task
31 \ingroup thread
32
33 QtConcurrent::task provides an alternative interface for running a
34 task in a separate thread. The return value of the function is made
35 available through the QFuture API.
36
37 If you want to just run a function in a separate thread without adjusting
38 any parameters, use QtConcurrent::run as that lets you write less code.
39 The QtConcurrent::task is designed for cases where you need to perform
40 extra configurations steps.
41
42 This function is a part of the \l {Qt Concurrent} framework.
43
44 \section1 Fluent interface
45
46 The QtConcurrent::task returns an instance of an auxiliary class called
47 QtConcurrent::QTaskBuilder. Normally, you don't need to create an instance
48 of this class manually. The QtConcurrent::QTaskBuilder provides an interface
49 to adjust different task parameters in a chain-like manner. This approach
50 is known as a
51 \l {https://en.wikipedia.org/wiki/Fluent_interface}{fluent interface}.
52
53 You can just set the parameters you need and then kick a task off.
54 In order to finalize the configuration of a task you must invoke
55 QtConcurrent::QTaskBuilder::spawn. This function is non-blocking (i.e.
56 returns a future object immediately), but it's not guaranteed that the
57 task starts immediately. You can use the QFuture and QFutureWatcher classes
58 to monitor the status of the task.
59
60 See more examples and explanations below.
61
62 \section1 Running a task in a separate thread
63
64 To run a function in another thread, use QtConcurrent::QTaskBuilder::spawn:
65
66 \snippet code/src_concurrent_qtconcurrenttask.cpp 0
67
68 This will run a lambda function in a separate thread obtained from
69 the default QThreadPool.
70
71 \section1 Passing arguments to the task
72
73 Invoking a function with arguments is done by passing them to
74 QtConcurrent::QTaskBuilder::withArguments:
75
76 \snippet code/src_concurrent_qtconcurrenttask.cpp 1
77
78 A copy of each argument is made at the point where
79 QtConcurrent::QTaskBuilder::withArguments is called, and these values
80 are passed to the thread when it begins executing the task. Changes made
81 to the arguments after calling QtConcurrent::QTaskBuilder::withArguments
82 are not visible to the thread.
83
84 If you want to run a function that accepts arguments by reference, you
85 should use \l {https://en.cppreference.com/w/cpp/utility/functional/ref}
86 {std::ref/cref} auxiliary functions. These functions create thin wrappers
87 around passed arguments:
88
89 \snippet code/src_concurrent_qtconcurrenttask.cpp 2
90
91 Make sure that all wrapped objects live long enough. It is possible to
92 get undefined behavior if a task outlives the object wrapped by
93 std::ref/cref.
94
95 \section1 Returning values from the task
96
97 You can obtain the result of a task with the QFuture API:
98
99 \snippet code/src_concurrent_qtconcurrenttask.cpp 3
100
101 Note that QFuture::result() is a blocking call, it waits for the
102 result to become available. Use QFutureWatcher to get a notification
103 when the task has finished execution and the result is available.
104
105 In case you want to pass a result to another asynchronous task, you can
106 use QFuture::then() to create a chain of dependent tasks. See the QFuture
107 documentation for more details.
108
109 \section1 Additional API features
110
111 \section2 Using different types of callable objects
112
113 Strictly speaking, you can use any type of tasks and arguments that
114 satisfy the following condition:
115
116 \snippet code/src_concurrent_qtconcurrenttask.cpp 4
117
118 You can use a free function:
119
120 \snippet code/src_concurrent_qtconcurrenttask.cpp 5
121
122 You can use a member function:
123
124 \snippet code/src_concurrent_qtconcurrenttask.cpp 6
125
126 You can use a callable object with an operator():
127
128 \snippet code/src_concurrent_qtconcurrenttask.cpp 7
129
130 If you want to use an existing callable object, you need to either
131 copy/move it to QtConcurrent::task or wrap it with std::ref/cref:
132
133 \snippet code/src_concurrent_qtconcurrenttask.cpp 8
134
135 \section2 Using custom thread pool
136
137 You can specify a custom thread pool:
138
139 \snippet code/src_concurrent_qtconcurrenttask.cpp 9
140
141 \section2 Setting priority for a task
142
143 You can set the priority for a task:
144
145 \snippet code/src_concurrent_qtconcurrenttask.cpp 10
146
147 If you don't need a future object, you can call
148 QtConcurrent::QTaskBuilder::spawn(QtConcurrent::FutureResult::Ignore):
149
150 \snippet code/src_concurrent_qtconcurrenttask.cpp 11
151
152 You can access the promise object associated with the task by defining an
153 additional argument of \c {QPromise<T> &} type inside the function.
154 This additional argument must be the first argument passed to the function, and
155 like in \l {Concurrent Run With Promise} mode, the function is expected to return void type.
156 Result reporting is done through QPromise API:
157
158 \snippet code/src_concurrent_qtconcurrenttask.cpp 12
159*/
160
161/*!
162 \fn template <typename Task> [[nodiscard]] QTaskBuilder<Task> QtConcurrent::task(Task &&task);
163 \since 6.0
164
165 Creates an instance of QtConcurrent::QTaskBuilder. This object can be used
166 to adjust some parameters and run \a task in a separate thread.
167
168 \sa {Concurrent Task}, QtConcurrent::QTaskBuilder
169*/
170