1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef _PSTL_EXECUTION_IMPL_H
11 #define _PSTL_EXECUTION_IMPL_H
12
13 #include <__config>
14 #include <__iterator/iterator_traits.h>
15 #include <__type_traits/conditional.h>
16 #include <__type_traits/conjunction.h>
17 #include <__type_traits/decay.h>
18 #include <__type_traits/integral_constant.h>
19 #include <__type_traits/is_base_of.h>
20
21 #include <__pstl/internal/execution_defs.h>
22
23 #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
24
25 namespace __pstl {
26 namespace __internal {
27
28 template <typename _IteratorTag, typename... _IteratorTypes>
29 using __are_iterators_of = std::conjunction<
30 std::is_base_of<_IteratorTag, typename std::iterator_traits<std::decay_t<_IteratorTypes>>::iterator_category>...>;
31
32 template <typename... _IteratorTypes>
33 using __are_random_access_iterators = __are_iterators_of<std::random_access_iterator_tag, _IteratorTypes...>;
34
35 struct __serial_backend_tag {};
36 struct __tbb_backend_tag {};
37 struct __openmp_backend_tag {};
38
39 # if defined(_PSTL_PAR_BACKEND_TBB)
40 using __par_backend_tag = __tbb_backend_tag;
41 # elif defined(_PSTL_PAR_BACKEND_OPENMP)
42 using __par_backend_tag = __openmp_backend_tag;
43 # elif defined(_PSTL_PAR_BACKEND_SERIAL)
44 using __par_backend_tag = __serial_backend_tag;
45 # else
46 # error "A parallel backend must be specified";
47 # endif
48
49 template <class _IsVector>
50 struct __serial_tag {
51 using __is_vector = _IsVector;
52 };
53
54 template <class _IsVector>
55 struct __parallel_tag {
56 using __is_vector = _IsVector;
57 // backend tag can be change depending on
58 // TBB availability in the environment
59 using __backend_tag = __par_backend_tag;
60 };
61
62 template <class _IsVector, class... _IteratorTypes>
63 using __tag_type =
64 typename std::conditional<__internal::__are_random_access_iterators<_IteratorTypes...>::value,
65 __parallel_tag<_IsVector>,
66 __serial_tag<_IsVector>>::type;
67
68 template <class... _IteratorTypes>
69 _LIBCPP_HIDE_FROM_ABI __serial_tag</*_IsVector = */ std::false_type>
__select_backend(__pstl::execution::sequenced_policy,_IteratorTypes &&...)70 __select_backend(__pstl::execution::sequenced_policy, _IteratorTypes&&...) {
71 return {};
72 }
73
74 template <class... _IteratorTypes>
75 _LIBCPP_HIDE_FROM_ABI __serial_tag<__internal::__are_random_access_iterators<_IteratorTypes...>>
__select_backend(__pstl::execution::unsequenced_policy,_IteratorTypes &&...)76 __select_backend(__pstl::execution::unsequenced_policy, _IteratorTypes&&...) {
77 return {};
78 }
79
80 template <class... _IteratorTypes>
81 _LIBCPP_HIDE_FROM_ABI __tag_type</*_IsVector = */ std::false_type, _IteratorTypes...>
__select_backend(__pstl::execution::parallel_policy,_IteratorTypes &&...)82 __select_backend(__pstl::execution::parallel_policy, _IteratorTypes&&...) {
83 return {};
84 }
85
86 template <class... _IteratorTypes>
87 _LIBCPP_HIDE_FROM_ABI __tag_type<__internal::__are_random_access_iterators<_IteratorTypes...>, _IteratorTypes...>
__select_backend(__pstl::execution::parallel_unsequenced_policy,_IteratorTypes &&...)88 __select_backend(__pstl::execution::parallel_unsequenced_policy, _IteratorTypes&&...) {
89 return {};
90 }
91
92 } // namespace __internal
93 } // namespace __pstl
94
95 #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
96
97 #endif /* _PSTL_EXECUTION_IMPL_H */
98