userver: userver/utils/async.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 <functional>
7#include <string>
8#include <utility>
9
10#include <userver/engine/async.hpp>
11#include <userver/utils/fast_pimpl.hpp>
12#include <userver/utils/lazy_prvalue.hpp>
13
14USERVER_NAMESPACE_BEGIN
15
16namespace utils {
17
18namespace impl {
19
20// A wrapper that obtains a Span from args, attaches it to current coroutine,
21// and applies a function to the rest of arguments.
22struct SpanWrapCall {
23 enum class InheritVariables { kYes, kNo };
24
25 explicit SpanWrapCall(std::string&& name, InheritVariables inherit_variables);
26
27 SpanWrapCall(const SpanWrapCall&) = delete;
28 SpanWrapCall(SpanWrapCall&&) = delete;
29 SpanWrapCall& operator=(const SpanWrapCall&) = delete;
30 SpanWrapCall& operator=(SpanWrapCall&&) = delete;
31 ~SpanWrapCall();
32
33 template <typename Function, typename... Args>
34 auto operator()(Function&& f, Args&&... args) {
35 DoBeforeInvoke();
36 return std::invoke(std::forward<Function>(f), std::forward<Args>(args)...);
37 }
38
39 private:
40 void DoBeforeInvoke();
41
42 struct Impl;
43
44 static constexpr std::size_t kImplSize = 4264;
45 static constexpr std::size_t kImplAlign = 8;
46 utils::FastPimpl<Impl, kImplSize, kImplAlign> pimpl_;
47};
48
49// Note: 'name' must outlive the result of this function
50inline auto SpanLazyPrvalue(std::string&& name) {
51 return utils::LazyPrvalue([&name] {
52 return SpanWrapCall(std::move(name), SpanWrapCall::InheritVariables::kYes);
53 });
54}
55
56} // namespace impl
57
58/// @ingroup userver_concurrency
59///
60/// Starts an asynchronous task, execution of function is guaranteed to start
61/// regardless of engine::TaskProcessor load limits.
62///
63/// Prefer using utils::Async if not sure that you need this.
64///
65/// By default, arguments are copied or moved inside the resulting
66/// `TaskWithResult`, like `std::thread` does. To pass an argument by reference,
67/// wrap it in `std::ref / std::cref` or capture the arguments using a lambda.
68///
69/// @param tasks_processor Task processor to run on
70/// @param name Name for the tracing::Span to use with this task
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 CriticalAsync(engine::TaskProcessor& task_processor,
76 std::string name, Function&& f,
77 Args&&... args) {
78 return engine::CriticalAsyncNoSpan(
79 task_processor, impl::SpanLazyPrvalue(std::move(name)),
80 std::forward<Function>(f), std::forward<Args>(args)...);
81}
82
83/// @ingroup userver_concurrency
84///
85/// Starts an asynchronous task, execution of function is guaranteed to start
86/// regardless of engine::TaskProcessor load limits.
87///
88/// Prefer using utils::SharedAsync if not sure that you need this.
89///
90/// By default, arguments are copied or moved inside the resulting
91/// `SharedTaskWithResult`, like `std::thread` does. To pass an argument by
92/// reference, wrap it in `std::ref / std::cref` or capture the arguments using
93/// a lambda.
94///
95/// @param tasks_processor Task processor to run on
96/// @param name Name for the tracing::Span to use with this task
97/// @param f Function to execute asynchronously
98/// @param args Arguments to pass to the function
99/// @returns engine::SharedTaskWithResult
100template <typename Function, typename... Args>
101[[nodiscard]] auto SharedCriticalAsync(engine::TaskProcessor& task_processor,
102 std::string name, Function&& f,
103 Args&&... args) {
104 return engine::SharedCriticalAsyncNoSpan(
105 task_processor, impl::SpanLazyPrvalue(std::move(name)),
106 std::forward<Function>(f), std::forward<Args>(args)...);
107}
108
109/// @ingroup userver_concurrency
110///
111/// Starts an asynchronous task, task execution may be cancelled before the
112/// function starts execution in case of TaskProcessor overload.
113///
114/// Use utils::CriticalAsync if the function execution must start and you are
115/// absolutely sure that you need it.
116///
117/// By default, arguments are copied or moved inside the resulting
118/// `TaskWithResult`, like `std::thread` does. To pass an argument by reference,
119/// wrap it in `std::ref / std::cref` or capture the arguments using a lambda.
120///
121/// @param tasks_processor Task processor to run on
122/// @param name Name of the task to show in logs
123/// @param f Function to execute asynchronously
124/// @param args Arguments to pass to the function
125/// @returns engine::TaskWithResult
126template <typename Function, typename... Args>
127[[nodiscard]] auto Async(engine::TaskProcessor& task_processor,
128 std::string name, Function&& f, Args&&... args) {
129 return engine::AsyncNoSpan(
130 task_processor, impl::SpanLazyPrvalue(std::move(name)),
131 std::forward<Function>(f), std::forward<Args>(args)...);
132}
133
134/// @ingroup userver_concurrency
135///
136/// Starts an asynchronous task, task execution may be cancelled before the
137/// function starts execution in case of TaskProcessor overload.
138///
139/// Use utils::SharedCriticalAsync if the function execution must start and you
140/// are absolutely sure that you need it.
141///
142/// By default, arguments are copied or moved inside the resulting
143/// `SharedTaskWithResult`, like `std::thread` does. To pass an argument by
144/// reference, wrap it in `std::ref / std::cref` or capture the arguments using
145/// a lambda.
146///
147/// @param tasks_processor Task processor to run on
148/// @param name Name of the task to show in logs
149/// @param f Function to execute asynchronously
150/// @param args Arguments to pass to the function
151/// @returns engine::SharedTaskWithResult
152template <typename Function, typename... Args>
153[[nodiscard]] auto SharedAsync(engine::TaskProcessor& task_processor,
154 std::string name, Function&& f, Args&&... args) {
155 return engine::SharedAsyncNoSpan(
156 task_processor, impl::SpanLazyPrvalue(std::move(name)),
157 std::forward<Function>(f), std::forward<Args>(args)...);
158}
159
160/// @ingroup userver_concurrency
161///
162/// Starts an asynchronous task with deadline, task execution may be cancelled
163/// before the function starts execution in case of TaskProcessor overload.
164///
165/// By default, arguments are copied or moved inside the resulting
166/// `TaskWithResult`, like `std::thread` does. To pass an argument by reference,
167/// wrap it in `std::ref / std::cref` or capture the arguments using a lambda.
168///
169/// @param tasks_processor Task processor to run on
170/// @param name Name of the task to show in logs
171/// @param f Function to execute asynchronously
172/// @param args Arguments to pass to the function
173/// @returns engine::TaskWithResult
174template <typename Function, typename... Args>
175[[nodiscard]] auto Async(engine::TaskProcessor& task_processor,
176 std::string name, engine::Deadline deadline,
177 Function&& f, Args&&... args) {
178 return engine::AsyncNoSpan(
179 task_processor, deadline, impl::SpanLazyPrvalue(std::move(name)),
180 std::forward<Function>(f), std::forward<Args>(args)...);
181}
182
183/// @ingroup userver_concurrency
184///
185/// Starts an asynchronous task with deadline, task execution may be cancelled
186/// before the function starts execution in case of TaskProcessor overload.
187///
188/// By default, arguments are copied or moved inside the resulting
189/// `SharedTaskWithResult`, like `std::thread` does. To pass an argument by
190/// reference, wrap it in `std::ref / std::cref` or capture the arguments using
191/// a lambda.
192///
193/// @param tasks_processor Task processor to run on
194/// @param name Name of the task to show in logs
195/// @param f Function to execute asynchronously
196/// @param args Arguments to pass to the function
197/// @returns engine::SharedTaskWithResult
198template <typename Function, typename... Args>
199[[nodiscard]] auto SharedAsync(engine::TaskProcessor& task_processor,
200 std::string name, engine::Deadline deadline,
201 Function&& f, Args&&... args) {
202 return engine::SharedAsyncNoSpan(
203 task_processor, deadline, impl::SpanLazyPrvalue(std::move(name)),
204 std::forward<Function>(f), std::forward<Args>(args)...);
205}
206
207/// @ingroup userver_concurrency
208///
209/// Starts an asynchronous task on current task processor, execution of
210/// function is guaranteed to start regardless of engine::TaskProcessor load
211/// limits.
212///
213/// Prefer using utils::Async if not sure that you need this.
214///
215/// By default, arguments are copied or moved inside the resulting
216/// `TaskWithResult`, like `std::thread` does. To pass an argument by reference,
217/// wrap it in `std::ref / std::cref` or capture the arguments using a lambda.
218///
219/// @param name Name for the tracing::Span to use with this task
220/// @param f Function to execute asynchronously
221/// @param args Arguments to pass to the function
222/// @returns engine::TaskWithResult
223template <typename Function, typename... Args>
224[[nodiscard]] auto CriticalAsync(std::string name, Function&& f,
225 Args&&... args) {
226 return utils::CriticalAsync(engine::current_task::GetTaskProcessor(),
227 std::move(name), std::forward<Function>(f),
228 std::forward<Args>(args)...);
229}
230
231/// @ingroup userver_concurrency
232///
233/// Starts an asynchronous task on current task processor, execution of
234/// function is guaranteed to start regardless of engine::TaskProcessor load
235/// limits.
236///
237/// Prefer using utils::SharedAsync if not sure that you need this.
238///
239/// By default, arguments are copied or moved inside the resulting
240/// `SharedTaskWithResult`, like `std::thread` does. To pass an argument by
241/// reference, wrap it in `std::ref / std::cref` or capture the arguments using
242/// a lambda.
243///
244/// @param name Name for the tracing::Span to use with this task
245/// @param f Function to execute asynchronously
246/// @param args Arguments to pass to the function
247/// @returns engine::SharedTaskWithResult
248template <typename Function, typename... Args>
249[[nodiscard]] auto SharedCriticalAsync(std::string name, Function&& f,
250 Args&&... args) {
251 return utils::SharedCriticalAsync(engine::current_task::GetTaskProcessor(),
252 std::move(name), std::forward<Function>(f),
253 std::forward<Args>(args)...);
254}
255
256/// @ingroup userver_concurrency
257///
258/// Starts an asynchronous task on current task processor, task execution
259/// may be cancelled before the function starts execution in case of
260/// engine::TaskProcessor overload.
261///
262/// Use utils::CriticalAsync if the function execution must start and you are
263/// absolutely sure that you need it.
264///
265/// By default, arguments are copied or moved inside the resulting
266/// `TaskWithResult`, like `std::thread` does. To pass an argument by reference,
267/// wrap it in `std::ref / std::cref` or capture the arguments using a lambda.
268///
269/// @param name Name of the task to show in logs
270/// @param f Function to execute asynchronously
271/// @param args Arguments to pass to the function
272/// @returns engine::TaskWithResult
273template <typename Function, typename... Args>
274[[nodiscard]] auto Async(std::string name, Function&& f, Args&&... args) {
275 return utils::Async(engine::current_task::GetTaskProcessor(), std::move(name),
276 std::forward<Function>(f), std::forward<Args>(args)...);
277}
278
279/// @ingroup userver_concurrency
280///
281/// Starts an asynchronous task on current task processor, task execution
282/// may be cancelled before the function starts execution in case of
283/// engine::TaskProcessor overload.
284///
285/// Use utils::SharedCriticalAsync if the function execution must start and you
286/// are absolutely sure that you need it.
287///
288/// By default, arguments are copied or moved inside the resulting
289/// `SharedTaskWithResult`, like `std::thread` does. To pass an argument by
290/// reference, wrap it in `std::ref / std::cref` or capture the arguments using
291/// a lambda.
292///
293/// @param name Name of the task to show in logs
294/// @param f Function to execute asynchronously
295/// @param args Arguments to pass to the function
296/// @returns engine::SharedTaskWithResult
297template <typename Function, typename... Args>
298[[nodiscard]] auto SharedAsync(std::string name, Function&& f, Args&&... args) {
299 return utils::SharedAsync(engine::current_task::GetTaskProcessor(),
300 std::move(name), std::forward<Function>(f),
301 std::forward<Args>(args)...);
302}
303
304/// @ingroup userver_concurrency
305///
306/// Starts an asynchronous task with deadline on current task processor, task
307/// execution may be cancelled before the function starts execution in case of
308/// engine::TaskProcessor overload.
309///
310/// By default, arguments are copied or moved inside the resulting
311/// `TaskWithResult`, like `std::thread` does. To pass an argument by reference,
312/// wrap it in `std::ref / std::cref` or capture the arguments using a lambda.
313///
314/// @param name Name of the task to show in logs
315/// @param f Function to execute asynchronously
316/// @param args Arguments to pass to the function
317/// @returns engine::TaskWithResult
318template <typename Function, typename... Args>
319[[nodiscard]] auto Async(std::string name, engine::Deadline deadline,
320 Function&& f, Args&&... args) {
321 return utils::Async(engine::current_task::GetTaskProcessor(), std::move(name),
322 deadline, std::forward<Function>(f),
323 std::forward<Args>(args)...);
324}
325
326/// @ingroup userver_concurrency
327///
328/// Starts an asynchronous task with deadline on current task processor, task
329/// execution may be cancelled before the function starts execution in case of
330/// engine::TaskProcessor overload.
331///
332/// By default, arguments are copied or moved inside the resulting
333/// `SharedTaskWithResult`, like `std::thread` does. To pass an argument by
334/// reference, wrap it in `std::ref / std::cref` or capture the arguments using
335/// a lambda.
336///
337/// @param name Name of the task to show in logs
338/// @param f Function to execute asynchronously
339/// @param args Arguments to pass to the function
340/// @returns engine::SharedTaskWithResult
341template <typename Function, typename... Args>
342[[nodiscard]] auto SharedAsync(std::string name, engine::Deadline deadline,
343 Function&& f, Args&&... args) {
344 return utils::SharedAsync(
345 engine::current_task::GetTaskProcessor(), std::move(name), deadline,
346 std::forward<Function>(f), std::forward<Args>(args)...);
347}
348
349/// @ingroup userver_concurrency
350///
351/// Starts an asynchronous task without propagating
352/// engine::TaskInheritedVariable. tracing::Span is still inherited. Task
353/// execution may be cancelled before the function starts execution in case of
354/// engine::TaskProcessor overload.
355///
356/// Typically used from a request handler to launch tasks that outlive the
357/// request and do not effect its completion.
358///
359/// ## Usage example
360/// Suppose you have some component that runs asynchronous tasks:
361/// @snippet utils/async_test.cpp AsyncBackground component
362/// @snippet utils/async_test.cpp AsyncBackground handler
363///
364/// If the tasks logically belong to the component itself (not to the method
365/// caller), then they should be launched using utils::AsyncBackground instead
366/// of the regular utils::Async
367/// @snippet utils/async_test.cpp AsyncBackground FooAsync
368///
369/// ## Arguments
370/// By default, arguments are copied or moved inside the resulting
371/// `TaskWithResult`, like `std::thread` does. To pass an argument by reference,
372/// wrap it in `std::ref / std::cref` or capture the arguments using a lambda.
373///
374/// @param name Name of the task to show in logs
375/// @param tasks_processor Task processor to run on
376/// @param f Function to execute asynchronously
377/// @param args Arguments to pass to the function
378/// @returns engine::TaskWithResult
379template <typename Function, typename... Args>
380[[nodiscard]] auto AsyncBackground(std::string name,
381 engine::TaskProcessor& task_processor,
382 Function&& f, Args&&... args) {
383 return engine::AsyncNoSpan(
384 task_processor, utils::LazyPrvalue([&] {
385 return impl::SpanWrapCall(std::move(name),
386 impl::SpanWrapCall::InheritVariables::kNo);
387 }),
388 std::forward<Function>(f), std::forward<Args>(args)...);
389}
390
391} // namespace utils
392
393USERVER_NAMESPACE_END