...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
We would be remiss to ignore the case in which the various task functions have distinct return types. That means that the value returned by the first of them might have any one of those types. We can express that with Boost.Variant.
To keep the example simple, we'll revert to pretending that none of them
can throw an exception. That makes wait_first_value_het()
strongly resemble wait_first_value()
.
We can actually reuse wait_first_value_impl()
,
merely passing boost::variant<T0, T1, ...>
as the queue's value type rather
than the common T
!
Naturally this could be extended to use wait_first_success()
semantics instead.
// No need to break out the first Fn for interface function: let the compiler // complain if empty. // Our functions have different return types, and we might have to return any // of them. Use a variant, expanding std::result_of<Fn()>::type for each Fn in // parameter pack. template< typename ... Fns > boost::variant< typename std::result_of< Fns() >::type ... > wait_first_value_het( Fns && ... functions) { // Use buffered_channel<boost::variant<T1, T2, ...>>; see remarks above. typedef boost::variant< typename std::result_of< Fns() >::type ... > return_t; typedef boost::fibers::buffered_channel< return_t > channel_t; auto chanp( std::make_shared< channel_t >( 64) ); // launch all the relevant fibers wait_first_value_impl< return_t >( chanp, std::forward< Fns >( functions) ... ); // retrieve the first value return_t value( chanp->value_pop() ); // close the channel: no subsequent push() has to succeed chanp->close(); return value; }
It might be called like this:
boost::variant< std::string, double, int > result = wait_first_value_het( [](){ return sleeper("wfvh_third", 150); }, [](){ return sleeper(3.14, 100); }, [](){ return sleeper(17, 50); }); std::cout << "wait_first_value_het() => " << result << std::endl; assert(boost::get< int >( result) == 17);