File indexing completed on 2025-01-18 09:54:53
0001
0002
0003
0004
0005 #ifndef CPPCORO_WHEN_ALL_HPP_INCLUDED
0006 #define CPPCORO_WHEN_ALL_HPP_INCLUDED
0007
0008 #include <cppcoro/when_all_ready.hpp>
0009 #include <cppcoro/awaitable_traits.hpp>
0010 #include <cppcoro/is_awaitable.hpp>
0011 #include <cppcoro/fmap.hpp>
0012
0013 #include <cppcoro/detail/unwrap_reference.hpp>
0014
0015 #include <tuple>
0016 #include <functional>
0017 #include <utility>
0018 #include <vector>
0019 #include <type_traits>
0020 #include <cassert>
0021
0022 namespace cppcoro
0023 {
0024
0025
0026
0027 template<
0028 typename... AWAITABLES,
0029 std::enable_if_t<
0030 std::conjunction_v<is_awaitable<detail::unwrap_reference_t<std::remove_reference_t<AWAITABLES>>>...>,
0031 int> = 0>
0032 [[nodiscard]] auto when_all(AWAITABLES&&... awaitables)
0033 {
0034 return fmap([](auto&& taskTuple)
0035 {
0036 return std::apply([](auto&&... tasks) {
0037 return std::make_tuple(static_cast<decltype(tasks)>(tasks).non_void_result()...);
0038 }, static_cast<decltype(taskTuple)>(taskTuple));
0039 }, when_all_ready(std::forward<AWAITABLES>(awaitables)...));
0040 }
0041
0042
0043
0044
0045 template<
0046 typename AWAITABLE,
0047 typename RESULT = typename awaitable_traits<detail::unwrap_reference_t<AWAITABLE>>::await_result_t,
0048 std::enable_if_t<std::is_void_v<RESULT>, int> = 0>
0049 [[nodiscard]]
0050 auto when_all(std::vector<AWAITABLE> awaitables)
0051 {
0052 return fmap([](auto&& taskVector) {
0053 for (auto& task : taskVector)
0054 {
0055 task.result();
0056 }
0057 }, when_all_ready(std::move(awaitables)));
0058 }
0059
0060 template<
0061 typename AWAITABLE,
0062 typename RESULT = typename awaitable_traits<detail::unwrap_reference_t<AWAITABLE>>::await_result_t,
0063 std::enable_if_t<!std::is_void_v<RESULT>, int> = 0>
0064 [[nodiscard]]
0065 auto when_all(std::vector<AWAITABLE> awaitables)
0066 {
0067 using result_t = std::conditional_t<
0068 std::is_lvalue_reference_v<RESULT>,
0069 std::reference_wrapper<std::remove_reference_t<RESULT>>,
0070 std::remove_reference_t<RESULT>>;
0071
0072 return fmap([](auto&& taskVector) {
0073 std::vector<result_t> results;
0074 results.reserve(taskVector.size());
0075 for (auto& task : taskVector)
0076 {
0077 if constexpr (std::is_rvalue_reference_v<decltype(taskVector)>)
0078 {
0079 results.emplace_back(std::move(task).result());
0080 }
0081 else
0082 {
0083 results.emplace_back(task.result());
0084 }
0085 }
0086 return results;
0087 }, when_all_ready(std::move(awaitables)));
0088 }
0089 }
0090
0091 #endif