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
11USERVER_NAMESPACE_BEGIN
12
13namespace engine {
14
15/// @ingroup userver_concurrency
16///
17/// @brief TaskInheritedVariable is a per-coroutine variable of arbitrary type.
18///
19/// These are like engine::TaskLocalVariable, but the variable instances are
20/// inherited by child tasks created via utils::Async.
21///
22/// The order of destruction of task-inherited variables is unspecified.
23template <typename T>
24class TaskInheritedVariable final {
25 static_assert(!std::is_reference_v<T>);
26 static_assert(!std::is_const_v<T>);
27
28 public:
29 /// @brief Get the variable instance for the current task.
30 /// @returns the variable or `nullptr` if variable was not set.
31 const T* GetOptional() const noexcept {
32 return Storage().GetOptional<T, kVariableKind>(impl_.GetKey());
33 }
34
35 /// @brief Get the variable instance for the current task.
36 /// @throws std::runtime_error if variable was not set.
37 const T& Get() const {
38 return Storage().Get<T, kVariableKind>(impl_.GetKey());
39 }
40
41 /// @brief Sets or replaces the T variable instance.
42 template <typename... Args>
43 void Emplace(Args&&... args) {
44 Storage().Emplace<T, kVariableKind>(impl_.GetKey(),
45 std::forward<Args>(args)...);
46 }
47
48 /// @overload
49 void Set(T&& value) { Emplace(std::move(value)); }
50
51 /// @overload
52 void Set(const T& value) { Emplace(value); }
53
54 /// @brief Hide the variable so that it is no longer accessible from the
55 /// current or new child tasks.
56 /// @note The variable might not actually be destroyed immediately.
57 void Erase() { Storage().Erase<T, kVariableKind>(impl_.GetKey()); }
58
59 /// @cond
60 // For internal use only
61 // inherits data to another storage
62 void InheritTo(impl::task_local::Storage& other,
63 impl::task_local::InternalTag) {
64 other.InheritNodeIfExists(Storage(), impl_.GetKey());
65 }
66 /// @endcond
67
68 private:
69 static constexpr auto kVariableKind =
70 impl::task_local::VariableKind::kInherited;
71
72 static impl::task_local::Storage& Storage() noexcept {
73 return impl::task_local::GetCurrentStorage();
74 }
75
76 impl::task_local::Variable impl_;
77};
78
79} // namespace engine
80
81USERVER_NAMESPACE_END