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/// Starts an asynchronous task with a hidden tracing::Span. The span has
88/// @ref logging::Level::kNone log level, while logs within the span remain
89/// linked to the nearest visible span.
90///
91/// Task execution may be cancelled before the function starts execution
92/// in case of TaskProcessor overload.
93///
94/// @param f Function to execute asynchronously
95/// @param args Arguments to pass to the function
96/// @returns engine::TaskWithResult
97template <typename Function, typename... Args>
98[[nodiscard]] auto AsyncHideSpan(Function&& f, Args&&... args) {
99 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
100 engine::impl::TaskConfig{},
101 utils::impl::SpanLazyPrvalue(
102 std::string{},
103 utils::impl::SpanWrapCall::InheritVariables::kYes,
104 utils::impl::SpanWrapCall::HideSpan::kYes
105 ),
106 std::forward<Function>(f),
107 std::forward<Args>(args)...
108 );
109}
110
111/// @overload
112/// @ingroup userver_concurrency
113///
114/// Starts an asynchronous task with a hidden tracing::Span. The span has
115/// @ref logging::Level::kNone log level, while logs within the span remain
116/// linked to the nearest visible span.
117///
118/// Task execution may be cancelled before the function starts execution
119/// in case of TaskProcessor overload.
120///
121/// @param task_processor Task processor to run on
122/// @param f Function to execute asynchronously
123/// @param args Arguments to pass to the function
124/// @returns engine::TaskWithResult
125template <typename Function, typename... Args>
126[[nodiscard]] auto AsyncHideSpan(engine::TaskProcessor& task_processor, Function&& f, Args&&... args) {
127 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
128 engine::impl::TaskConfig{.task_processor = &task_processor},
129 utils::impl::SpanLazyPrvalue(
130 std::string{},
131 utils::impl::SpanWrapCall::InheritVariables::kYes,
132 utils::impl::SpanWrapCall::HideSpan::kYes
133 ),
134 std::forward<Function>(f),
135 std::forward<Args>(args)...
136 );
137}
138
139/// @overload
140/// @ingroup userver_concurrency
141///
142/// Execution of function is guaranteed to start regardless
143/// of engine::TaskProcessor load limits. Prefer utils::Async by default.
144///
145/// @param task_processor Task processor to run on
146/// @param name Name for the tracing::Span to use with this task
147/// @param f Function to execute asynchronously
148/// @param args Arguments to pass to the function
149/// @returns engine::TaskWithResult
150template <typename Function, typename... Args>
151[[nodiscard]] auto CriticalAsync(
152 engine::TaskProcessor& task_processor,
153 std::string name,
154 Function&& f,
155 Args&&... args
156) {
157 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
158 engine::impl::TaskConfig{
159 .task_processor = &task_processor,
160 .importance = engine::Task::Importance::kCritical,
161 },
162 utils::impl::SpanLazyPrvalue(std::move(name)),
163 std::forward<Function>(f),
164 std::forward<Args>(args)...
165 );
166}
167
168/// @overload
169/// @ingroup userver_concurrency
170///
171/// Task execution may be cancelled before the function starts execution
172/// in case of TaskProcessor overload.
173///
174/// @param task_processor Task processor to run on
175/// @param name Name of the task to show in logs
176/// @param f Function to execute asynchronously
177/// @param args Arguments to pass to the function
178/// @returns engine::SharedTaskWithResult
179template <typename Function, typename... Args>
180[[nodiscard]] auto SharedAsync(engine::TaskProcessor& task_processor, std::string name, Function&& f, Args&&... args) {
181 return engine::impl::MakeTaskWithResult<engine::SharedTaskWithResult>(
182 engine::impl::TaskConfig{.task_processor = &task_processor},
183 utils::impl::SpanLazyPrvalue(std::move(name)),
184 std::forward<Function>(f),
185 std::forward<Args>(args)...
186 );
187}
188
189/// @overload
190/// @ingroup userver_concurrency
191///
192/// Execution of function is guaranteed to start regardless
193/// of engine::TaskProcessor load limits. Prefer utils::Async by default.
194///
195/// @param name Name for the tracing::Span to use with this task
196/// @param f Function to execute asynchronously
197/// @param args Arguments to pass to the function
198/// @returns engine::TaskWithResult
199template <typename Function, typename... Args>
200[[nodiscard]] auto CriticalAsync(std::string name, Function&& f, Args&&... args) {
201 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
202 engine::impl::TaskConfig{.importance = engine::Task::Importance::kCritical},
203 utils::impl::SpanLazyPrvalue(std::move(name)),
204 std::forward<Function>(f),
205 std::forward<Args>(args)...
206 );
207}
208
209/// @overload
210/// @ingroup userver_concurrency
211///
212/// Execution of function is guaranteed to start regardless
213/// of engine::TaskProcessor load limits. Prefer utils::SharedAsync by default.
214///
215/// @param name Name for the tracing::Span to use with this task
216/// @param f Function to execute asynchronously
217/// @param args Arguments to pass to the function
218/// @returns engine::SharedTaskWithResult
219template <typename Function, typename... Args>
220[[nodiscard]] auto SharedCriticalAsync(std::string name, Function&& f, Args&&... args) {
221 return engine::impl::MakeTaskWithResult<engine::SharedTaskWithResult>(
222 engine::impl::TaskConfig{.importance = engine::Task::Importance::kCritical},
223 utils::impl::SpanLazyPrvalue(std::move(name)),
224 std::forward<Function>(f),
225 std::forward<Args>(args)...
226 );
227}
228
229/// @overload
230/// @ingroup userver_concurrency
231///
232/// Task execution may be cancelled before the function starts execution
233/// in case of TaskProcessor overload.
234///
235/// @param name Name of the task to show in logs
236/// @param f Function to execute asynchronously
237/// @param args Arguments to pass to the function
238/// @returns engine::SharedTaskWithResult
239template <typename Function, typename... Args>
240[[nodiscard]] auto SharedAsync(std::string name, Function&& f, Args&&... args) {
241 return engine::impl::MakeTaskWithResult<engine::SharedTaskWithResult>(
242 engine::impl::TaskConfig{},
243 utils::impl::SpanLazyPrvalue(std::move(name)),
244 std::forward<Function>(f),
245 std::forward<Args>(args)...
246 );
247}
248
249/// @overload
250/// @ingroup userver_concurrency
251///
252/// Task execution may be cancelled before the function starts execution
253/// in case of TaskProcessor overload.
254///
255/// @param name Name of the task to show in logs
256/// @param deadline Deadline to set for the child task, upon reaching it the task will be cancelled
257/// @param f Function to execute asynchronously
258/// @param args Arguments to pass to the function
259/// @returns engine::TaskWithResult
260template <typename Function, typename... Args>
261[[nodiscard]] auto Async(std::string name, engine::Deadline deadline, Function&& f, Args&&... args) {
262 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
263 engine::impl::TaskConfig{.deadline = deadline},
264 utils::impl::SpanLazyPrvalue(std::move(name)),
265 std::forward<Function>(f),
266 std::forward<Args>(args)...
267 );
268}
269
270/// @ingroup userver_concurrency
271///
272/// Starts an asynchronous task without propagating
273/// engine::TaskInheritedVariable. tracing::Span and baggage::Baggage are
274/// inherited. Task execution may be cancelled before the function starts
275/// execution in case of engine::TaskProcessor overload.
276///
277/// Typically used from a request handler to launch tasks that outlive the
278/// request and do not effect its completion.
279///
280/// ## Usage example
281/// Suppose you have some component that runs asynchronous tasks:
282/// @snippet utils/async_test.cpp AsyncBackground component
283/// @snippet utils/async_test.cpp AsyncBackground handler
284///
285/// If the tasks logically belong to the component itself (not to the method
286/// caller), then they should be launched using utils::AsyncBackground instead
287/// of the regular utils::Async
288/// @snippet utils/async_test.cpp AsyncBackground FooAsync
289///
290/// ## Arguments
291/// By default, arguments are copied or moved inside the resulting
292/// `TaskWithResult`, like `std::thread` does. To pass an argument by reference,
293/// wrap it in `std::ref / std::cref` or capture the arguments using a lambda.
294///
295/// @param name Name of the task to show in logs
296/// @param task_processor Task processor to run on
297/// @param f Function to execute asynchronously
298/// @param args Arguments to pass to the function
299/// @returns engine::TaskWithResult
300template <typename Function, typename... Args>
301[[nodiscard]] auto AsyncBackground(
302 std::string name,
303 engine::TaskProcessor& task_processor,
304 Function&& f,
305 Args&&... args
306) {
307 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
308 engine::impl::TaskConfig{.task_processor = &task_processor},
309 utils::impl::SpanLazyPrvalue(
310 std::move(name),
311 utils::impl::SpanWrapCall::InheritVariables::kNo,
312 utils::impl::SpanWrapCall::HideSpan::kNo
313 ),
314 std::forward<Function>(f),
315 std::forward<Args>(args)...
316 );
317}
318
319/// @overload
320/// @ingroup userver_concurrency
321///
322/// Execution of function is guaranteed to start regardless
323/// of engine::TaskProcessor load limits. Use for background tasks for which
324/// failing to start not just breaks handling of a single request, but harms
325/// the whole service instance.
326///
327/// @param name Name of the task to show in logs
328/// @param task_processor Task processor to run on
329/// @param f Function to execute asynchronously
330/// @param args Arguments to pass to the function
331/// @returns engine::TaskWithResult
332template <typename Function, typename... Args>
333[[nodiscard]] auto CriticalAsyncBackground(
334 std::string name,
335 engine::TaskProcessor& task_processor,
336 Function&& f,
337 Args&&... args
338) {
339 return engine::impl::MakeTaskWithResult<engine::TaskWithResult>(
340 engine::impl::TaskConfig{
341 .task_processor = &task_processor,
342 .importance = engine::Task::Importance::kCritical,
343 },
344 utils::impl::SpanLazyPrvalue(
345 std::move(name),
346 utils::impl::SpanWrapCall::InheritVariables::kNo,
347 utils::impl::SpanWrapCall::HideSpan::kNo
348 ),
349 std::forward<Function>(f),
350 std::forward<Args>(args)...
351 );
352}
353
354} // namespace utils
355
356USERVER_NAMESPACE_END