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