Seba92
Seba92

Reputation: 455

Wait for all threads in C++

I'm using the construct "thread" in C++ and I create a variable number of thread in a recursive function. I want the main thread to wait for all of them. How can I do it without WaitForMultipleObjects ?

Upvotes: 17

Views: 37984

Answers (5)

Gunnar Nilsson
Gunnar Nilsson

Reputation: 1

Simpler!?

Use a simple atomic global counter:

using namespace std;

atomic_ullong numThreads = 0;

At start of thread function's:

numThreads++;

In all return from thread function's:

numThreads--;

Waiting:

while (numThreads)
{
    Sleep(100);
}

There is a tiny flaw here, if wait loop starts before any thread function has incremented. This could be eliminated by wait for an event after creating threads, signaled after the increment.

Upvotes: 0

M.L.
M.L.

Reputation: 738

Take a look at example in cplusplus. Store threads with emplace_back() in vector. At the end you have loop with joins.

std::vector<std::thread> threads;
//create threads
for (int i=1; i<=10; ++i)
    threads.emplace_back(std::thread(increase_global,1000));
//wait for them to complete
for (auto& th : threads) 
    th.join();

Upvotes: 35

Galik
Galik

Reputation: 48645

I don't know the specifics of your situation but this kind of approach might be useful to you:

using thread_vec = std::vector<std::thread>;

void batch_process(int n)
{
    static std::mutex mtx;
    std::lock_guard<std::mutex> lock(mtx);
    std::cout << "process: " << n << '\n';
}

void recursive(thread_vec& tv, int n)
{
    // do some stuff
    tv.emplace_back(batch_process, n);

    if(n > 0)
        recursive(tv, n - 1);
}

int main(int, char* argv[])
{
    thread_vec tv;

    recursive(tv, 3);

    for(auto&& t: tv)
        t.join();
}

Output:

process: 1
process: 0
process: 2
process: 3

Upvotes: 1

Elkvis
Elkvis

Reputation: 739

You could also use boost thread_group. It only works with boost threads, but they have a nearly identical interface to std::thread (boost threads were the basis for threads in the standard library in C++11), and once you add all your threads to the thread_group, you simply call join_all on the group. You could also implement a thread_group class of your own, to work with std::thread, which would essentially do what has already been suggested, with a vector of thread objects or pointers, and waits on them in a loop.

Upvotes: 2

Min Lin
Min Lin

Reputation: 3197

Use an atomic variable as a counter, increase the variable when launching new thread, in the thread decrease the counter once the thread is completed.

int main() {
    mutex m;
    condition_variable cv;
    atomic<int> counter = 0;

    // .... in your recursive call
    // increase counter when launching thread.
    counter++;
    thread t([](){
        // do whatever
        lock_guard<mutex> lk(m);
        counter--;
        cv.notify_all();
    });
    t.detach(); // no need to join anymore.
    // .... end recursive call

    unique_lock<mutex> lock(m);
    cv.wait(lock, [](){ return counter == 0; });
}

Upvotes: 6

Related Questions