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