In this article we will create a vector thread and discuss things which we need to take care while using it.
Creating & Using vector of std::thread
Let’s Create a vector of std::thread objects i.e.
// Create a vector of threads std::vector<std::thread> vecOfThreads;
Now let’s create a std::function<> object that we will pass to thread object as thread function i.e.
// Create a function object std::function<void()> func = []() { //Do Some Important Work // ..... //Print Thread ID std::cout << "From Thread ID : "<<std::this_thread::get_id() << "\n"; };
Now let’s create 2 thread objects using this std::function objects i.e.
std::thread th1(func); std::thread th2(func);
Now, as std::thread objects are move only i.e. we can not copy them, only move them. Therefore, we need to move these 2 thread objects in vector i.e.
// Move thread objects to vector vecOfThreads.push_back(std::move(th1)); vecOfThreads.push_back(std::move(th2));
We can also push std::thread without specifically specifying std::move(), if we pass them as rvalue i.e.
// Add a Thread object to vector vecOfThreads.push_back(std::thread(func));
As vector contains various thread objects, so when this vector object is destructed it will call destructor of all the thread objects in the vector.
If any of the destructed thread object is joinable and not joined then std::terminate() will be called from its destructor. Therefore its necessary to join all the joinable threads in vector before vector is destructed i.e.
// Iterate over the thread vector for (std::thread & th : vecOfThreads) { // If thread Object is Joinable then Join that thread. if (th.joinable()) th.join(); }
Complete example is as follows,
#include <thread> #include <vector> #include <iostream> int main() { // Create a vector of threads std::vector<std::thread> vecOfThreads; // Create a function object std::function<void()> func = []() { //Do Some Important Work // ..... //Print Thread ID std::cout << "From Thread ID : "<<std::this_thread::get_id() << "\n"; }; // Add a Thread object to vector vecOfThreads.push_back(std::thread(func)); // Create 3 differet thread objects std::thread th1(func); std::thread th2(func); std::thread th3(func); // Move all three thread objects to vector vecOfThreads.push_back(std::move(th1)); vecOfThreads.push_back(std::move(th2)); vecOfThreads.push_back(std::move(th3)); // Do some important work in main thread. /** Wait for all the threads in vector to join **/ // Iterate over the thread vector for (std::thread & th : vecOfThreads) { // If thread Object is Joinable then Join that thread. if (th.joinable()) th.join(); } return 0; }
Output:
From Thread ID : 140261435352832 From Thread ID : 140261452138240 From Thread ID : 140261426960128 From Thread ID : 140261443745536
To compile the above example in linux use,
g++ –std=C++11 example.cpp -lpthread
Use vector<std::thread> cautiously
std::vector<std::thread> vecOfThreads;
Move only vector of thread
As thread objects are move only objects, therefore we can not copy vector of thread objects to an another of vector of thread i.e.
// Can not copy vector of thread , COMPILE TIME ERROR std::vector<std::thread> newVecThreads = vecOfThreads;
It will not compile
Therefore, we can only move vector of thread to an another vector thread i.e.
// Can Only move vector of thread std::vector<std::thread> newVecThreads = std::move(vecOfThreads);
Changing contents of vector of thread
If we will try to change the value of any element in vector of thread directly i.e.
//Destructor of already existing thread object will call terminate vecOfThreads[1] = std::move(th4);
It will crash our application, because on replacing a thread object inside the vector, destructor of existing thread object will be called and we haven’t joined that object yet. So, it call terminate in its destructor. So, to replace a thread object in vector, we first need to join the existing object and then replace it with new one i.e.
// First join the existing object if(vecOfThreads[1].joinable()) vecOfThreads[1].join(); // Replace the joined thread object vecOfThreads[1] = std::move(th4);
Complete example is as follows,
#include <thread> #include <mutex> #include <vector> #include <iostream> #include <chrono> int main() { // Create a vector of threads std::vector<std::thread> vecOfThreads; // Create a function object std::function < void() > func = []() { //Do Some Important Work // Sleep for 1 second std::this_thread::sleep_for (std::chrono::seconds(1)); //Print Thread ID std::cout << "From Thread ID : "<<std::this_thread::get_id() << "\n"; }; // Add a Thread object to vector vecOfThreads.push_back(std::thread(func)); // Create 3 differet thread objects std::thread th1(func); std::thread th2(func); std::thread th3(func); // Move all three thread objects to vector vecOfThreads.push_back(std::move(th1)); vecOfThreads.push_back(std::move(th2)); vecOfThreads.push_back(std::move(th3)); std::thread th4(func); //Destructor of already existing thread object will call terminate //vecOfThreads[1] = std::move(th4); // First join the existing object if (vecOfThreads[1].joinable()) vecOfThreads[1].join(); // Replace the joined thread object vecOfThreads[1] = std::move(th4); // Can not copy vector of thread , COMPILE TIME ERROR //std::vector<std::thread> newVecThreads = vecOfThreads; // Can Only move vector of thread std::vector<std::thread> newVecThreads = std::move(vecOfThreads); /** Wait for all the threads in vector to join **/ // Iterate over the thread vector for (std::thread & th : newVecThreads) { // If thread Object is Joinable then Join that thread. if (th.joinable()) th.join(); } return 0; }
Output:
From Thread ID : 140642994353920 From Thread ID : 140643002746624 From Thread ID : 140642985961216 From Thread ID : 140643011139328 From Thread ID : 140642977568512
To compile the above example in linux use,
Pointers in C/C++ [Full Course]
g++ –std=C++11 example.cpp -lpthread
Thanks for this tutorial, it’s the first tutorial I could find that resolved my issue. What i was missing was the std::move() function and I wasn’t able to find it for months now.
Thank you!