简体   繁体   English

现代C ++。 从工作线程返回数据结构,继续执行

[英]Modern C++. Return data structure from working thread continuing its execution

I need to launch working thread, perform some initialization, return data structure as initialization result and continue thread execution. 我需要启动工作线程,执行一些初始化,返回数据结构作为初始化结果,然后继续执行线程。 What is the best (or possible) code to achieve this using modern c++ features only? 仅使用现代c ++功能实现此目标的最佳(或可能)代码是什么? Note, launched thread should continue its execution (thread does not terminated as usual). 注意,启动的线程应继续执行(线程不会照常终止)。 Unfortunately, most solutions assume worker thread termination. 不幸的是,大多数解决方案都假定工作线程终止。

Pseudo code: 伪代码:

// Executes in WorkerThread context 
void SomeClass::Worker_treadfun_with_init()
{
    // 1. Initialization calls...
    // 2. Pass/signal initialization results to caller
    // 3. Continue execution of WorkerThread    
}

// Executes in CallerThread context
void SomeClass::Caller()  
{
    // 1. Create WorkerThread with SomeClass::Worker_treadfun_with_init()" thread function
    // 2. Sleep thread for some initialization results 
    // 3. Grab results
    // 3. Continue execution of CallerThread
}

Try using a pointer or reference to the data structure with the answer in it, and std::condition_variable to let you know when the answer has been computed: 尝试使用指针或对包含答案的数据结构的引用,并使用std :: condition_variable告知您何时计算出答案:

#include <iostream>           
#include <thread>             
#include <mutex>              
#include <condition_variable> 

#include <chrono>
#include <vector>

std::vector<double> g_my_answer;
std::mutex g_mtx;
std::condition_variable g_cv;
bool g_ready = false;


void Worker_treadfun_with_init()
{
  //Do your initialization here
  {
     std::unique_lock<std::mutex> lck( g_mtx );
     for( double val = 0; val < 10; val += 0.3 )
       g_my_answer.push_back( val );

     g_ready = true;
     lck.unlock();
     g_cv.notify_one();
  }

  //Keep doing your other work..., here we'll just sleep
  for( int i = 0; i < 100; ++i )
  {
    std::this_thread::sleep_for( std::chrono::seconds(1) );
  }
}

void Caller()  
{
  std::unique_lock<std::mutex> lck(g_mtx);

  std::thread worker_thread = std::thread( Worker_treadfun_with_init );

  //Calling wait will cause current thread to sleep until g_cv.notify_one() is called.
  g_cv.wait( lck, [&g_ready](){ return g_ready; } ); 

  //Print out the answer as the worker thread continues doing its work
  for( auto val : g_my_answer )
    std::cout << val << std::endl;

  //Unlock mutex (or better yet have unique_lock go out of scope)
  // incase worker thread needs to lock again to finish
  lck.unlock();  

  //...

  //Make sure to join the worker thread some time later on.
  worker_thread.join();
}

Of course in actual code you wouldnt use global variables, and instead pass them by pointer or reference (or as member variables of SomeClass ) to the worker function, but you get the point. 当然,在实际代码中,您不会使用全局变量,而是通过指针或引用(或作为SomeClass成员变量)将它们传递给worker函数,但是您明白了。

I think std::future meets your requirements. 我认为std :: future符合您的要求。

// Executes in WorkerThread context 
void SomeClass::Worker_treadfun_with_init(std::promise<Result> &pro)
{
    // 1. Initialization calls...
    // 2. Pass/signal initialization results to caller
    pro.set_value(yourInitResult);
    // 3. Continue execution of WorkerThread    
}

// Executes in CallerThread context
void SomeClass::Caller()  
{
    // 1. Create WorkerThread with SomeClass::Worker_treadfun_with_init()" thread function
    std::promise<Result> pro;
    auto f=pro.get_future();
    std::thread([this,&pro](){Worker_treadfun_with_init(pro);}).detach();
    auto result=f.get();
    // 3. Grab results
    // 3. Continue execution of CallerThread
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM