Is it allowed to leak pointers of thread local variable?

  c++, language-lawyer, multithreading

I am currently trying to better understand thread local storage in C++. To this end I wrote the following example:

#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <chrono>

thread_local int thread_index;

std::vector<int*> pointers;
std::mutex mutex;

void show_index()
{
  {
    thread_index = 0;

    std::lock_guard<std::mutex> lk(mutex);

    pointers.push_back(&thread_index);
  }

  while(true)
  {
    std::this_thread::sleep_for(std::chrono::seconds(1));

    {
      std::lock_guard<std::mutex> lk(mutex);
      std::cout << "Index of thread "
                << std::this_thread::get_id()
                << " : "
                << thread_index
                << std::endl;
    }
  }
}

void change_index()
{
  while(true)
  {
    std::this_thread::sleep_for(std::chrono::seconds(3));

    {
      std::lock_guard<std::mutex> lk(mutex);

      std::cout << "Thread "
                << std::this_thread::get_id()
                << " is changing indices"
                << std::endl;

      for(auto& pointer : pointers)
      {
        ++(*pointer);
      }
    }
  }
}

int main()
{
  std::vector<std::thread> threads;

  for(int i = 0; i < 3; ++i)
  {
    threads.push_back(std::thread(show_index));
  }

  threads.push_back(std::thread(change_index));

  for(auto& thread : threads)
  {
    thread.join();
  }

  return 0;
}

As can be seen the address of a thread_local variable is leaked into the program and the thread local variables are inadvertedly changed by another thread. All access to the global state is protected by a std::mutex, so there should not be an races. Indeed, I see the following expected output:

Index of thread 140443980949056 : 0
Index of thread 140443887072832 : 0
Index of thread 140443989341760 : 0
Index of thread 140443980949056 : 0
Index of thread 140443887072832 : 0
Index of thread 140443989341760 : 0
Thread 140443972556352 is changing indices
Index of thread 140443980949056 : 1
Index of thread 140443989341760 : 1
Index of thread 140443887072832 : 1
...

My question is: What does the standard say about accessing thread local variables from another thread? Is a thread local variable merely a pointer to memory that is guaranteed to be unique for each thread, or does the standard mandate "thread local" access as well?

Source: Windows Questions C++

LEAVE A COMMENT