c++vectorpthreads

How to return a vector from a thread in C++?


struct Data_1{

    
    string stm;
    ...
};

void get_child_tree_thread(void *arguments){    

 vector<Data_1> v_result;

  Data_1 a,a1;

  a.stm = "1234";

  a1.stm = "1235";
  
  v_result.push_back(a);

  v_result.push_back(a1);
  
  std::vector<Data_1>* vec = new std::vector<Data_1>(v_result.size());
    
  vec->assign(v_result.begin(),v_result.end()); 
  
  **return vec;**
 
}
int main(void)
{
    
    if (pthread_create(&thread,NULL, get_child_tree_thread,NULL)){
            cerr << "create thread  error" << endl;         
            cout << "create thread fail->"  << endl;
            exit(0);
        }
    sleep(3);
    void *threadResult = NULL;
    cout << "main 3" << endl;
    pthread_join(thread, &threadResult);
        
    std::vector<Data_1> *v_child_out = (std::vector<Data_1> *)((std::vector<Data_1>* )threadResult);
    
    cout << "p join v_child_out size" << v_child_out->size()<<  endl;       
        
  
}

how to cast vector properly? ->

std::vector<Data_1> *v_child_out = (std::vector<Data_1> *)((std::vector<Data_1>* )threadResult);

cout << "p join v_child_out size" << v_child_out->size()<<  endl;       

Solution

  • Your get_child_tree_thread() function is declared wrong. It needs to return void* not void (your compiler should have caught that mistake):

    void* get_child_tree_thread(void *arguments){
      ...
      auto* vec = new std::vector<Data_1>(...);
      ...
      return vec; 
    }
    

    Then, your typecast of threadResult can be simplified by removing the redundant cast (you are casting twice when once will suffice):

    int main()
    {
        ...
    
        void *threadResult = nullptr;
        pthread_join(thread, &threadResult);
    
        auto *v_child_out = static_cast<std::vector<Data_1>*>(threadResult);
        ...
        delete v_child_out;
    }
    

    You can then simplify the code further by passing a pointer to a vector object to the thread via its input argument, and get rid of new entirely, eg:

    void* get_child_tree_thread(void *argument){
    
      auto *v_result = static_cast<std::vector<Data_1>*>(argument);
    
      ...
      v_result->push_back(...);
      ...
    
      return nullptr;
    }
    
    int main()
    {
        std::vector<Data_1> v_child_out;
    
        if (pthread_create(&thread, nullptr, get_child_tree_thread, &v_child_out)){
            std::cerr << "create thread error" << std::endl;
            std::cout << "create thread fail->" << std::endl;
            return 0;
        }
        sleep(3);
    
        std::cout << "main 3" << std::endl;
        pthread_join(thread, nullptr);
    
        std::cout << "p join v_child_out size" << v_child_out.size() << std::endl;
    }
    

    Now, that said, you should not be using pthreads at all. Use C++'s native std::thread instead:

    #include <thread>
    
    void get_child_tree(std::vector<Data_1> &v_result){
      ...  
      v_result.push_back(...);
      ...
    }
    
    int main()
    {
        std::vector<Data_1> v_child_out;
    
        std::thread thd(get_child_tree, std::ref(v_child_out));
        sleep(3);
    
        std::cout << "main 3" << std::endl;
        thd.join();
        
        std::cout << "p join v_child_out size" << v_child_out.size() << std::endl;         
    }
    

    Or even std::async() and std::future:

    #include <future>
    
    std::vector<Data_1> get_child_tree(){
    
      std::vector<Data_1> v_result;
    
      ...  
      v_result.push_back(...);
      ...
    
      return v_result;
    }
    
    int main()
    {
        auto f = std::async(std::launch::async, get_child_tree);
    
        sleep(3);
    
        std::cout << "main 3" << std::endl;
    
        auto v_child_out = f.get();
    
        std::cout << "p join v_child_out size" << v_child_out.size() << std::endl;         
    }