userver: userver/utils/async.hpp Source File
Loading...
Searching...
No Matches
async.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/async.hpp
4/// @brief Utility functions to start asynchronous tasks.
5
6#include <string>
7#include <utility>
8
9#include <userver/engine/impl/task_context_factory.hpp>
10#include <userver/engine/task/shared_task_with_result.hpp>
11#include <userver/engine/task/task_with_result.hpp>
12#include <userver/utils/impl/source_location.hpp>
13#include <userver/utils/impl/span_wrap_call.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace utils {
18
19/// @ingroup userver_concurrency
20///
21/// @brief Starts an asynchronous task.
22///
23/// By default, arguments are copied or moved inside the resulting
24/// `TaskWithResult`, like `std::thread` does. To pass an argument by reference,
25/// wrap it in `std::ref / std::cref` or capture the arguments using a lambda.
26///
27/// For more documentation on launching asynchronous tasks:
28///
29/// @see @ref intro_tasks
30///
31/// ## About this specific overload
32///
33/// This is the overload that should be used by default.
34///
35/// * The task will be launched on the current TaskProcessor.
36/// * Only 1 task may call `Wait` or `Get` on this task.
37/// * The task may be cancelled before the function starts execution
38/// in case of TaskProcessor overload. Also, if the task is cancelled for any
39/// reason before the function starts execution, it will not run at all.
40/// * The task will create a child tracing::Span with the specified name
41/// * The task will inherit all engine::TaskInheritedVariable instances
42/// from the current task.
43///
44/// For details on the various other overloads:
45/// @see @ref flavors_of_async
46///
47/// For maximum customization of task parameters, see @ref utils::TaskBuilder.
48///
49/// @param name Name of the task to show in logs
50/// @param f Function to execute asynchronously
51/// @param args Arguments to pass to the function
52/// @returns engine::TaskWithResult
53template <typename Function, typename... Args>
54[[nodiscard]] auto Async(std::string name, Function&& f, Args&&... args) {
55 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
56 engine::impl::TaskConfig{},
57 utils::impl::SpanLazyPrvalue(std::move(name)),
58 std::forward<Function>(f),
59 std::forward<Args>(args)...
60 );
61}
62
63/// @overload
64/// @ingroup userver_concurrency
65///
66/// Task execution may be cancelled before the function starts execution
67/// in case of TaskProcessor overload.
68///
69/// @param task_processor Task processor to run on
70/// @param name Name of the task to show in logs
71/// @param f Function to execute asynchronously
72/// @param args Arguments to pass to the function
73/// @returns engine::TaskWithResult
74template <typename Function, typename... Args>
75[[nodiscard]] auto Async(engine::TaskProcessor& task_processor, std::string name, Function&& f, Args&&... args) {
76 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
77 engine::impl::TaskConfig{.task_processor = &task_processor},
78 utils::impl::SpanLazyPrvalue(std::move(name)),
79 std::forward<Function>(f),
80 std::forward<Args>(args)...
81 );
82}
83
84/// @overload
85/// @ingroup userver_concurrency
86///
87/// Execution of function is guaranteed to start regardless
88/// of engine::TaskProcessor load limits. Prefer utils::Async by default.
89///
90/// @param task_processor Task processor to run on
91/// @param name Name for the tracing::Span to use with this task
92/// @param f Function to execute asynchronously
93/// @param args Arguments to pass to the function
94/// @returns engine::TaskWithResult
95template <typename Function, typename... Args>
96[[nodiscard]] auto CriticalAsync(
97 engine::TaskProcessor& task_processor,
98 std::string name,
99 Function&& f,
100 Args&&... args
101) {
102 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
103 engine::impl::TaskConfig{
104 .task_processor = &task_processor,
105 .importance = engine::Task::Importance::kCritical,
106 },
107 utils::impl::SpanLazyPrvalue(std::move(name)),
108 std::forward<Function>(f),
109 std::forward<Args>(args)...
110 );
111}
112
113/// @overload
114/// @ingroup userver_concurrency
115///
116/// Task execution may be cancelled before the function starts execution
117/// in case of TaskProcessor overload.
118///
119/// @param task_processor Task processor to run on
120/// @param name Name of the task to show in logs
121/// @param f Function to execute asynchronously
122/// @param args Arguments to pass to the function
123/// @returns engine::SharedTaskWithResult
124template <typename Function, typename... Args>
125[[nodiscard]] auto SharedAsync(engine::TaskProcessor& task_processor, std::string name, Function&& f, Args&&... args) {
126 return engine::impl::MakeTaskWithResult<engine::SharedTaskWithResult>(
127 engine::impl::TaskConfig{.task_processor = &task_processor},
128 utils::impl::SpanLazyPrvalue(std::move(name)),
129 std::forward<Function>(f),
130 std::forward<Args>(args)...
131 );
132}
133
134/// @overload
135/// @ingroup userver_concurrency
136///
137/// Execution of function is guaranteed to start regardless
138/// of engine::TaskProcessor load limits. Prefer utils::Async by default.
139///
140/// @param name Name for the tracing::Span to use with this task
141/// @param f Function to execute asynchronously
142/// @param args Arguments to pass to the function
143/// @returns engine::TaskWithResult
144template <typename Function, typename... Args>
145[[nodiscard]] auto CriticalAsync(std::string name, Function&& f, Args&&... args) {
146 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
147 engine::impl::TaskConfig{.importance = engine::Task::Importance::kCritical},
148 utils::impl::SpanLazyPrvalue(std::move(name)),
149 std::forward<Function>(f),
150 std::forward<Args>(args)...
151 );
152}
153
154/// @overload
155/// @ingroup userver_concurrency
156///
157/// Execution of function is guaranteed to start regardless
158/// of engine::TaskProcessor load limits. Prefer utils::SharedAsync by default.
159///
160/// @param name Name for the tracing::Span to use with this task
161/// @param f Function to execute asynchronously
162/// @param args Arguments to pass to the function
163/// @returns engine::SharedTaskWithResult
164template <typename Function, typename... Args>
165[[nodiscard]] auto SharedCriticalAsync(std::string name, Function&& f, Args&&... args) {
166 return engine::impl::MakeTaskWithResult<engine::SharedTaskWithResult>(
167 engine::impl::TaskConfig{.importance = engine::Task::Importance::kCritical},
168 utils::impl::SpanLazyPrvalue(std::move(name)),
169 std::forward<Function>(f),
170 std::forward<Args>(args)...
171 );
172}
173
174/// @overload
175/// @ingroup userver_concurrency
176///
177/// Task execution may be cancelled before the function starts execution
178/// in case of TaskProcessor overload.
179///
180/// @param name Name of the task to show in logs
181/// @param f Function to execute asynchronously
182/// @param args Arguments to pass to the function
183/// @returns engine::SharedTaskWithResult
184template <typename Function, typename... Args>
185[[nodiscard]] auto SharedAsync(std::string name, Function&& f, Args&&... args) {
186 return engine::impl::MakeTaskWithResult<engine::SharedTaskWithResult>(
187 engine::impl::TaskConfig{},
188 utils::impl::SpanLazyPrvalue(std::move(name)),
189 std::forward<Function>(f),
190 std::forward<Args>(args)...
191 );
192}
193
194/// @overload
195/// @ingroup userver_concurrency
196///
197/// Task execution may be cancelled before the function starts execution
198/// in case of TaskProcessor overload.
199///
200/// @param name Name of the task to show in logs
201/// @param deadline Deadline to set for the child task, upon reaching it the task will be cancelled
202/// @param f Function to execute asynchronously
203/// @param args Arguments to pass to the function
204/// @returns engine::TaskWithResult
205template <typename Function, typename... Args>
206[[nodiscard]] auto Async(std::string name, engine::Deadline deadline, Function&& f, Args&&... args) {
207 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
208 engine::impl::TaskConfig{.deadline = deadline},
209 utils::impl::SpanLazyPrvalue(std::move(name)),
210 std::forward<Function>(f),
211 std::forward<Args>(args)...
212 );
213}
214
215/// @ingroup userver_concurrency
216///
217/// Starts an asynchronous task without propagating
218/// engine::TaskInheritedVariable. tracing::Span and baggage::Baggage are
219/// inherited. Task execution may be cancelled before the function starts
220/// execution in case of engine::TaskProcessor overload.
221///
222/// Typically used from a request handler to launch tasks that outlive the
223/// request and do not effect its completion.
224///
225/// ## Usage example
226/// Suppose you have some component that runs asynchronous tasks:
227/// @snippet utils/async_test.cpp AsyncBackground component
228/// @snippet utils/async_test.cpp AsyncBackground handler
229///
230/// If the tasks logically belong to the component itself (not to the method
231/// caller), then they should be launched using utils::AsyncBackground instead
232/// of the regular utils::Async
233/// @snippet utils/async_test.cpp AsyncBackground FooAsync
234///
235/// ## Arguments
236/// By default, arguments are copied or moved inside the resulting
237/// `TaskWithResult`, like `std::thread` does. To pass an argument by reference,
238/// wrap it in `std::ref / std::cref` or capture the arguments using a lambda.
239///
240/// @param name Name of the task to show in logs
241/// @param task_processor Task processor to run on
242/// @param f Function to execute asynchronously
243/// @param args Arguments to pass to the function
244/// @returns engine::TaskWithResult
245template <typename Function, typename... Args>
246[[nodiscard]] auto AsyncBackground(
247 std::string name,
248 engine::TaskProcessor& task_processor,
249 Function&& f,
250 Args&&... args
251) {
252 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
253 engine::impl::TaskConfig{.task_processor = &task_processor},
254 utils::impl::SpanLazyPrvalue(
255 std::move(name),
256 utils::impl::SpanWrapCall::InheritVariables::kNo,
257 utils::impl::SpanWrapCall::HideSpan::kNo
258 ),
259 std::forward<Function>(f),
260 std::forward<Args>(args)...
261 );
262}
263
264/// @overload
265/// @ingroup userver_concurrency
266///
267/// Execution of function is guaranteed to start regardless
268/// of engine::TaskProcessor load limits. Use for background tasks for which
269/// failing to start not just breaks handling of a single request, but harms
270/// the whole service instance.
271///
272/// @param name Name of the task to show in logs
273/// @param task_processor Task processor to run on
274/// @param f Function to execute asynchronously
275/// @param args Arguments to pass to the function
276/// @returns engine::TaskWithResult
277template <typename Function, typename... Args>
278[[nodiscard]] auto CriticalAsyncBackground(
279 std::string name,
280 engine::TaskProcessor& task_processor,
281 Function&& f,
282 Args&&... args
283) {
284 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
285 engine::impl::TaskConfig{
286 .task_processor = &task_processor,
287 .importance = engine::Task::Importance::kCritical,
288 },
289 utils::impl::SpanLazyPrvalue(
290 std::move(name),
291 utils::impl::SpanWrapCall::InheritVariables::kNo,
292 utils::impl::SpanWrapCall::HideSpan::kNo
293 ),
294 std::forward<Function>(f),
295 std::forward<Args>(args)...
296 );
297}
298
299} // namespace utils
300
301USERVER_NAMESPACE_END