Multithreading in C++

Multithreading in C++

Introduction :

The std::thread class was introduced in C++ 11 to facilitate multithreading. POSIX (Pthread thread ) library in C or Win32 threads (CreateThread AfxBeginThread) in windows were used to create threads prior to class std::thread.

There are a number of ways through which users can create threads using std::thread.

A callable can be one of the three types.:

1: Function Pointer.
2: Function object.
3:Lambda function.
4: Function object by passing object reference.

#include <thread>
#include <chrono>
#include <iostream>
using namespace std;

class FunctionObject
{
    public:
    void operator()() const
    {
        cout<<"Thread cretation: Functional object."<<endl;
    }

    void fun1()
    {
        cout<<"FunctionObject::fun1"<<endl;
    }
};
void work()
{
	cout<<"Thread cretation: Executing function."<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
    //Type 1: Function pointer
    std::thread t1(work);
    t1.join();

    //Type 2:  Function object
    FunctionObject objFunctionObject;
    std::thread t2(objFunctionObject);
    t2.join();

    // thread executing through lambda function
    std::thread t3([] {std::cout << "Thread cretation: Lamda Expression" << std::endl; });
    t3.join();

    //Function object by passing object reference
    std::thread t4 ( &FunctionObject::fun1, ref(objFunctionObject));
    t4.join();

     return 0;
}

Output:

Thread cretation: Executing function.
Thread cretation: Functional object.
Thread cretation: Lamda Expression
FunctionObject::fun1

Thread Class member functions

 FunctionDescription
1get_id   Member function to get thread id   
2joinableMember function to check if joinable   
3joinMember function to join a thread   
4detachMember function to detach thread   
5swapMember function to swap threads   
6native_handleMember function to get native handle of a thread  
7hardware_concurrencyMember function to  [static] detect hardware concurrency   

Note:

The lifetime of the created thread ends with its callable unit. There are two options.
1: wait (t.join()) until its child is done.
2: detach (t.detach()) child from parent. Once detach, cannot rejoin.

Example :

#include <thread>
#include <chrono>
#include <iostream>
using namespace std;

void work()
{
this_thread::sleep_for(chrono::milliseconds(500));
cout<<"Thread cretation: Executing function."<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
    //detach
    std::thread t1(work);
    t1.detach();


    //join, joinable, native_handle, hardware_concurrency 
    std::thread t2([] {std::cout << "Thread cretation: Lamda Expression" << std::endl; }); 
   

    std::cout <<"Before - Joinable: "<< t2.joinable()<<endl;
    t2.join();
    std::cout <<"After -  Joinable: "<< t2.joinable()<<endl;


    std::cout <<"t2:: native_handle: "<< t2.native_handle()<<endl;
    std::cout <<"t2:: hardware_concurrency: "<<                 t2.hardware_concurrency()<<endl;


    thread t3;
    t2.swap(t3);
    std::cout <<"t2:: after swap: native_handle: "<< t2.native_handle()<<endl;
    std::cout <<"t3 :: after swap: native_handle: "<< t3.native_handle()<<endl;


    return 0;
}

Output:

Thread cretation: Lamda Expression
Before – Joinable: 1
After – Joinable: 0
t2:: native_handle: 00000140
t2:: hardware_concurrency: 4
t2:: after swap: native_handle: CCCCCCCC
t3 :: after swap: native_handle: 00000140