MYtry
MYtry

Reputation: 7

c++ multithreading return value

I am using 3 threads to chunk a for loop, and the 'data' is a global array so I want to lock that part in 'calculateAll' function,

 std::vector< int > calculateAll(int ***data,std::vector<LineIndex> indexList)
{
  std::vector<int> v_a=std::vector<int>();
  for(int a=0;a<indexList.size();a++)
  {         
    mylock.lock();
    v_b.push_back(/*something related with data*/); 
    mylock.unlock();
    v_a.push_back(a); 
  }
  return v_a;
}
 for(int i=0;i<3;i++)
    {
      int s =firstone+i*chunk;
      int e = ((s+chunk)<indexList.size())? (s+chunk) : indexList.size();
      t[i]=std::thread(calculateAll,data,indexList,s,e);      
    }
    for (int i = 0; i < 3; ++i)
    {
      t[i].join();
    }

my question is, how can I get the return value which is a vector from each thread and then combine them together? The reason I want to do that is because if I declare ’v_a‘ as a global vector, when each thread trys to push_back their value in this vector 'v_a' it will be some crash(or not?).So I am thinking to declare a vector for each of the thread, then combine them into a new vector for further use( like I do it without thread ).

Or is there some better methods to deal with that concurrency problem? The order of 'v_a' does not matter.

I appreciate for any suggestion.

Upvotes: 2

Views: 2411

Answers (2)

WhiZTiM
WhiZTiM

Reputation: 21576

First of all, rather than the explicit lock() and unlock() seen in your code, always use std::lock_guard where possible. Secondly, it would be better you use std::futures to this thing. Launch each thread with std::async then get the results in another loop while aggregating the results at the same time. Like this:

using Vector = std::vector<int>;
using Future = std::future<Vector>;
std::vector<Future> futures;

for(int i=0;i<3;i++)
{
    int s =firstone+i*chunk;
    int e = ((s+chunk)<indexList.size())? (s+chunk) : indexList.size();
    auto fut = std::async(std::launch::async, calculateAll, data, indexList, s, e);
    futures.push_back( std::move(fut) );      
}

//Combine the results
std::vector<int> result;
for(auto& fut : futures){    //Iterate through in the order the future was created
    auto vec = fut.get();    //Get the result of the future
    result.insert(result.end(), vec.begin(), vec.end());  //append it to results in order
}

Here is a minimal, complete and working example based on your code - which demonstrates what I mean: Live On Coliru

Upvotes: 3

John Major
John Major

Reputation: 36

Create a structure with a vector and a lock. Pass an instance of that structure, with the lock pre-locked, to each thread as it starts. Wait for all locks to become unlocked. Each thread then does its work and unlocks its lock when done.

Upvotes: 0

Related Questions