The few examples I've seen for std:barrier statically set the expected count.
std::barrier my_barrier(5);
The code I'm writing determines the number of threads to launch based on some factors at runtime. I'm struggling to come up with a clever way to construct the barrier at runtime after the number of threads to be launched is determined. Ideas appreciated.
Based on your comment:
If it's calculated it needs to be at a non-global scope. I don't see how to pass it as a local into the threads.
At some point the barrier has to be somewhat 'global'. Sure it doesn't make sense to put the barrier globally at e.g. file scope (deleted copy ctor and assignment operator) but it does make sense to put the barrier into the scope where the (dynamic amount of) workers will be invoked. Then the barrier has to be made local to the thread function. There are multiple ways to do that, it all depends whether you're using a lambda, function object or a function. So either via capture (lambda), as a class member (function object) or as argument (all).
e.g.
void invoke(int num_threads)
{
//completition function, will be invoked after all threads arrived at the barrier
auto on_completion = []() noexcept
{
std::cout << "done\n";
};
//construct barrier
std::barrier sync_point(num_threads, on_completion);
//work function (could be also a function object or a function, here we use a lambda)
auto work = [&sync_point /*either capture*/](/*or as argument*/)
{
//do something, then
//wait for all threads to arrive
sync_point.arrive_and_wait();
};
//construct workers
std::vector<std::jthread> threads; //dynamic array of threads
threads.reserve(num_threads); //alloc space
for (int n=0; n < num_threads; ++n) { //for each thread in list
//invoke the work function
threads.emplace_back(work /*, pass the function arguments here*/);
}
}
then
int main()
{
int n = 4;
invoke(n);
}