The class thread

Defining an object of type std::thread

The class std::thread, declared in the header file <thread>, is used to create and launch a logical thread. If its constructor receives a function address in argument, a thread executing the function is automatically launched. If the function takes arguments, we must give them to the constructor of the std::thread object.

Before a std::thread object get destroyed, we must call its method join. If the thread has not finished its execution yet, the effect of that method is to make the thread from which it is called, wait for the thread to finish.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <thread> #include <iostream> void func1() { std::cout << "void func1()\n"; } void func2(int a) { std::cout << "void func2(int a)\n"; } int main() { // Starts a logical thread executing the function 'func1'. std::thread thr(func1); // Starts a logical thread executing the function 'func2'. std::thread thr2(func2, 82); thr.join(); thr2.join(); return 0; }

A std::thread object is a link

A std::thread object is not the thread itself, but rather a link to the actual thread. As long as a std::thread object is linked to a thread, its method joinable returns true.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <thread> #include <iostream> void func() { std::cout << "From a secondary thread.\n"; } std::string stringFromBool(bool b) { return b ? "true" : "false"; } int main() { // Starts a logical thread executing the function 'func'. std::thread thr(func); std::thread thr2; std::cout << "Is 'thr2' linked to a thread? " << stringFromBool(thr2.joinable()) << ".\n"; std::cout << "Is 'thr' still linked to the thread? " << stringFromBool(thr.joinable()) << ".\n"; thr.join(); std::cout << "Is 'thr' still linked to the thread? " << stringFromBool(thr.joinable()) << ".\n"; return 0; }

If a std::thread object is destroyed while still being linked to a thread (Its method joinable returning true), its destructor will terminate the execution of the program. Even if the execution of the thread ended, the std::thread object is still linked to it, as long as its method join (Or detach) is not called.

Detaching the thread from a std::thread object

Like the method join, calling the method detach unlinks the std::thread object from the thread it created. However, unlike join, it does not wait for it to terminate. The thread continues its execution, on its own. When the main thread ends, all the running detached threads are automatically terminated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <thread> #include <iostream> void func() { while(true) std::cout << "Hello, from a secondary thread.\n"; } int main() { // Starts a logical thread executing the function 'func'. std::thread *thr = new std::thread(func); // Detaches the thread from the thread object. thr->detach(); // We can delete the std::thread object, because it has been unlinked from its thread. delete thr; // Executes some instructions so the main thread does not directly end. for(unsigned c = 0; c < 1000 * 1000; c++) {} return 0; }

Above, a secondary (non-ending) thread, printing to the console, is launched and detached from the std::thread object that created it. Once the main function ends, the detached thread is terminated (In its execution) by the operating system.

std::thread objects can not be copied

Thread objects can not be copied, but they can be moved. Also, using the method swap, we can swap the threads to which two std::thread objects are linked to.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <thread> #include <iostream> void func() { // Infinite loop. while(true); } std::string stringFromBool(bool b) { return b ? "true" : "false"; } int main() { std::thread thr1; // Moves the temporary thread object into 'thr1'. thr1 = std::thread(func); std::thread thr2; /* Error: std::thread objects can not be copied. */ // std::thread thr3 = thr1; std::cout << "thr1.joinable() == " << stringFromBool(thr1.joinable()) << ".\n"; std::cout << "thr2.joinable() == " << stringFromBool(thr2.joinable()) << ".\n\n"; // Swaps the thread linked to by the thread objects. thr1.swap(thr2); std::cout << "thr1.joinable() == " << stringFromBool(thr1.joinable()) << ".\n"; std::cout << "thr2.joinable() == " << stringFromBool(thr2.joinable()) << ".\n\n"; // Detaches the thread from the thread object. thr2.detach(); return 0; }

Retrieving the number of physical threads of the system

The method static unsigned std::thread::hardware_concurrency() returns the number of physical threads of the system. It may, however, be simply an approximation rather than the exact number.

1
2
3
4
5
6
7
8
9
10
#include<thread> #include <iostream> int main() { std::cout << "Number of physical threads (approximation): " << std::thread::hardware_concurrency() << ".\n"; return 0; }

When executed, the example above returned an accurate number of physical threads, as the system that executed it had a processor with 6 cores and 12 physical threads.