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
&&
13 (__clang_major__
>= 13
|| !defined(__clang__
) && __GNUC__
>= 9
)
15#define USERVER_IMPL_UNEVALUATED_LAMBDAS
18USERVER_NAMESPACE_BEGIN
24bool AreCoroutineSwitchesAllowed()
noexcept;
26void IncrementLocalCoroutineSwitchBans()
noexcept;
28void DecrementLocalCoroutineSwitchBans()
noexcept;
30#ifdef USERVER_IMPL_UNEVALUATED_LAMBDAS
31template <
typename T,
typename Factory =
decltype([] {
return T{}; })>
32using UniqueDefaultFactory = Factory;
35struct UniqueDefaultFactory final {
36 static_assert(!
sizeof(T),
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.");
48template <
typename VariableType>
49class ThreadLocalScope final {
51 ThreadLocalScope(ThreadLocalScope&&) =
delete;
52 ThreadLocalScope& operator=(ThreadLocalScope&&) =
delete;
62 explicit ThreadLocalScope(VariableType& variable)
noexcept;
65 VariableType& operator*() &&
noexcept =
delete;
68 VariableType* operator->() &&
noexcept =
delete;
72 static_assert(!std::is_reference_v<VariableType>);
73 static_assert(!std::is_const_v<VariableType>);
75 VariableType& variable_;
136template <
typename VariableType,
137 typename Factory = impl::UniqueDefaultFactory<VariableType>>
138class ThreadLocal final {
139 static_assert(std::is_empty_v<Factory>);
141 std::is_same_v<VariableType, std::invoke_result_t<
const Factory&>>);
147 : factory_(factory) {}
149 ThreadLocalScope<VariableType> Use() {
150 return ThreadLocalScope<VariableType>(impl::ThreadLocal(factory_));
161template <
typename Factory>
162ThreadLocal(Factory factory)
163 -> ThreadLocal<std::invoke_result_t<
const Factory&>, Factory>;
165template <
typename VariableType>
166ThreadLocalScope<VariableType>::ThreadLocalScope(
167 VariableType& variable)
noexcept
168 : variable_(variable) {
170 impl::IncrementLocalCoroutineSwitchBans();
174template <
typename VariableType>
175ThreadLocalScope<VariableType>::~ThreadLocalScope() {
177 impl::DecrementLocalCoroutineSwitchBans();
181template <
typename VariableType>
182VariableType& ThreadLocalScope<VariableType>::
operator*() &
noexcept
187template <
typename VariableType>
188VariableType* ThreadLocalScope<VariableType>::
operator->() &
noexcept