Is it legal to return a thread_local reference from a function?

thread_local c
c++ thread_local destructor
__thread vs thread_local
c++ thread_local initialization
thread_local rust
__declspec(thread)
c thread local singleton
thread storage duration

Returning a reference from a static like shown here is legal C++

static int& from_static() {
     static int x;
     return x;
}

Everything looks swell so far. But would it also be legal, if the static variable inside the function was thread_local instead?

static int& from_thread_local() {
     thread_local int x;
     return x;
}

Actually, I'm pretty sure it is. But mixing the static keyword in the declaration of the function with the thread_local from the variable declaration somehow doesn't sparkle with me.

This depends on how you are using it. thread_local storage duration lasts for the life time of the thread that created the variable. So, if this function was called by a thread then x would live until that thread exited. If you ran from_thread_local in it's own thread then it would not be safe as you wouldn't get the value until after the thread ends and the lifetime of x has ended.

The static on the function level has no effect on this since in that context static describes the linkage of the function, not the duration when it is a free function. If it is a member function then it just describes that no instance of the class is needed to call the function.

Keeping references to #[thread_local] statics is allowed across , This does not affect stabilization of async fn unless #[thread_local] is also fn foo​() -> impl Generator<Yield = (String, usize), Return = ()> { static || { let x In non-​generator functions, such references have function-local  It’s possible to return a reference from a function. But be careful if you try to do this: You do not want to return a reference to a local variable within a function — because when the function ends, the storage space for the local variables goes away. Not good!

You are basically asking two questions:

  1. Is it ok to return a reference to a local thread_local variable?
  2. What happens when you return a reference to a local thread_local variable from a static function?

The answer to question 1 is yes. The variable will outlive the function call, so the reference will be usable. (However, there are some obvious cases where this is not true, e.g., do not use the return value from such a function if you are wrapping it in a packaged_task that you are going to execute in another thread.)

The answer to question 2 is: the fact that the function is static has no effect on the meaning of the thread_local local variable. In the case of the Meyers singleton, the static specifier just means the function doesn't require an instance of the enclosing class.

Chapter 8 Thread-Local Storage (Linker and Libraries Guide), A shared library containing a reference to a thread-local variable, may be loaded The round(offset, align) function returns an offset rounded up to the next  The function above returns an object by value. From the previous tip, you know that you should not pass an object by value, but instead by reference. Passing by reference means passing a reference to an object that already exist. Thus, if you want to return a reference in a function, it means that you must create that object in the function.

Yes it is still legal C++.

However keep in mind that the reference you're returning is to a variable that is local to the thread, not to the function. So you need to take care not to exchange the reference between threads, or if you do you must ensure not to use it after the originating thread exits.

Thread Local Storage (TLS), Thread Local Storage (TLS) is the method by which each thread in a given return tls_i; } Although C++ generally allows for such dynamic initialization of objects with an expression that involves a reference to itself, this kind of error in C __declspec( thread )int tls_i = sizeof( tls_i ) // Legal in C and C++. Thread local storage is static but it behaves quite differently from simple static storage. When you declare a variable static there is exactly one instance of the variable. The compiler/runtime system guarantees that it will be initialized for you sometime before you actually use it, without specifying exactly when (some details omitted here.)

C++ keywords: thread_local (since C++11), C++ keywords: thread_local (since C++11). From cppreference. goto - return · Functions · Function declaration · Lambda function declaration. Both these examples allow for the thread local variable to exist within the function that uses it. In pre-threaded code, it would simply be a static storage duration variable within the function. For threads, that's modified to thread local storage duration. Yet another example would be something like errno.

Storage class specifiers - cppreference.com, goto - return 5) The thread_local keyword is only allowed for objects declared at namespace scope, objects A name that denotes object, reference, function, type, template, namespace, or value, may have linkage. A return by value means a copy will be made. A reference return type sends back a reference to the original. int Task1(int x, double y); // uses return by value int& Task2(int x, double y); // uses return by reference This is a trickier situation than reference parameters (which we will not see in detail right now).

Google C++ Style Guide, By this we specifically refer to the established conventions of the entire Google C++ In particular, a function-local static reference of the form static T& t = *new T; is allowed. thread_local variables that aren't declared inside a function must be The output of a C++ function is naturally provided via a return value and  The argument a would be passed by reference to SimpleThread(). The thread may still be sleeping in the function SimpleThread() after the variable a has already gone out of scope and its lifetime has ended. If so, i in SimpleThread() would actually be a dangling reference, and the assignment i = 0 would result in undefined behaviour.

Comments
  • I'm sorry, if I misused any C++ vocabulary. I didn't learn the language by reading the standard.
  • Why wouldn't it be OK? As long as the reference is not used after the calling thread terminates, it should be fine, the memory is still valid. The static on the function just means the function doesn't have a this parameter if it is a member of a class, or it has local linkage if it is standalone function. That doesn't affect the memory that the function is able to access. Applying static or thread_local on the local x variable inside the function dictates its lifetime, not its access rights.
  • You can return a reference to whatever you want, as long as it's lifetime exceeds that of the function call. The only thing that doesn't achieve that by default is a variable with automatic storage associated with the function's scope (local objects). thread_local does not have automatic storage so this usage is fine for the same reasons static is fine.
  • Learning C++ from reading the Standard is one of the harder ways to learn the language. Better than Trial and Error, I suppose, but much harder than a good text.
  • static describes the linkage of the function, not the duration Many thanks for reminding me
  • @nada No problem. Doesn't help the C++ likes to reuse keywords. Unfortunately intern or internal was never reserved so they couldn't make a common sense identifier.
  • In the case of the Meyers singleton (the topic of the post referenced by the OP) the static keyword is used inside a class, so it doesn't even affect the linkage of the function.
  • @Brian I wasn't thinking about member function but I have now added that in.