0

Consider the following C++11 program:

struct S {
   S() {/* do something */ }
} global_object;

int main() {
}

I don't have GCC 4.8 yet to test, but from what I read about the C++11 standard, no matter if I declare the global object as thread_local, the object itself will be instantiated once for all the possible threads that can be created during the execution of the program.

Is there a way (portable or not) in GCC to have the global object instantiated and constrcuted every time one thread starts and destructed every time the same thread finishes?

4

2 回答 2

4

but from what I read about the C++11 standard, no matter if I declare the global object as thread_local, the object itself will be instantiated once for all the possible threads that can be created during the execution of the program.

This is not what the C++11 standard states. The relevant sections from C++11 standard (draft n3337):

  • 3.7.2 Thread storage duration, clause 1:

All variables declared with the thread_local keyword have thread storage duration. The storage for these entities shall last for the duration of the thread in which they are created. There is a distinct object or reference per thread, and use of the declared name refers to the entity associated with the current thread.

  • 7.1.1 Storage class specifiers, clause 4:

The thread_local specifier indicates that the named entity has thread storage duration (3.7.2). It shall be applied only to the names of variables of namespace or block scope and to the names of static data members. When thread_local is applied to a variable of block scope the storage-class-specifier static is implied if it does not appear explicitly.

Nowhere does it state that if an object is defined in the global namespace with thread_local that only a single instance of it will be created. An alternative example to that already posted by Jesse Good prints the unique address of each instance of the global object (see online demo):

#include <iostream>
#include <thread>
#include <vector>

struct S {};
thread_local S global_s;

int main()
{
    std::vector<std::thread> threads;
    for (int i = 0; i < 10; ++i)
        threads.push_back(std::thread([](){ std::cout << &global_s << '\n'; }));
    for (auto& t: threads) t.join();
}

Output:

0x4165993f
0x4205a93f
0x4485e93f
0x42a5b93f
0x4525f93f
0x45c6093f
0x4666193f
0x4706293f
0x43e5d93f
0x4345c93f
于 2013-07-04T14:17:57.037 回答
3

no matter if I declare the global object as thread_local

Did you try it out? I'm pretty sure that it will create a separate instance per thread.

See the following code on coliru:

struct S {
   int i = 0;
   S() {}
};

thread_local S global;

int main()
{
    std::thread t1([](){global.i = 1; std::cout << global.i << std::endl;});
    t1.join();
    std::cout << global.i << std::endl;
    std::thread t2([](){global.i = 2; std::cout << global.i << std::endl;});
    t2.join();
    std::cout << global.i << std::endl;
    std::thread t3([](){global.i = 3; std::cout << global.i << std::endl;});
    t3.join();
    std::cout << global.i << std::endl;
}

It outputs:

1
0
2
0
3
0
于 2013-07-04T13:42:19.987 回答