8#include <userver/compiler/impl/constexpr.hpp>
9#include <userver/compiler/impl/lifetime.hpp>
10#include <userver/compiler/impl/tls.hpp>
12#if __cplusplus
>= 202002L
&& (__clang_major__
>= 13
|| !defined(__clang__
) && __GNUC__
>= 9
)
14#define USERVER_IMPL_UNEVALUATED_LAMBDAS
17USERVER_NAMESPACE_BEGIN
23bool AreCoroutineSwitchesAllowed()
noexcept;
25void IncrementLocalCoroutineSwitchBans()
noexcept;
27void DecrementLocalCoroutineSwitchBans()
noexcept;
29#ifdef USERVER_IMPL_UNEVALUATED_LAMBDAS
30template <
typename T,
typename Factory =
decltype([] {
return T{}; })>
31using UniqueDefaultFactory = Factory;
34struct UniqueDefaultFactory final {
37 "Defaulted syntax for compiler::ThreadLocal is unavailable on "
38 "your compiler. Please use the lambda-factory syntax, see the "
39 "documentation for compiler::ThreadLocal."
49template <
typename VariableType>
50class ThreadLocalScope final {
52 ThreadLocalScope(ThreadLocalScope&&) =
delete;
53 ThreadLocalScope& operator=(ThreadLocalScope&&) =
delete;
57 VariableType&
operator*() &
noexcept USERVER_IMPL_LIFETIME_BOUND;
60 VariableType*
operator->() &
noexcept USERVER_IMPL_LIFETIME_BOUND;
63 explicit ThreadLocalScope(VariableType& variable)
noexcept;
66 VariableType& operator*() &&
noexcept =
delete;
69 VariableType* operator->() &&
noexcept =
delete;
73 static_assert(!std::is_reference_v<VariableType>);
74 static_assert(!std::is_const_v<VariableType>);
76 VariableType& variable_;
137template <
typename VariableType,
typename Factory = impl::UniqueDefaultFactory<VariableType>>
138class ThreadLocal final {
139 static_assert(std::is_empty_v<Factory>);
140 static_assert(std::is_same_v<VariableType, std::invoke_result_t<
const Factory&>>);
143 USERVER_IMPL_CONSTEVAL ThreadLocal()
144 : factory_(Factory{})
147 USERVER_IMPL_CONSTEVAL ThreadLocal(Factory factory)
151 ThreadLocalScope<VariableType> Use() {
return ThreadLocalScope<VariableType>(impl::ThreadLocal(factory_)); }
161template <
typename Factory>
162ThreadLocal(Factory factory) -> ThreadLocal<std::invoke_result_t<
const Factory&>, Factory>;
164template <
typename VariableType>
165ThreadLocalScope<VariableType>::ThreadLocalScope(VariableType& variable)
noexcept : variable_(variable) {
167 impl::IncrementLocalCoroutineSwitchBans();
171template <
typename VariableType>
172ThreadLocalScope<VariableType>::~ThreadLocalScope() {
174 impl::DecrementLocalCoroutineSwitchBans();
178template <
typename VariableType>
179VariableType& ThreadLocalScope<VariableType>::
operator*() &
noexcept
180USERVER_IMPL_LIFETIME_BOUND {
184template <
typename VariableType>
185VariableType* ThreadLocalScope<VariableType>::
operator->() &
noexcept
186USERVER_IMPL_LIFETIME_BOUND {