在一个函数调用中创建线程池,并从另一个函数调用来使用它

Creating a thread pool in one function call and using it from another function call

本文关键字:函数调用 另一个 线程 一个 创建      更新时间:2023-10-16

我有一个Fortran程序,它调用C++dll对10000组数据进行一些数学运算。这些数据集彼此完全独立。我本来打算创建一个线程池,然后向它发送任务。然而,对dll的调用将进行1000多次(每次调用将处理10000组数据)。

我的问题是:当我在第一次调用dll时创建线程池时,dll中的函数返回后,这个线程池会发生什么?第二个调用(以及其余998个调用)是否可以访问在第一个调用期间创建的池。

如果设置正确,您确实可以使用相同的线程池。

在FORTRAN->C++调用线程的堆栈上创建的对象将在堆栈展开并将控制返回FORTRAN时被销毁,因此在该堆栈上拥有线程池管理数据不是一个好主意。然而,您可以:

  • 启动另一个创建线程池管理数据/对象的线程,或者
  • 在堆上分配(使用new)以将生存期与FORTRAN->C++调用解耦

后者可能更简单、更干净。。。指向管理线程池的堆对象/数据的指针可以返回到FORTRAN,并用作未来调用的"句柄",指示应该使用相同的线程池。

如果你可以控制fortran代码,你可以通过使用3个函数而不是一个来为自己保存一些状态的秘密隐藏。

someStateHandle PrepareBackgroundWork();
// Then you do your actual call series...
DoMyMath(someStateHandle, args...);
// And when you are done with all that, you call
FinalizeBackgroundWork(someStateHandle);

如果你不能控制fortran代码,你将不得不决定你想要保留什么(线程池的东西或线程句柄和一些同步对象),然后惰性地初始化它们。

struct MyWorkerContext
{
    size_t numberOfWorkerThreads;
    std::vector<HANDLE> workerHandles; 
    // ...
};
static MyWorkerContext* s_context = NULL; // Sorry - looks like a singleton to me.
void DoMyMath( args..)
{
    if(NULL == s_context) InitializeContext();
    if( NULL != s_context )
    {
         // do the calculations using all that infrastructure.
    }
}
E.g. in DLLMain() or hopefully earlier: clean up s_context.

最后,我认为有一个"默认线程池",您也可以使用它,而不是创建自己的线程池。