【问题标题】:ThreadPool pass function as argumentThreadPool 传递函数作为参数
【发布时间】:2019-02-18 19:00:32
【问题描述】:

我正在尝试实现我自己的并行版本,以使用 https://github.com/Fdhvdu/ThreadPool 作为后端线程池

我将任务分成几个部分并启动一个具有以下功能的线程:

template <typename Callable>
void launchRange(int id, Callable func, int k1, int k2)
{
    for (int k = k1; k < k2; k++) {
        func(k);
    }
}

我遇到的问题是如何将这个Callable 传递给线程池

相关部分是:

poolPtr->add(launchRange, func, i1, i2);

但我不断收到编译错误。错误是:

...\ithreadpoolitembase.hpp(36): error C2027: use of undefined type 'std::tuple<conditional<_Test,void(__cdecl *&)(int),_Ty>::type,conditional<_Test,int&,int>::type,conditional<_Test,int&,int>::type>'
with
[
    _Ty=void (__cdecl *)(int)
]

add的接口是

template<class Func,class ... Args>
inline thread_id add(Func &&func,Args &&...args);

我正在使用 Visual Studio 2017 Community 15.4 和 /std:c++17

【问题讨论】:

  • 问题中有c++11标签,但你使用/std:c++17?由于您使用的是VS2017,您是否尝试过使用Execution policies的函数?
  • c++17 评论是因为链接的 ThreadPool 库声明它需要 c++17,所以我想避免 cmets 声明 VS2017 15.4 不完全支持 c++17。跨度>

标签: c++ multithreading c++11 threadpool


【解决方案1】:

launchRange 是函数模板而不是函数。

除非重载决议完成,否则不能将函数模板作为函数传递。该行不会触发重载决议。

auto launchRange = [](int id, auto&& func, int k1, int k2)
{
  for (int k = k1; k < k2; k++) {
    func(k);
  }
};

上面是一个 lambda,其行为与 launchRange 模板非常相似,但它是一个实际对象,而不仅仅是一个模板。

它仍然不起作用,因为您没有将 add 传递给 id 参数。

poolPtr->add(launchRange, 77, func, i1, i2);

这可能会编译。

我不是特别喜欢那个特定的线程池实现。我的意思是,你可以有多少个毫无意义的 pimpl 层?多少无意义的堆分配?而且,它默认通过引用传递,这在将东西传递给另一个线程时是一个可怕的想法。

我认为在这里接受争论是一个糟糕的计划。避免使用它们。

poolPtr->add([=]{ launchRange(77, func, i1, i2); });

这也消除了创建auto launchRange = [] lambda 的需要。错误最终更容易阅读。

【讨论】:

  • 谢谢,在将 lambda 应用到 add 后它可以工作。关于您的评论,我正在寻找一个轻量级的线程池实现。可以推荐吗?
  • @Lablabla Here is a toy one,喜欢 40 行代码?在 C++17 中将 boost::optional 替换为 std::optional。它可能需要一些清理,我现在可以写一个更好的,但我相信它是有用的。
猜你喜欢
  • 1970-01-01
  • 2013-01-27
  • 2021-04-13
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
相关资源
最近更新 更多