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() : factory_(Factory{}) {}
145 USERVER_IMPL_CONSTEVAL ThreadLocal(Factory factory) : factory_(factory) {}
147 ThreadLocalScope<VariableType> Use() {
return ThreadLocalScope<VariableType>(impl::ThreadLocal(factory_)); }
157template <
typename Factory>
158ThreadLocal(Factory factory) -> ThreadLocal<std::invoke_result_t<
const Factory&>, Factory>;
160template <
typename VariableType>
161ThreadLocalScope<VariableType>::ThreadLocalScope(VariableType& variable)
noexcept : variable_(variable) {
163 impl::IncrementLocalCoroutineSwitchBans();
167template <
typename VariableType>
168ThreadLocalScope<VariableType>::~ThreadLocalScope() {
170 impl::DecrementLocalCoroutineSwitchBans();
174template <
typename VariableType>
175VariableType& ThreadLocalScope<VariableType>::
operator*() &
noexcept
176 USERVER_IMPL_LIFETIME_BOUND {
180template <
typename VariableType>
181VariableType* ThreadLocalScope<VariableType>::
operator->() &
noexcept
182 USERVER_IMPL_LIFETIME_BOUND {