-1

I'm trying to implement my own version of parallel for using https://github.com/Fdhvdu/ThreadPool as the backend thread pool

I'm splitting up the task to several slices and launching a thread with the following function:

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

The problem I'm having is how to pass this Callable to the thread pool

The relevant part is:

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

But I keep getting compilation errors. The error is:

...\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)
]

The interface for add is

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

I'm using Visual Studio 2017 Community 15.4 with /std:c++17

La bla bla
  • 8,558
  • 13
  • 60
  • 109
  • There is a `c++11` tag in the question, but you use `/std:c++17`? Since you are using VS2017, have you tried using functions with [Execution policies](https://en.cppreference.com/w/cpp/experimental/parallelism)? – Ted Lyngmo Feb 18 '19 at 19:13
  • the `c++17` comment was because the ThreadPool library linked stated that it needs c++17 so I wanted to avoid comments that states that VS2017 15.4 doesn't fully support c++17. – La bla bla Feb 18 '19 at 19:36

1 Answers1

2

launchRange is a function template not a function.

You cannot pass a function template as a function unless overload resolution has completed. That line doesn't trigger overload resolution.

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

the above is a lambda that acts a lot like launchRange template does, but it is an actual object, not just a template.

It still won't work because you don't pass add the id argument.

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

that will probably compile.

I don't particularly like that specific thread pool implementation. I mean, how many pointless pimpl layers can you have? How much pointless heap allocation? And, it passes by reference by default, which is a horrible idea when passing stuff to another thread.

I'd argue that taking arguments is a bad plan here. Avoid using them.

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

that also eliminates the need to create a auto launchRange = [] lambda as well. And errors end up being far easier to read.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • Thanks, It works after applying the lambda to `add`. Regarding your comment, I'm looking for a lightweight thread pool implementation. Can you recommend any? – La bla bla Feb 18 '19 at 19:35
  • @Lablabla [Here is a toy one](https://stackoverflow.com/a/53089760/1774667), like 40 lines of code? Replace `boost::optional` with `std::optional` in C++17. It could use some cleaning up, I can write a better one now, but I believe it is serviceable. – Yakk - Adam Nevraumont Feb 18 '19 at 19:41