Skip to content

Commit

Permalink
Adding split_future for std::vector
Browse files Browse the repository at this point in the history
- this fixes #2940
  • Loading branch information
hkaiser committed Oct 10, 2017
1 parent 8ecf819 commit 738dec5
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
56 changes: 56 additions & 0 deletions hpx/lcos/split_future.hpp
Expand Up @@ -40,6 +40,27 @@ namespace hpx
template <typename ... Ts>
inline tuple<future<Ts>...>
split_future(future<tuple<Ts...> > && f);

/// The function \a split_future is an operator allowing to split a given
/// future of a sequence of values (any std::vector)
/// into a std::vector of futures where each future represents
/// one of the values from the original std::vector. In some sense this
/// function provides the inverse operation of \a when_all.
///
/// \param f [in] A future holding an arbitrary sequence of values stored
/// in a std::vector.
/// \param size [in] The number of elements the vector will hold once the
/// input future has become ready
///
/// \return Returns a std::vector of futures, where each future refers
/// to the corresponding value in the input parameter. All of
/// the returned futures become ready once the input future has
/// become ready. If the input future is exceptional, all output
/// futures will be exceptional as well.
///
template <typename T>
inline std::vector<future<T>>
split_future(future<std::vector<T> > && f, std::size_t size);
}

#else // DOXYGEN
Expand All @@ -65,6 +86,7 @@ namespace hpx
#include <exception>
#include <type_traits>
#include <utility>
#include <vector>

///////////////////////////////////////////////////////////////////////////////
namespace hpx { namespace lcos
Expand Down Expand Up @@ -217,6 +239,12 @@ namespace hpx { namespace lcos
try {
typedef typename traits::future_traits<T>::type result_type;
result_type* result = state->get_result();
if (i >= result->size())
{
HPX_THROW_EXCEPTION(length_error,
"split_continuation::on_ready",
"index out of bounds");
}
this->base_type::set_value(std::move((*result)[i]));
}
catch (...) {
Expand Down Expand Up @@ -270,6 +298,19 @@ namespace hpx { namespace lcos

return result;
}

template <typename T, typename Future>
inline std::vector<hpx::future<T> >
split_future_helper_vector(Future && f, std::size_t size)
{
std::vector<hpx::future<T> > result;
result.reserve(size);

for (std::size_t i = 0; i != size; ++i)
result.push_back(extract_future_array<T>(i, f));

return result;
}
}

///////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -352,6 +393,21 @@ namespace hpx { namespace lcos
result[0] = hpx::make_future<void>(std::move(f));
return result;
}

///////////////////////////////////////////////////////////////////////////
template <typename T>
HPX_FORCEINLINE std::vector<hpx::future<T> >
split_future(hpx::future<std::vector<T> > && f, std::size_t size)
{
return detail::split_future_helper_vector<T>(std::move(f), size);
}

template <typename T>
HPX_FORCEINLINE std::vector<hpx::future<T> >
split_future(hpx::shared_future<std::vector<T> > && f, std::size_t size)
{
return detail::split_future_helper_vector<T>(std::move(f), size);
}
}}

namespace hpx
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/lcos/split_future.cpp
Expand Up @@ -152,6 +152,27 @@ void test_split_future_array()
HPX_TEST_EQ(result[2].get(), 44);
}

///////////////////////////////////////////////////////////////////////////////
std::vector<int> make_vector_slowly()
{
hpx::this_thread::sleep_for(std::chrono::milliseconds(100));
return std::vector<int>{{42, 43, 44}};
}

void test_split_future_vector()
{
hpx::lcos::local::futures_factory<std::vector<int>()> pt(
make_vector_slowly);
pt.apply();

std::vector<hpx::future<int> > result =
hpx::split_future(pt.get_future(), 3);

HPX_TEST_EQ(result[0].get(), 42);
HPX_TEST_EQ(result[1].get(), 43);
HPX_TEST_EQ(result[2].get(), 44);
}

///////////////////////////////////////////////////////////////////////////////
int hpx_main(int argc, char* argv[])
{
Expand All @@ -165,6 +186,8 @@ int hpx_main(int argc, char* argv[])
test_split_future_array0();
test_split_future_array();

test_split_future_vector();

hpx::finalize();
return hpx::util::report_errors();
}
Expand Down

0 comments on commit 738dec5

Please sign in to comment.