sbabbi
sbabbi

Reputation: 11181

When is a `thread_local` global variable initialized?

Consider the following example (lock guards on cout omitted for simplicity).

#include <future>
#include <iostream>
#include <thread>

using namespace std;

struct C
{
  C() { cout << "C constructor\n";}
  ~C() { cout << "C destructor\n";}
};

thread_local C foo;

int main()
{
   int select;
   cin >> select;
   future<void> f[10];
   for ( int i = 0;i < 10; ++i)
       f[i] = async( launch::async,[&](){ if (select) foo; } );
   return 0;
}

On both clang and gcc, this program outputs nothing if the user writes '0', while it prints Constructor/Destructor 10 times if the user inputs a non zero number. Additionally clang complains about an obvious non used expression result.

Since a thread_local storage life-time is supposed to span the entire thread's life, I expected the foo variable to be initialized in every thread regardless of the user input.

I might want to have a thread-local variable for the sole purpose of having a side-effect in the constructor, does the standard mandates that a thread_local object is initialized on its first use?

Upvotes: 32

Views: 10961

Answers (1)

Jon
Jon

Reputation: 437326

The standard allows for this behavior, although it doesn't guarantee it. From 3.7.2/2 [basic.stc.thread]:

A variable with thread storage duration shall be initialized before its first odr-use (3.2) and, if constructed, shall be destroyed on thread exit.

It's also possible that the objects are constructed at some other time (e.g. on program startup), as "before first use" means "at any point as long as it is before" rather than does "just before".

Upvotes: 26

Related Questions