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