1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef _LIBCPP___PSTL_CONFIGURATION_FWD_H
10 #define _LIBCPP___PSTL_CONFIGURATION_FWD_H
11 
12 #include <__config>
13 #include <execution>
14 
15 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
16 #  pragma GCC system_header
17 #endif
18 
19 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
20 
21 _LIBCPP_BEGIN_NAMESPACE_STD
22 
23 /*
24 TODO: Documentation of how backends work
25 
26 A PSTL parallel backend is a tag type to which the following functions are associated, at minimum:
27 
28   template <class _ExecutionPolicy, class _Iterator, class _Func>
29   optional<__empty> __pstl_for_each(_Backend, _ExecutionPolicy&&, _Iterator __first, _Iterator __last, _Func __f);
30 
31   template <class _ExecutionPolicy, class _Iterator, class _Predicate>
32   optional<_Iterator> __pstl_find_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred);
33 
34   template <class _ExecutionPolicy, class _RandomAccessIterator, class _Comp>
35   optional<__empty>
36   __pstl_stable_sort(_Backend, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp);
37 
38   template <class _ExecutionPolicy,
39             class _ForwardIterator1,
40             class _ForwardIterator2,
41             class _ForwardOutIterator,
42             class _Comp>
43   optional<_ForwardOutIterator> __pstl_merge(_Backend,
44                                              _ForwardIterator1 __first1,
45                                              _ForwardIterator1 __last1,
46                                              _ForwardIterator2 __first2,
47                                              _ForwardIterator2 __last2,
48                                              _ForwardOutIterator __result,
49                                              _Comp __comp);
50 
51   template <class _ExecutionPolicy, class _InIterator, class _OutIterator, class _UnaryOperation>
52   optional<_OutIterator>
53   __pstl_transform(_Backend, _InIterator __first, _InIterator __last, _OutIterator __result, _UnaryOperation __op);
54 
55   template <class _ExecutionPolicy, class _InIterator1, class _InIterator2, class _OutIterator, class _BinaryOperation>
56   optional<_OutIterator> __pstl_transform(_InIterator1 __first1,
57                                           _InIterator2 __first2,
58                                           _InIterator1 __last1,
59                                           _OutIterator __result,
60                                           _BinaryOperation __op);
61 
62   template <class _ExecutionPolicy,
63             class _Iterator1,
64             class _Iterator2,
65             class _Tp,
66             class _BinaryOperation1,
67             class _BinaryOperation2>
68   optional<_Tp> __pstl_transform_reduce(_Backend,
69                                         _Iterator1 __first1,
70                                         _Iterator1 __last1,
71                                         _Iterator2 __first2,
72                                         _Iterator2 __last2,
73                                         _Tp __init,
74                                         _BinaryOperation1 __reduce,
75                                         _BinaryOperation2 __transform);
76 
77   template <class _ExecutionPolicy, class _Iterator, class _Tp, class _BinaryOperation, class _UnaryOperation>
78   optional<_Tp> __pstl_transform_reduce(_Backend,
79                                         _Iterator __first,
80                                         _Iterator __last,
81                                         _Tp __init,
82                                         _BinaryOperation __reduce,
83                                         _UnaryOperation __transform);
84 
85 // TODO: Complete this list
86 
87 The following functions are optional but can be provided. If provided, they are used by the corresponding
88 algorithms, otherwise they are implemented in terms of other algorithms. If none of the optional algorithms are
89 implemented, all the algorithms will eventually forward to the basis algorithms listed above:
90 
91   template <class _ExecutionPolicy, class _Iterator, class _Size, class _Func>
92   optional<__empty> __pstl_for_each_n(_Backend, _Iterator __first, _Size __n, _Func __f);
93 
94   template <class _ExecutionPolicy, class _Iterator, class _Predicate>
95   optional<bool> __pstl_any_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred);
96 
97   template <class _ExecutionPolicy, class _Iterator, class _Predicate>
98   optional<bool> __pstl_all_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred);
99 
100   template <class _ExecutionPolicy, class _Iterator, class _Predicate>
101   optional<bool> __pstl_none_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred);
102 
103   template <class _ExecutionPolicy, class _Iterator, class _Tp>
104   optional<_Iterator> __pstl_find(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value);
105 
106   template <class _ExecutionPolicy, class _Iterator, class _Predicate>
107   optional<_Iterator> __pstl_find_if_not(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred);
108 
109   template <class _ExecutionPolicy, class _Iterator, class _Tp>
110   optional<__empty> __pstl_fill(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value);
111 
112   template <class _ExecutionPolicy, class _Iterator, class _SizeT, class _Tp>
113   optional<__empty> __pstl_fill_n(_Backend, _Iterator __first, _SizeT __n, const _Tp& __value);
114 
115   template <class _ExecutionPolicy, class _Iterator, class _Generator>
116   optional<__empty> __pstl_generate(_Backend, _Iterator __first, _Iterator __last, _Generator __gen);
117 
118   template <class _ExecutionPolicy, class _Iterator, class _Predicate>
119   optional<__empty> __pstl_is_partitioned(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred);
120 
121   template <class _ExecutionPolicy, class _Iterator, class _Size, class _Generator>
122   optional<__empty> __pstl_generator_n(_Backend, _Iterator __first, _Size __n, _Generator __gen);
123 
124   template <class _ExecutionPolicy, class _terator1, class _Iterator2, class _OutIterator, class _Comp>
125   optional<_OutIterator> __pstl_merge(_Backend,
126                                       _Iterator1 __first1,
127                                       _Iterator1 __last1,
128                                       _Iterator2 __first2,
129                                       _Iterator2 __last2,
130                                       _OutIterator __result,
131                                       _Comp __comp);
132 
133   template <class _ExecutionPolicy, class _Iterator, class _OutIterator>
134   optional<_OutIterator> __pstl_move(_Backend, _Iterator __first, _Iterator __last, _OutIterator __result);
135 
136   template <class _ExecutionPolicy, class _Iterator, class _Tp, class _BinaryOperation>
137   optional<_Tp> __pstl_reduce(_Backend, _Iterator __first, _Iterator __last, _Tp __init, _BinaryOperation __op);
138 
139   temlate <class _ExecutionPolicy, class _Iterator>
140   optional<__iter_value_type<_Iterator>> __pstl_reduce(_Backend, _Iterator __first, _Iterator __last);
141 
142   template <class _ExecutionPolicy, class _Iterator, class _Tp>
143   optional<__iter_diff_t<_Iterator>> __pstl_count(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value);
144 
145   template <class _ExecutionPolicy, class _Iterator, class _Predicate>
146   optional<__iter_diff_t<_Iterator>> __pstl_count_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred);
147 
148   template <class _ExecutionPolicy, class _Iterator, class _Tp>
149   optional<__empty>
150   __pstl_replace(_Backend, _Iterator __first, _Iterator __last, const _Tp& __old_value, const _Tp& __new_value);
151 
152   template <class _ExecutionPolicy, class _Iterator, class _Pred, class _Tp>
153   optional<__empty>
154   __pstl_replace_if(_Backend, _Iterator __first, _Iterator __last, _Pred __pred, const _Tp& __new_value);
155 
156   template <class _ExecutionPolicy, class _Iterator, class _OutIterator, class _Tp>
157   optional<__empty> __pstl_replace_copy(_Backend,
158                                         _Iterator __first,
159                                         _Iterator __last,
160                                         _OutIterator __result,
161                                         const _Tp& __old_value,
162                                         const _Tp& __new_value);
163 
164   template <class _ExecutionPolicy, class _Iterator, class _OutIterator, class _Pred, class _Tp>
165   optional<__empty> __pstl_replace_copy_if(_Backend,
166                                            _Iterator __first,
167                                            _Iterator __last,
168                                            _OutIterator __result,
169                                            _Pred __pred,
170                                            const _Tp& __new_value);
171 
172   template <class _ExecutionPolicy, class _Iterator, class _OutIterator>
173   optional<_Iterator> __pstl_rotate_copy(
174       _Backend, _Iterator __first, _Iterator __middle, _Iterator __last, _OutIterator __result);
175 
176   template <class _ExecutionPolicy, class _Iterator, class _Comp>
177   optional<__empty> __pstl_sort(_Backend, _Iterator __first, _Iterator __last, _Comp __comp);
178 
179   template <class _ExecutionPolicy, class _Iterator1, class _Iterator2, class _Comp>
180   optional<bool> __pstl_equal(_Backend, _Iterator1 first1, _Iterator1 last1, _Iterator2 first2, _Comp __comp);
181 
182 // TODO: Complete this list
183 
184 Exception handling
185 ==================
186 
187 PSTL backends are expected to report errors (i.e. failure to allocate) by returning a disengaged `optional` from their
188 implementation. Exceptions shouldn't be used to report an internal failure-to-allocate, since all exceptions are turned
189 into a program termination at the front-end level. When a backend returns a disengaged `optional` to the frontend, the
190 frontend will turn that into a call to `std::__throw_bad_alloc();` to report the internal failure to the user.
191 */
192 
193 namespace __pstl {
194 struct __libdispatch_backend_tag {};
195 struct __serial_backend_tag {};
196 struct __std_thread_backend_tag {};
197 } // namespace __pstl
198 
199 #  if defined(_LIBCPP_PSTL_BACKEND_SERIAL)
200 using __cpu_backend_tag = __pstl::__serial_backend_tag;
201 #  elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD)
202 using __cpu_backend_tag = __pstl::__std_thread_backend_tag;
203 #  elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH)
204 using __cpu_backend_tag = __pstl::__libdispatch_backend_tag;
205 #  endif
206 
207 template <class _ExecutionPolicy>
208 struct __select_backend;
209 
210 template <>
211 struct __select_backend<std::execution::sequenced_policy> {
212   using type = __cpu_backend_tag;
213 };
214 
215 #  if _LIBCPP_STD_VER >= 20
216 template <>
217 struct __select_backend<std::execution::unsequenced_policy> {
218   using type = __cpu_backend_tag;
219 };
220 #  endif
221 
222 #  if defined(_LIBCPP_PSTL_BACKEND_SERIAL) || defined(_LIBCPP_PSTL_BACKEND_STD_THREAD) ||                              \
223       defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH)
224 template <>
225 struct __select_backend<std::execution::parallel_policy> {
226   using type = __cpu_backend_tag;
227 };
228 
229 template <>
230 struct __select_backend<std::execution::parallel_unsequenced_policy> {
231   using type = __cpu_backend_tag;
232 };
233 
234 #  else
235 
236 // ...New vendors can add parallel backends here...
237 
238 #    error "Invalid choice of a PSTL parallel backend"
239 #  endif
240 
241 _LIBCPP_END_NAMESPACE_STD
242 
243 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
244 
245 #endif // _LIBCPP___PSTL_CONFIGURATION_FWD_H
246