0

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.

nada
  • 2,109
  • 2
  • 16
  • 23
  • I'm sorry, if I misused any C++ vocabulary. I didn't learn the language by reading the standard. – nada Oct 15 '19 at 20:34
  • 2
    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. – Remy Lebeau Oct 15 '19 at 20:34
  • 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. – François Andrieux Oct 15 '19 at 20:39
  • 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. – user4581301 Oct 15 '19 at 21:02

3 Answers3

2

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.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • _static describes the linkage of the function, not the duration_ Many thanks for reminding me – nada Oct 15 '19 at 20:45
  • @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. – NathanOliver Oct 15 '19 at 20:47
  • 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 Bi Oct 15 '19 at 20:47
  • @Brian I wasn't thinking about member function but I have now added that in. – NathanOliver Oct 15 '19 at 20:50
2

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.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
1

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.

mnistic
  • 10,866
  • 2
  • 19
  • 33