userver: utils::ResourceScopeStorage Class Reference
Loading...
Searching...
No Matches
utils::ResourceScopeStorage Class Referencefinal

#include <userver/utils/resource_scopes.hpp>

Detailed Description

Defers subscription and callback registration until the object is fully constructed.

Components often register external subscriptions (statistics writers, config listeners, and similar) that capture this and run later on another thread. Registering them directly in the constructor is unsafe: the callback may fire before the constructor finishes and observe partially initialized fields. Unregistering in the destructor is equally unsafe if the callback can still run while members are already being destroyed.

During construction, call Register to queue a functor that performs the actual registration. The component system calls AfterConstruction when the constructor (including derived classes) has completed, and BeforeDestruction before the destructor body runs. That way registration callbacks see a fully built object, and unregistration runs before members used by the callback are torn down.

The same storage is available from components::ComponentContext::Scopes in components, or as a standalone helper in unit tests and WithResourceScopes.

Warning
Do not store ResourceScopeStorage as a field of the object that registers subscriptions on it. The storage would share that object's constructor and destructor, so AfterConstruction cannot run after the object is complete and BeforeDestruction cannot run before its members are destroyed. Wrap the object in WithResourceScopes instead.
static std::vector<int> trace;
// Reset static variables for --gtest_repeat.
trace = {};
class ComponentWithResource final : public components::ComponentBase {
public:
ComponentWithResource(const components::ComponentConfig& config, const components::ComponentContext& context)
: components::ComponentBase(config, context)
{
trace.push_back(0);
context.Scopes().Register([] {
trace.push_back(1);
return utils::FastScopeGuard([]() noexcept { trace.push_back(2); });
});
context.Scopes().Register([] {
trace.push_back(3);
return utils::FastScopeGuard([]() noexcept { trace.push_back(4); });
});
}
};
auto component_list = components::MinimalComponentList().Append<ComponentWithResource>("component");
components::InMemoryConfig{tests::MergeYaml(tests::kMinimalStaticConfig, kConfig)},
component_list
);
EXPECT_THAT(trace, ::testing::ElementsAre(0, 1, 3, 4, 2));

Definition at line 94 of file resource_scopes.hpp.

Public Member Functions

 ResourceScopeStorage (ResourceScopeStorage &&other) noexcept=default
ResourceScopeStorage & operator= (ResourceScopeStorage &&other) noexcept=default
template<std::invocable<> AfterConstructionCallback>
void Register (AfterConstructionCallback after_construction)
 Registers a functor to register some resource that will be called after the component is successfully created (including all class descendants) or after the component creation is emulated in unit tests. The functor must return a RAII-style handle object that unregisters the previously registered resource. The returned handle's destructor is called just before the component destructor is called.
void AfterConstruction ()
 Call all registered functors.
void BeforeDestruction () noexcept
 Unregister all previously registered resources.

Member Function Documentation

◆ AfterConstruction()

void utils::ResourceScopeStorage::AfterConstruction ( )

Call all registered functors.

If a functor throws, already constructed resources are unregistered via BeforeDestruction and the exception is rethrown.

◆ BeforeDestruction()

void utils::ResourceScopeStorage::BeforeDestruction ( )
noexcept

Unregister all previously registered resources.

Also drops factories that have not run AfterConstruction yet, so captured RAII handles unregister immediately.

◆ Register()

template<std::invocable<> AfterConstructionCallback>
void utils::ResourceScopeStorage::Register ( AfterConstructionCallback after_construction)
inline

Registers a functor to register some resource that will be called after the component is successfully created (including all class descendants) or after the component creation is emulated in unit tests. The functor must return a RAII-style handle object that unregisters the previously registered resource. The returned handle's destructor is called just before the component destructor is called.

Note
callback is not called if the component is not created OR any previously registered callback throws an exception.
if you don't have an existing RAII-ish class, but still want to do a cleanup, you might want to use utils::FastScopeGuard to wrap the cleanup function.

Definition at line 114 of file resource_scopes.hpp.


The documentation for this class was generated from the following file: