A common approach for handling a set number of threads performing some task is to start X threads, and then let each thread pick it's "work" from a common queue. In a really simple case, you'd simply, instead of doing i+1
and i++
in the loop that creates the thread, let i
be a std::atomic<int>
, and do:
void some_thread_function()
{
for(;;)
{
int work_on = i.fetch_add(1); // "work_on = i++;"
if (work_on >= samples)
break;
... // do actual work
}
}
In a more complex case, you'd have a waitable queue that contains a more complex datatype to describe the "work" to be done.
This means you always have the "right" number of threads, and there is no overhead of creating/tearing down threads (if the threads run for quite some time (tenths of a second or longer), this is not an issue anyway, but for "short" runtimes it is quite possibly a factor.