userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
component_context.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/components/component_context.hpp
4
/// @brief @copybrief components::ComponentContext
5
6
#
include
<
stdexcept
>
7
#
include
<
string_view
>
8
9
#
include
<
userver
/
compiler
/
demangle
.
hpp
>
10
#
include
<
userver
/
components
/
component_fwd
.
hpp
>
11
#
include
<
userver
/
components
/
raw_component_base
.
hpp
>
12
#
include
<
userver
/
engine
/
task
/
task_processor_fwd
.
hpp
>
13
#
include
<
userver
/
utils
/
impl
/
internal_tag
.
hpp
>
14
#
include
<
userver
/
utils
/
resource_scopes_fwd
.
hpp
>
15
16
// TODO remove extra includes
17
#
include
<
functional
>
18
#
include
<
memory
>
19
#
include
<
vector
>
20
21
USERVER_NAMESPACE_BEGIN
22
23
namespace
engine::
impl
{
24
class
TaskContext;
25
}
// namespace engine::impl
26
27
namespace
components
{
28
29
namespace
impl {
30
31
class
Manager;
32
class
ComponentContextImpl;
33
class
ComponentInfo;
34
35
template
<
class
T>
36
constexpr
auto
NameFromComponentType() ->
decltype
(std::string_view{T::kName}) {
37
return
T::kName;
38
}
39
40
template
<
class
T,
class
... Args>
41
constexpr
auto
NameFromComponentType(Args...) {
42
static_assert
(
43
!
sizeof
(T),
44
"Component does not have a 'kName' member convertible to "
45
"std::string_view. You have to explicitly specify the name: "
46
"context.FindComponent<T>(name) or "
47
"context.FindComponentOptional<T>(name)."
48
);
49
return
std::string_view{};
50
}
51
52
}
// namespace impl
53
54
/// @brief Exception that is thrown from
55
/// components::ComponentContext::FindComponent() if a component load failed.
56
class
ComponentsLoadCancelledException
:
public
std::runtime_error {
57
public
:
58
ComponentsLoadCancelledException();
59
explicit
ComponentsLoadCancelledException(std::string_view message);
60
};
61
62
/// @brief Class to retrieve other components.
63
///
64
/// Only the const member functions of this class are meant for usage in
65
/// component constructor (because of that this class is always passed as a
66
/// const reference to the constructors).
67
///
68
/// @warning Don't store references to `ComponentContext` in your component!
69
/// Lifetime of the passed `ComponentContext` ends as soon as
70
/// the constructor ends.
71
///
72
/// For usage outside the component constructor see components::State.
73
///
74
/// @see @ref userver_components
75
class
ComponentContext
final
{
76
public
:
77
ComponentContext(ComponentContext&&) =
delete
;
78
ComponentContext& operator=(ComponentContext&&) =
delete
;
79
80
/// @brief Finds a component of type T with specified name (if any) and
81
/// returns the component after it was initialized.
82
///
83
/// Can only be called from other component's constructor in a task where
84
/// that constructor was called.
85
/// May block and asynchronously wait for the creation of the requested
86
/// component.
87
/// @throw ComponentsLoadCancelledException if components loading was
88
/// cancelled due to errors in the creation of other component.
89
/// @throw std::runtime_error if component missing in `component_list` was
90
/// requested.
91
template
<
typename
T>
92
T&
FindComponent
()
const
{
93
return
FindComponent<T>(impl::NameFromComponentType<T>());
94
}
95
96
/// @overload T& FindComponent()
97
template
<
typename
T>
98
T& FindComponent(std::string_view name)
const
{
99
if
(!Contains(name)) {
100
ThrowNonRegisteredComponent(name,
compiler
::GetTypeName<T>());
101
}
102
103
auto
* component_base = DoFindComponent(name);
104
T* ptr =
dynamic_cast
<T*>(component_base);
105
if
(!ptr) {
106
ThrowComponentTypeMismatch(name,
compiler
::GetTypeName<T>(), component_base);
107
}
108
109
return
*ptr;
110
}
111
112
template
<
typename
T>
113
T& FindComponent(std::string_view
/*name*/
= {}) {
114
return
ReportMisuse<T>();
115
}
116
117
/// @brief If there's no component with specified type and name return
118
/// nullptr; otherwise behaves as FindComponent().
119
template
<
typename
T>
120
T*
FindComponentOptional
()
const
{
121
return
FindComponentOptional<T>(impl::NameFromComponentType<T>());
122
}
123
124
/// @overload T* FindComponentOptional()
125
template
<
typename
T>
126
T* FindComponentOptional(std::string_view name)
const
{
127
if
(!Contains(name)) {
128
return
nullptr
;
129
}
130
return
dynamic_cast
<T*>(DoFindComponent(name));
131
}
132
133
template
<
typename
T>
134
T& FindComponentOptional(std::string_view
/*name*/
= {}) {
135
return
ReportMisuse<T>();
136
}
137
138
/// @brief Returns an engine::TaskProcessor with the specified name.
139
engine::TaskProcessor&
GetTaskProcessor
(std::string_view name)
const
;
140
141
template
<
typename
T>
142
engine::TaskProcessor& GetTaskProcessor(
const
T&) {
143
return
ReportMisuse<T>();
144
}
145
146
/// @brief Returns the current component name. This is helpful in cases
147
/// where multiple instances of the component class may be created using
148
/// `component_list.Append<T>("custom-name")` syntax.
149
///
150
/// @warning The lifetime of the returned string ends as soon as
151
/// the current component's constructor completes. Store it
152
/// as an `std::string` if needed.
153
std::string_view
GetComponentName
()
const
;
154
155
/// @brief Returns @ref utils::ResourceScopeStorage that can be used
156
/// (by a component or any other class) to register user resources.
157
utils
::ResourceScopeStorage&
Scopes
()
const
;
158
159
/// @cond
160
// For internal use only.
161
ComponentContext(
utils
::impl::InternalTag, impl::ComponentContextImpl& impl, impl::ComponentInfo& component_info)
162
noexcept
;
163
164
// For internal use only.
165
impl::ComponentContextImpl& GetImpl(
utils
::impl::InternalTag)
const
;
166
167
// For internal use only.
168
const
impl::Manager& GetManager(
utils
::impl::InternalTag)
const
;
169
/// @endcond
170
171
private
:
172
/// @returns true if there is a component with the specified name and it
173
/// could be found via FindComponent()
174
bool
Contains(std::string_view name)
const
noexcept
;
175
176
template
<
typename
T>
177
bool
Contains(
const
T&) {
178
return
ReportMisuse<T>();
179
}
180
181
template
<
class
T>
182
decltype
(
auto
) ReportMisuse() {
183
static_assert
(
184
!
sizeof
(T),
185
"components::ComponentContext should be accepted by "
186
"a constant reference, i.e. "
187
"`MyComponent(const components::ComponentConfig& config, "
188
"const components::ComponentContext& context)`"
189
);
190
return
0;
191
}
192
193
[[noreturn]]
void
ThrowNonRegisteredComponent(std::string_view name, std::string_view type)
const
;
194
195
[[noreturn]]
void
ThrowComponentTypeMismatch(
196
std::string_view name,
197
std::string_view type,
198
RawComponentBase
* component
199
)
const
;
200
201
RawComponentBase
* DoFindComponent(std::string_view name)
const
;
202
203
impl::ComponentContextImpl& impl_;
204
impl::ComponentInfo& component_info_;
205
};
206
207
}
// namespace components
208
209
USERVER_NAMESPACE_END
userver
components
component_context.hpp
Generated on
for userver by
Doxygen
1.17.0