For the thread in C++, an id is an object with data members and member functions. This id object has a text code, which is what people normally consider as the id. The id object uses the << operator to send the text code to the cout object (terminal). The id object and its text code are different from when the thread is not running to when it is running.
The thread is a class in which the id object is a data member. The id object can be obtained with the following syntax:
The syntax “thread::get_id()” can be used when the thread is not running and also when the thread is running, and it will give different objects and corresponding text codes for the two different situations.
A way to obtain the thread id within the thread body while it is running is to use the syntax:
All threads that are running have different id objects and corresponding text codes. All threads that are not running have the same corresponding text code for the same program. Though they have the same text code, all threads that are not running have different id objects because objects are references and not pointers.
A thread that is running is referred to as a thread-of-execution.
To compile a program of threads, with the g++ compiler, use a command similar to:
This article explains different ways of obtaining id’s of different threads in C++, beginning with a summary of what a thread is.
Article Content
Thread Summary
A thread is an enclosure of a top-level function. A thread is instantiated from the thread class. The name of the top-level function is an argument to the constructor function of the thread object. The main() function in C++ is also a top-level function. So the main() function behaves like the main thread. The following program shows two threads of which the main() function is one:
#include <thread>
using namespace std;
thread thr;
void fun() {
cout <<"This is line A." <<endl;
cout <<"This is line B." <<endl;
}
int main()
{
thr = thread(fun);
thr.join();
/* statements */
return 0;
}
The output is:
This is line B.
The top-level functions are fun() and main(). main() is like the main thread. The name of the top-level function, fun() is the argument for the constructor of the thread, thr, in the main function.
The program begins with the inclusion of the iostream library. This is followed by the inclusion of the thread library. The statement after that ensures that any name used in the program is of the standard namespace unless otherwise indicated.
Next, the thread thr is declared without a function call. The top-level function, fun() is then defined. Thereafter is the definition of the main() function. The first statement in main(), assigns the function, fun() to the thread, thr, as well as calling the function.
The second statement in main() is the join statement. If this statement is absent, the main thread may run to completion without the thread, thr running to its own completion. With this statement, at the point where the statement is typed, the main thread (function) halts (blocks), and allows the joined thread (thr) to execute to its completion; before the main thread continues to its own completion. An attempt to compile the program without the join statement should end up with an error message and no compilation.
When the thread is declared with the statement,
it is not a running thread; no function is running. However, when the thread, thr is given a function name as argument, as in,
it becomes a running thread. This statement is also a function call, for the function, fun().
After the join statement in the main function, the thread, thr has completed its execution, and it is no longer a running thread. At that state, its id is different from when it was running.
Obtaining Thread id
The following program shows the basic way of obtaining the thread id when the thread is not executing and also when it is executing:
#include <thread>
using namespace std;
thread thr;
void fun() {
cout <<"This is line A." <<endl;
thread::id idR = thr.get_id();
cout <<idR <<endl;
cout <<"This is line B." <<endl;
}
int main()
{
thread::id idD = thr.get_id();
cout <<idD <<endl; cout <<endl;
thr = thread(fun);
thr.join();
//cout <<thr.get_id() <<endl;
/* statements */
return 0;
}
The output of the author’s computer is:
This is line A.
140362842543872
This is line B.
thr is a global variable. It is used within the function body of the thread thr, in the statement:
The variable holding the thread object obtained is idR. Though id is an instantiated object, it is also a member of the thread class. So the declaration of idR has to be:
with the semicolon. The next statement after this one is:
The operator, <<obtains and inserts the text version of the id into cout (terminal). Note: the id in this situation is obtained while the thread is running (executing). The statement that obtains the id while the thread is not executing is
in the main() function. It is the same as the one in the thread executing function, except for the receiving variable, idD. This statement is executed before the thread, thr is assigned a function. The text id (code) for this thread that is not executing is:
During the main() function execution, the thread thr has finished its own execution after the join statement. And so, “thr.get_id()” should be able to return the id of the thread when it is not executing. As of now, the C++ program compiled with g++ has difficulty obtaining the id of the thread that has run to completion. That is why the id statement after the join statement in the code above is commented off.
Use of this_thread::get_id()
“this_thread::” is coded within the thread of execution (function). It represents the thread that is currently running. It can be followed by a function for the thread, such as get_id(), to have
to obtain the running thread’s id of the thread, which is different from the id when the thread is not running.
“this_thread::” is used within a thread’s function body. The following program illustrates this for the thread, thr:
#include <thread>
using namespace std;
thread thr;
void fun() {
cout <<"This is line A." <<endl;
thread::id idR = this_thread::get_id();
cout <<idR <<endl;
cout <<"This is line B." <<endl;
}
int main()
{
thread::id idD = thr.get_id();
cout <<idD <<endl; cout <<endl;
thr = thread(fun);
thr.join();
return 0;
}
The output of the author’s computer is:
This is line A.
140199206078208
This is line B.
Note that the thread name, thr, was not used within the thread function body, in this case.
Conclusion
There are two forms of the thread ID in C++. The ID when the thread is executing is different from the ID when the thread is not executing. An ID (for IDentifier) is what identifies something. In C++, the name for the thread ID is id, in lowercase. This is a data member in the thread class. It is not a fundamental object. It is instantiated from its own class, of the namespace, thread::id. Though the id is an object, it has a corresponding text form. The text form can be inserted into the cout object (terminal) with the C++ insertion operator, <<.
Each thread has two different IDs: One when the thread is running; and the other when the thread is not running. When the thread is not running, the text form for the id is different from the text form when the thread is running for the same thread.
The C++ specification has various ways of getting the thread id. However, as of now, with the g++ compiler, the only ways to get the id are from the expressions: “threadObject.get_id()” and “this_thread::get_id()”. “this_thread::get_id()” is used within the executing thread’s function body, where “this_thread::” refers to the thread currently running. A running thread is referred to as a thread of execution.