Как и в случае с<wait_first_outcome()
>, мы можем<wait_all_values()
>и<wait_all_values_source()
>путем прохождения<future<
T>
>вместо простого<T
>.
<wait_all_until_error()
>всплывает<future<T>
>и называет его<future::get()
>:
template< typename Fn, typename ... Fns >
std::vector< typename std::result_of< Fn() >::type >
wait_all_until_error( Fn && function, Fns && ... functions) {
std::size_t count( 1 + sizeof ... ( functions) );
typedef typename std::result_of< Fn() >::type return_t;
typedef typename boost::fibers::future< return_t > future_t;
typedef std::vector< return_t > vector_t;
vector_t results;
results.reserve( count);
std::shared_ptr<
boost::fibers::unbounded_channel< future_t > > channel(
wait_all_until_error_source( std::forward< Fn >( function),
std::forward< Fns >( functions) ... ) );
future_t future;
while ( boost::fibers::channel_op_status::success == channel->pop( future) ) {
results.push_back( future.get() );
}
return results;
}
Например:
std::string thrown;
try {
std::vector< std::string > values = wait_all_until_error(
[](){ return sleeper("waue_late", 150); },
[](){ return sleeper("waue_middle", 100, true); },
[](){ return sleeper("waue_early", 50); });
} catch ( std::exception const& e) {
thrown = e.what();
}
std::cout << "wait_all_until_error(fail) threw '" << thrown
<< "'" << std::endl;
Естественно, это усложняет API<wait_all_until_error_source()
>. Абонент должен получить<future<
T>
>и назвать его<get()
>методом. Конечно, можно было бы вернуть façade над потребительским концом канала, который неявно выполнял бы<get()
>и возвращал бы простой<T
>(или бросок).
Реализация такая же, как и вы ожидаете. Обратите внимание, что мы можем использовать<wait_first_outcome_impl()
>, передавая<nchannel<T>
>, а не<unbounded_channel<T>
>.
template< typename Fn, typename ... Fns >
std::shared_ptr<
boost::fibers::unbounded_channel<
boost::fibers::future<
typename std::result_of< Fn() >::type > > >
wait_all_until_error_source( Fn && function, Fns && ... functions) {
std::size_t count( 1 + sizeof ... ( functions) );
typedef typename std::result_of< Fn() >::type return_t;
typedef boost::fibers::future< return_t > future_t;
typedef boost::fibers::unbounded_channel< future_t > channel_t;
auto channelp( std::make_shared< channel_t >() );
auto ncp( std::make_shared< nchannel< future_t > >( channelp, count) );
wait_first_outcome_impl< return_t >( ncp,
std::forward< Fn >( function),
std::forward< Fns >( functions) ... );
return channelp;
}
Например:
typedef boost::fibers::future< std::string > future_t;
std::shared_ptr< boost::fibers::unbounded_channel< future_t > > channel =
wait_all_until_error_source(
[](){ return sleeper("wauess_third", 150); },
[](){ return sleeper("wauess_second", 100); },
[](){ return sleeper("wauess_first", 50); });
future_t future;
while ( boost::fibers::channel_op_status::success == channel->pop( future) ) {
std::string value( future.get() );
std::cout << "wait_all_until_error_source(success) => '" << value
<< "'" << std::endl;
}