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

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

本文关键字:工作 线程 返回 数据结构 执行 C++ 继续 现代      更新时间:2023-10-16

我需要启动工作线程,执行一些初始化,返回数据结构作为初始化结果并继续线程执行。仅使用现代 c++ 功能来实现此目的的最佳(或可能)代码是什么?请注意,启动的线程应继续执行(线程不会像往常一样终止)。遗憾的是,大多数解决方案都假定工作线程终止。

伪代码:

// 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
}

我认为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
}

尝试使用指针或对包含答案的数据结构的引用,以及 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();
}

当然,在实际代码中,您不会使用全局变量,而是通过指针或引用(或作为 SomeClass 的成员变量)将它们传递给工作线程函数,但您明白了这一点。