Reputation: 189
I have a variable in file tracker.hpp:
namespace TRIALS
{
static thread_local int a = -1;
}
I have another class in file called EMP in ema.hpp/ema.cpp
namespace Algo
{
class EMP
{
public:
void Sample();
};
}
namespace Algo
{
void EMP::Sample()
{
std::cout << "model " << std::this_thread::get_id() << " " << &TRIALS::a << " " << TRIALS::a << std::endl;
}
}
Then my main file I have
auto model = Algo::EMP();
void Simulate(const int a)
{
TRIALS::a = a;
model.Sample()
std::cout << "worker " << std::this_thread::get_id() << " " << &TRIALS::a << " " << TRIALS::a << std::endl;
}
int main()
{
std::cout << &TRIALS::a << std::endl;
const int nthreads = 1;
std::cout << "main " << std::this_thread::get_id() << " " << &TRIALS::a << " " << TRIALS::a << std::endl;
std::vector<std::thread> threads;
for(int i=0; i<nthreads; ++i)
{
threads.emplace_back(&Simulate, i);
}
for(auto &thread : threads)
{
thread.join();
}
std::cout << "main " << std::this_thread::get_id() << " " << &TRIALS::a << " " << TRIALS::a << std::endl;
return 0;
}
I am just running one thread for debugging but this is the output:
0x7f9540b621d8
main 140279012532800 0x7f9540b621d8 -1 (As expected)
model 140278985606912 0x7f953f1b469c -1 (Shouldn't this be 0??)
worker 140278985606912 0x7f953f1b4698 0 (As expected)
main 140279012532800 0x7f9540b621d8 -1 (As expected)
I was under the impression that each thread has it's own local copy of TRIALS::a. The a in model correctly gets incremented but when it returns from the function in the same thread, the value is still 0. I am printing out the thread ids and the address of a for good measure and I am seeing that there are actually 3 different versions of TRIALS::a despite only two total threads.
As a bonus question, what is the difference between static thread_local int a
and thread_local int a
?
Upvotes: 5
Views: 1401
Reputation: 136208
In your example static
makes that thread_local
object use internal linkage, so that each translation unit (.cpp file) has its own copy of the variable.
See storage class specifiers for details:
The
thread_local
keyword is only allowed for objects declared at namespace scope, objects declared at block scope, and static data members. It indicates that the object has thread storage duration. It can be combined withstatic
orextern
to specify internal or external linkage (except for static data members which always have external linkage), respectively, but that additional static doesn't affect the storage duration.
I.e. you may like to drop that static
keyword, so that you only have one copy of the object in the entire application. In the header file do:
namespace TRIALS {
extern thread_local int a;
}
And in one of the .cpp
:
thread_local int TRIALS::a = -1;
In C++17, you can make the variable inline
to avoid having to provide its definition in a .cpp
:
namespace TRIALS {
inline thread_local int a = -1;
}
Upvotes: 8