LeechCraft 0.6.70-19214-g121e5318a7
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
inparallel.h
Go to the documentation of this file.
1/**********************************************************************
2 * LeechCraft - modular cross-platform feature rich internet client.
3 * Copyright (C) 2006-2014 Georg Rudoy
4 *
5 * Distributed under the Boost Software License, Version 1.0.
6 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7 **********************************************************************/
8
9#pragma once
10
11#include <exception>
12#include <ranges>
13#include <type_traits>
14#include <QVector>
15#include <util/sll/void.h>
16#include "../threadsconfig.h"
17#include "task.h"
18
19namespace LC::Util
20{
21 namespace detail
22 {
24
25 inline void SaveFirst (std::exception_ptr& ex)
26 {
27 if (!ex)
28 ex = std::current_exception ();
29 else
31 }
32
33 template<
34 typename T,
35 template<typename> typename... Exts,
36 bool IsRet = !std::is_void_v<T>,
37 typename RetType = std::conditional_t<IsRet, QVector<T>, void>
38 >
39 Task<RetType, Exts...> JoinAll (QVector<Task<T, Exts...>> tasks, std::exception_ptr ex)
40 {
41 std::conditional_t<IsRet, QVector<T>, Void> result;
42 if constexpr (IsRet)
43 result.reserve (tasks.size ());
44
45 for (auto& task : tasks)
46 try
47 {
48 if constexpr (IsRet)
49 result << co_await task;
50 else
51 co_await task;
52 }
53 catch (...)
54 {
55 SaveFirst (ex);
56 }
57
58 if (ex)
59 std::rethrow_exception (ex);
60
61 if constexpr (IsRet)
62 co_return result;
63 }
64 }
65
76 template<typename T, template<typename> typename... Exts>
77 auto InParallel (QVector<Task<T, Exts...>> tasks)
78 {
79 return detail::JoinAll (std::move (tasks), {});
80 }
81
84 template<typename T, template<typename> typename... Exts>
85 auto InParallel (std::initializer_list<Task<T, Exts...>> tasks)
86 {
87 return detail::JoinAll (QVector<Task<T, Exts...>> { tasks }, {});
88 }
89
97 template<
98 std::ranges::range Inputs,
99 typename F,
100 typename... MkTaskArgs
101 >
102 auto InParallel (Inputs inputs, F mkTask, MkTaskArgs&&... mkTaskArgs)
103 {
104 QVector<decltype (std::invoke (mkTask, std::move (*inputs.begin ()), mkTaskArgs...))> tasks;
105 if constexpr (std::ranges::sized_range<Inputs>)
106 tasks.reserve (std::ranges::size (inputs));
107
108 std::exception_ptr ex;
109 try
110 {
111 for (auto&& input : inputs)
112 tasks << std::invoke (mkTask, std::move (input), mkTaskArgs...);
113 }
114 catch (...)
115 {
116 ex = std::current_exception ();
117 }
118 return detail::JoinAll (std::move (tasks), ex);
119 }
120
125 template<typename... Ts, template<typename> typename... Exts>
126 Task<std::tuple<Ts...>, Exts...> InParallel (Task<Ts, Exts...>... tasks)
127 {
128 // TODO C++26 template for to account for `tasks` exceptions here
129 co_return std::tuple<Ts...> { co_await tasks... };
130 }
131
137 auto NCopies (qsizetype count, auto taskFactory)
138 {
139 return InParallel (QVector<Void> { count, Void {} }, [&] (Void) { return taskFactory (); });
140 }
141}
void SaveFirst(std::exception_ptr &ex)
Definition inparallel.h:25
void HandleSubsequentException()
Task< RetType, Exts... > JoinAll(QVector< Task< T, Exts... > > tasks, std::exception_ptr ex)
Definition inparallel.h:39
auto NCopies(qsizetype count, auto taskFactory)
Starts count tasks via taskFactory and awaits them all.
Definition inparallel.h:137
auto InParallel(QVector< Task< T, Exts... > > tasks)
Awaits all the tasks, collecting their results in order.
Definition inparallel.h:77
A proper void type, akin to unit (or ()) type in functional languages.
Definition void.h:21
#define UTIL_THREADS_API