userver: userver/engine/task/local_variable.hpp Source File
Loading...
Searching...
No Matches
local_variable.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/task/local_variable.hpp
4/// @brief @copybrief engine::TaskLocalVariable
5
6#include <type_traits>
7
8#include <userver/engine/impl/task_local_storage.hpp>
9
10USERVER_NAMESPACE_BEGIN
11
12namespace engine {
13
14/// @ingroup userver_concurrency
15///
16/// @brief TaskLocalVariable is a per-coroutine variable of arbitrary type.
17///
18/// It is an alternative to `thread_local`, but per-task instead of per-thread.
19///
20/// The order of destruction of task-local variables is inverse to the order of
21/// initialization.
22template <typename T>
23class TaskLocalVariable final {
24 static_assert(!std::is_reference_v<T>);
25 static_assert(!std::is_const_v<T>);
26
27public:
28 /// @brief Get the instance of the variable for the current coroutine.
29 /// Initializes (default constructs) the variable if it was not previously
30 /// initialized.
31 /// @note Must be called from a coroutine, otherwise it is UB.
32 T& operator*();
33
34 /// @overload
35 T* operator->();
36
37 /// @brief Get the variable instance for the current task.
38 /// @returns the variable or `nullptr` if variable was not initialized.
39 T* GetOptional() noexcept {
40 return impl::task_local::GetCurrentStorage().GetOptional<T, kVariableKind>(impl_.GetKey());
41 }
42
43private:
44 static constexpr auto kVariableKind = impl::task_local::VariableKind::kNormal;
45
46 impl::task_local::Variable impl_;
47};
48
49template <typename T>
50T& TaskLocalVariable<T>::operator*() {
51 return impl::task_local::GetCurrentStorage().GetOrEmplace<T, kVariableKind>(impl_.GetKey());
52}
53
54template <typename T>
55T* TaskLocalVariable<T>::operator->() {
56 return &(**this);
57}
58
59} // namespace engine
60
61USERVER_NAMESPACE_END