userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
background_task_storage.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/concurrent/background_task_storage.hpp
4
/// @brief @copybrief concurrent::BackgroundTaskStorage
5
6
#
include
<
cstdint
>
7
#
include
<
utility
>
8
9
#
include
<
userver
/
engine
/
impl
/
detached_tasks_sync_block
.
hpp
>
10
#
include
<
userver
/
engine
/
task
/
task_processor_fwd
.
hpp
>
11
#
include
<
userver
/
utils
/
async
.
hpp
>
12
13
USERVER_NAMESPACE_BEGIN
14
15
namespace
concurrent
{
16
17
/// @ingroup userver_concurrency userver_containers
18
///
19
/// A version of concurrent::BackgroundTaskStorage for advanced use cases (e.g.
20
/// driver internals) that can take the ownership of any kind of task.
21
class
BackgroundTaskStorageCore
final
{
22
public
:
23
/// Creates an empty BTS.
24
BackgroundTaskStorageCore
();
25
26
BackgroundTaskStorageCore(BackgroundTaskStorageCore&&) =
delete
;
27
BackgroundTaskStorageCore& operator=(BackgroundTaskStorageCore&&) =
delete
;
28
~BackgroundTaskStorageCore();
29
30
/// Explicitly cancel and wait for the tasks. New tasks must not be launched
31
/// after this call returns. Should be called no more than once.
32
void
CancelAndWait
()
noexcept
;
33
34
/// Explicitly wait for execution tasks in the store.
35
/// Should be called no more than once.
36
void
CloseAndWaitDebug
()
noexcept
;
37
38
/// @brief Detaches task, allowing it to continue execution out of scope. It
39
/// will be cancelled and waited for on BTS destruction.
40
/// @note After detach, Task becomes invalid
41
///
42
/// Can be called from a coroutine or a non-coroutine thread.
43
void
Detach
(engine::
Task
&& task);
44
45
/// Approximate number of currently active tasks
46
std::
int64_t
ActiveTasksApprox
()
const
noexcept
;
47
48
private
:
49
std::optional<engine::
impl
::DetachedTasksSyncBlock> sync_block_;
50
};
51
52
/// @ingroup userver_concurrency userver_containers
53
///
54
/// A storage that allows one to start detached tasks; cancels and waits for
55
/// unfinished tasks completion at the destructor. Provides CancelAndWait to
56
/// explicitly cancel tasks (recommended).
57
///
58
/// Usable for detached tasks that capture references to resources with a
59
/// limited lifetime. You must guarantee that the resources are available while
60
/// the BackgroundTaskStorage is alive.
61
///
62
/// ## Performance considerations
63
///
64
/// Tasks remove themselves from the BackgroundTaskStorage on completion, so there is no memory leak.
65
///
66
/// @warning The implementation is optimized for spawning tasks. Waiting for remaining tasks may be slow CPU-wise.
67
/// As a guideline, do not create `BackgroundTaskStorage` instances for each request, use `std::vector<Task>`
68
/// for storing per-request child tasks instead.
69
///
70
/// ## Usage synopsis
71
///
72
/// @snippet concurrent/background_task_storage_test.cpp Sample
73
///
74
/// ## Lifetime of task's captures
75
///
76
/// All the advice from utils::Async is applicable here.
77
///
78
/// BackgroundTaskStorage is always stored as a class field. Tasks that are
79
/// launched inside it (or moved inside it, for BackgroundTaskStorageCore)
80
/// can safely access fields declared before it, but not after it:
81
///
82
/// @snippet concurrent/background_task_storage_test.cpp BtsLifetimeCapturesPitfalls
83
///
84
/// Generally, it's a good idea to declare `bts_` after most other fields
85
/// to avoid lifetime bugs. An example of fool-proof code:
86
///
87
/// @snippet concurrent/background_task_storage_test.cpp Bts field ordering
88
///
89
/// Components and their clients can always be safely captured by reference:
90
///
91
/// @see @ref scripts/docs/en/userver/component_system.md
92
///
93
/// So for a BackgroundTaskStorage stored in a component, its tasks can only
94
/// safely use the fields declared before the BTS field, as well as everything
95
/// from the components, on which the current component depends.
96
class
BackgroundTaskStorage
final
{
97
public
:
98
/// Creates a BTS that launches tasks in the engine::TaskProcessor used at the
99
/// BTS creation.
100
BackgroundTaskStorage
();
101
102
/// Creates a BTS that launches tasks in the specified engine::TaskProcessor.
103
explicit
BackgroundTaskStorage
(engine::TaskProcessor& task_processor);
104
105
BackgroundTaskStorage(
const
BackgroundTaskStorage&) =
delete
;
106
BackgroundTaskStorage& operator=(
const
BackgroundTaskStorage&) =
delete
;
107
108
/// @brief Explicitly cancel and wait for the tasks. New tasks must not be launched
109
/// after this call returns. Should be called no more than once.
110
///
111
/// More precisely, new tasks must not be launched once this call is completed, but can be launched in the process
112
/// of waiting for the remaining tasks. This means that one detached task is allowed to spawn another detached
113
/// task into the same BTS, which will immediately be cancelled and for which `CancelAndWait` will wait as well.
114
///
115
/// Can only be called from a coroutine.
116
void
CancelAndWait
()
noexcept
;
117
118
/// @brief Explicitly stop accepting new tasks and wait for execution tasks in the
119
/// store. Should be called no more than once.
120
///
121
/// Can only be called from a coroutine.
122
void
CloseAndWaitDebug
()
noexcept
;
123
124
/// @brief Launch a task that will be cancelled and waited for in the BTS
125
/// destructor.
126
///
127
/// The task is started as non-Critical, it may be cancelled due to
128
/// `TaskProcessor` overload. engine::TaskInheritedVariable instances are not
129
/// inherited from the caller except baggage::Baggage. See
130
/// utils::AsyncBackground for details.
131
///
132
/// Can be called from a coroutine or a non-coroutine thread.
133
template
<
typename
... Args>
134
void
AsyncDetach
(std::string name, Args&&... args) {
135
core_
.
Detach
(
utils
::AsyncBackground(std::move(name), task_processor_, std::forward<Args>(args)...)
)
;
136
}
137
138
/// @brief Launch a task that will be cancelled and waited for in the BTS
139
/// destructor.
140
///
141
/// Execution of function is guaranteed to start regardless
142
/// of engine::TaskProcessor load limits.
143
/// engine::TaskInheritedVariable instances are not
144
/// inherited from the caller except baggage::Baggage. See
145
/// utils::CriticalAsyncBackground for details.
146
///
147
/// Can be called from a coroutine or a non-coroutine thread.
148
template
<
typename
... Args>
149
void
CriticalAsyncDetach
(std::string name, Args&&... args) {
150
core_
.
Detach
(
utils
::CriticalAsyncBackground(std::move(name), task_processor_, std::forward<Args>(args)...)
)
;
151
}
152
153
/// Approximate number of currently active tasks
154
std::
int64_t
ActiveTasksApprox
()
const
noexcept
;
155
156
private
:
157
BackgroundTaskStorageCore core_;
158
engine::TaskProcessor& task_processor_;
159
};
160
161
}
// namespace concurrent
162
163
USERVER_NAMESPACE_END
userver
concurrent
background_task_storage.hpp
Generated on
for userver by
Doxygen
1.17.0