userver: userver/engine/task/inherited_variable.hpp Source File
Loading...
Searching...
No Matches
inherited_variable.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/task/inherited_variable.hpp
4/// @brief @copybrief engine::TaskInheritedVariable
5
6#include <type_traits>
7#include <utility>
8
9#include <userver/engine/impl/task_local_storage.hpp>
10#include <userver/engine/task/inherited_variable_options.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace engine {
15
16/// @ingroup userver_concurrency
17///
18/// @brief TaskInheritedVariable is a per-coroutine variable of arbitrary type.
19///
20/// These are like engine::TaskLocalVariable, but the variable instances are
21/// inherited by child tasks created via utils::Async.
22///
23/// By default a variable is inherited only by regular child tasks, not @ref utils::AsyncBackground.
24/// This behavior can be changed by passing a different priority to the constructor.
25///
26/// The order of destruction of task-inherited variables is unspecified.
27template <typename T>
28class TaskInheritedVariable final {
29 static_assert(!std::is_reference_v<T>);
30 static_assert(!std::is_const_v<T>);
31
32public:
33 /// @brief Create a task-inherited variable with @ref TaskInheritedVariablePriority::kNormal.
37
38 /// @brief Create a task-inherited variable with the specified inheritance priority.
40 : impl_(priority)
41 {}
42
43 /// @brief Get the variable instance for the current task.
44 /// @returns the variable or `nullptr` if variable was not set.
45 const T* GetOptional() const noexcept { return Storage().GetOptional<T, kVariableKind>(impl_.GetKey()); }
46
47 /// @brief Get the variable instance for the current task.
48 /// @throws std::runtime_error if variable was not set.
49 const T& Get() const { return Storage().Get<T, kVariableKind>(impl_.GetKey()); }
50
51 /// @brief Sets or replaces the T variable instance.
52 template <typename... Args>
53 void Emplace(Args&&... args) {
54 Storage().Emplace<T, kVariableKind>(impl_.GetKey(), std::forward<Args>(args)...);
55 }
56
57 /// @overload
58 void Set(T&& value) { Emplace(std::move(value)); }
59
60 /// @overload
61 void Set(const T& value) { Emplace(value); }
62
63 /// @brief Hide the variable so that it is no longer accessible from the
64 /// current or new child tasks.
65 /// @note The variable might not actually be destroyed immediately.
66 void Erase() { Storage().Erase<T, kVariableKind>(impl_.GetKey()); }
67
68private:
69 static constexpr auto kVariableKind = impl::task_local::VariableKind::kInherited;
70
71 static impl::task_local::Storage& Storage() noexcept { return impl::task_local::GetCurrentStorage(); }
72
73 impl::task_local::Variable impl_;
74};
75
76} // namespace engine
77
78USERVER_NAMESPACE_END