userver: compiler::ThreadLocal< VariableType, Factory > Class Template Reference
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
compiler::ThreadLocal< VariableType, Factory > Class Template Referencefinal

#include <userver/compiler/thread_local.hpp>

Detailed Description

template<typename VariableType, typename Factory = impl::UniqueDefaultFactory<VariableType>>
class compiler::ThreadLocal< VariableType, Factory >

Creates a unique thread-local variable that can be used in a coroutine-safe manner.

Thread-local variables are known to cause issues when used together with userver coroutines:

Thread-local variables created through this class are protected against these issues.

Example usage:

// NOTE: the thread-local itself should be:
// * NEVER `thread_local`
// * `static` where appropriate
// * `inline` where appropriate
void WriteAll(fs::blocking::FileDescriptor& fd,
utils::span<const std::string_view> data) {
// If we just write one item in `data` after the other, we might perform too
// many syscall-s, because each of the strings may be short.
//
// So let's somehow concatenate `data` into a single string. But now there
// may be too many allocations if such an operation is frequent.
//
// Solution: use a thread_local buffer to only allocate once per thread.
// NOTE: the scope should be non-static, non-thread_local.
auto buffer = local_buffer.Use();
buffer->clear();
for (const auto piece : data) {
buffer->append(piece);
}
fd.Write(*buffer);
}

The thread-local variable is value-initialized.

In C++17 mode, or if you need to initialize the variable with some arguments, the ThreadLocal should be passed a capture-less lambda that constructs the variable. Example:

// NOTE: if you need thread-local randomness, don't roll your own!
// See <userver/utils/rand.hpp> and <userver/crypto/random.hpp> first!
compiler::ThreadLocal local_rng = [] {
return std::minstd_rand{utils::Rand()};
};
std::uint32_t MyRand() {
auto rng = local_rng.Use();
return std::uniform_int_distribution<std::uint32_t>{}(*rng);
}

Once acquired through Use, the reference to the thread-local variable should not be returned or otherwise escape the scope of the ThreadLocalScope object. An example of buggy code:

std::string_view PrepareBuffer(std::string_view x, std::string_view y) {
const auto buffer = local_buffer.Use();
buffer->clear();
buffer->append(x);
buffer->append(y);
return *buffer; // <- BUG! Reference to thread-local escapes the scope
}

Do not store a reference to the thread-local object in a separate variable:

void WriteMessage(std::string_view x, std::string_view y) {
auto buffer_scope = local_buffer.Use();
// Code smell! This makes it more difficult to see that `buffer` is
// a reference to thread-local at a glance.
auto& buffer = *buffer_scope;
buffer.clear();
// ...
}

Until the variable name goes out of scope, userver engine synchronization primitives and clients (web or db) should not be used.

Definition at line 138 of file thread_local.hpp.

Public Member Functions

USERVER_IMPL_CONSTEVAL ThreadLocal (Factory factory)
 
ThreadLocalScope< VariableType > Use ()
 

Constructor & Destructor Documentation

◆ ThreadLocal() [1/2]

template<typename VariableType , typename Factory = impl::UniqueDefaultFactory<VariableType>>
USERVER_IMPL_CONSTEVAL compiler::ThreadLocal< VariableType, Factory >::ThreadLocal ( )
inline

Definition at line 144 of file thread_local.hpp.

◆ ThreadLocal() [2/2]

template<typename VariableType , typename Factory = impl::UniqueDefaultFactory<VariableType>>
USERVER_IMPL_CONSTEVAL compiler::ThreadLocal< VariableType, Factory >::ThreadLocal ( Factory factory)
inline

Definition at line 146 of file thread_local.hpp.

Member Function Documentation

◆ Use()

template<typename VariableType , typename Factory = impl::UniqueDefaultFactory<VariableType>>
ThreadLocalScope< VariableType > compiler::ThreadLocal< VariableType, Factory >::Use ( )
inline

Definition at line 149 of file thread_local.hpp.


The documentation for this class was generated from the following file: