Для случая, в котором мы должны ждатьвсефункции задачи для завершения — но нам не нужны результаты (или ожидаем исключения) от любого из них — мы можем написать<wait_all_simple()>, который выглядит удивительно как<wait_first_simple()>. Разница в том, что вместо нашего<Done>класс, мы создаем<barrier>и назвать его<barrier::wait()>.
Мы начинаем<barrier>с<(count+1)>, потому что мы запускаем<count>волокна, плюс<wait()>вызов внутри<wait_all_simple()>.
template< typename ... Fns >
void wait_all_simple( Fns && ... functions) {
std::size_t count( sizeof ... ( functions) );
auto barrier( std::make_shared< boost::fibers::barrier >( count + 1) );
wait_all_simple_impl( barrier, std::forward< Fns >( functions) ... );
barrier->wait();
}
Как было сказано выше, единственное различие между<wait_all_simple_impl()>и<wait_first_simple_impl()>заключается в том, что первые призывают<barrier::wait()>, а не<Done::notify()>:
template< typename Fn, typename ... Fns >
void wait_all_simple_impl( std::shared_ptr< boost::fibers::barrier > barrier,
Fn && function, Fns && ... functions) {
boost::fibers::fiber(
std::bind(
[]( std::shared_ptr< boost::fibers::barrier > & barrier,
typename std::decay< Fn >::type & function) mutable {
function();
barrier->wait();
},
barrier,
std::forward< Fn >( function)
)).detach();
wait_all_simple_impl( barrier, std::forward< Fns >( functions) ... );
}
Вы можете назвать это так:
wait_all_simple(
[](){ sleeper("was_long", 150); },
[](){ sleeper("was_medium", 100); },
[](){ sleeper("was_short", 50); });
Контроль не вернется с вызова<wait_all_simple()>до тех пор, пока не завершится последняя из его рабочих функций.