Boost C++ Libraries of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards


when_all, simple completion

For the case in which we must wait for all task functions to complete — but we don't need results (or expect exceptions) from any of them — we can write wait_all_simple() that looks remarkably like wait_first_simple(). The difference is that instead of our Done class, we instantiate a barrier and call its barrier::wait().

We initialize the barrier with (count+1) because we are launching count fibers, plus the wait() call within wait_all_simple() itself.

template< typename ... Fns >
void wait_all_simple( Fns && ... functions) {
    std::size_t count( sizeof ... ( functions) );
    // Initialize a barrier(count+1) because we'll immediately wait on it. We
    // don't want to wake up until 'count' more fibers wait on it. Even though
    // we'll stick around until the last of them completes, use shared_ptr
    // anyway because it's easier to be confident about lifespan issues.
    auto barrier( std::make_shared< boost::fibers::barrier >( count + 1) );
    wait_all_simple_impl( barrier, std::forward< Fns >( functions) ... );

As stated above, the only difference between wait_all_simple_impl() and wait_first_simple_impl() is that the former calls barrier::wait() rather than Done::notify():

template< typename Fn, typename ... Fns >
void wait_all_simple_impl( std::shared_ptr< boost::fibers::barrier > barrier,
                           Fn && function, Fns && ... functions) {
                []( std::shared_ptr< boost::fibers::barrier > & barrier,
                    typename std::decay< Fn >::type & function) mutable {
                std::forward< Fn >( function)
    wait_all_simple_impl( barrier, std::forward< Fns >( functions) ... );

You might call it like this:

        [](){ sleeper("was_long",   150); },
        [](){ sleeper("was_medium", 100); },
        [](){ sleeper("was_short",   50); });

Control will not return from the wait_all_simple() call until the last of its task functions has completed.