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
28public:
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 { return Storage().GetOptional<T, kVariableKind>(impl_.GetKey()); }
32
33 /// @brief Get the variable instance for the current task.
34 /// @throws std::runtime_error if variable was not set.
35 const T& Get() const { return Storage().Get<T, kVariableKind>(impl_.GetKey()); }
36
37 /// @brief Sets or replaces the T variable instance.
38 template <typename... Args>
39 void Emplace(Args&&... args) {
40 Storage().Emplace<T, kVariableKind>(impl_.GetKey(), std::forward<Args>(args)...);
41 }
42
43 /// @overload
44 void Set(T&& value) { Emplace(std::move(value)); }
45
46 /// @overload
47 void Set(const T& value) { Emplace(value); }
48
49 /// @brief Hide the variable so that it is no longer accessible from the
50 /// current or new child tasks.
51 /// @note The variable might not actually be destroyed immediately.
52 void Erase() { Storage().Erase<T, kVariableKind>(impl_.GetKey()); }
53
54 /// @cond
55 // For internal use only
56 // inherits data to another storage
57 void InheritTo(impl::task_local::Storage& other, impl::task_local::InternalTag) {
58 other.InheritNodeIfExists(Storage(), impl_.GetKey());
59 }
60 /// @endcond
61
62private:
63 static constexpr auto kVariableKind = impl::task_local::VariableKind::kInherited;
64
65 static impl::task_local::Storage& Storage() noexcept { return impl::task_local::GetCurrentStorage(); }
66
67 impl::task_local::Variable impl_;
68};
69
70} // namespace engine
71
72USERVER_NAMESPACE_END