1/*
2 Copyright (c) 2005-2021 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#ifndef __TBB_detail__range_common_H
18#define __TBB_detail__range_common_H
19
20#include "_config.h"
21#include "_utils.h"
22#if __TBB_CPP20_CONCEPTS_PRESENT
23#include <concepts>
24#include <iterator>
25#endif
26
27namespace tbb {
28namespace detail {
29inline namespace d0 {
30
31//! Dummy type that distinguishes splitting constructor from copy constructor.
32/**
33 * See description of parallel_for and parallel_reduce for example usages.
34 * @ingroup algorithms
35 */
36class split {};
37
38//! Type enables transmission of splitting proportion from partitioners to range objects
39/**
40 * In order to make use of such facility Range objects must implement
41 * splitting constructor with this type passed.
42 */
43class proportional_split : no_assign {
44public:
45 proportional_split(size_t _left = 1, size_t _right = 1) : my_left(_left), my_right(_right) { }
46
47 size_t left() const { return my_left; }
48 size_t right() const { return my_right; }
49
50 // used when range does not support proportional split
51 explicit operator split() const { return split(); }
52
53private:
54 size_t my_left, my_right;
55};
56
57template <typename Range, typename = void>
58struct range_split_object_provider {
59 template <typename PartitionerSplitType>
60 static split get( PartitionerSplitType& ) { return split(); }
61};
62
63template <typename Range>
64struct range_split_object_provider<Range,
65 typename std::enable_if<std::is_constructible<Range, Range&, proportional_split&>::value>::type> {
66 template <typename PartitionerSplitType>
67 static PartitionerSplitType& get( PartitionerSplitType& split_obj ) { return split_obj; }
68};
69
70template <typename Range, typename PartitionerSplitType>
71auto get_range_split_object( PartitionerSplitType& split_obj )
72-> decltype(range_split_object_provider<Range>::get(split_obj)) {
73 return range_split_object_provider<Range>::get(split_obj);
74}
75
76#if __TBB_CPP20_CONCEPTS_PRESENT
77template <typename Range>
78using range_iterator_type = decltype(std::begin(std::declval<Range&>()));
79
80template <typename Iterator>
81using iterator_reference_type = typename std::iterator_traits<Iterator>::reference;
82
83template <typename Range>
84using range_reference_type = iterator_reference_type<range_iterator_type<Range>>;
85
86template <typename Value>
87concept blocked_range_value = std::copyable<Value> &&
88 requires( const std::remove_reference_t<Value>& lhs, const std::remove_reference_t<Value>& rhs ) {
89 { lhs < rhs } -> relaxed_convertible_to<bool>;
90 { lhs - rhs } -> std::convertible_to<std::size_t>;
91 { lhs + (rhs - lhs) } -> std::convertible_to<Value>;
92 };
93
94template <typename T>
95concept splittable = std::constructible_from<T, T&, tbb::detail::split>;
96
97template <typename Range>
98concept tbb_range = std::copy_constructible<Range> &&
99 splittable<Range> &&
100 requires( const std::remove_reference_t<Range>& range ) {
101 { range.empty() } -> relaxed_convertible_to<bool>;
102 { range.is_divisible() } -> relaxed_convertible_to<bool>;
103 };
104
105template <typename Iterator>
106constexpr bool iterator_concept_helper( std::input_iterator_tag ) {
107 return std::input_iterator<Iterator>;
108}
109
110template <typename Iterator>
111constexpr bool iterator_concept_helper( std::random_access_iterator_tag ) {
112 return std::random_access_iterator<Iterator>;
113}
114
115template <typename Iterator, typename IteratorTag>
116concept iterator_satisfies = requires (IteratorTag tag) {
117 requires iterator_concept_helper<Iterator>(tag);
118};
119
120template <typename Sequence, typename IteratorTag>
121concept container_based_sequence = requires( Sequence& seq ) {
122 { std::begin(seq) } -> iterator_satisfies<IteratorTag>;
123 { std::end(seq) } -> iterator_satisfies<IteratorTag>;
124};
125#endif // __TBB_CPP20_CONCEPTS_PRESENT
126} // namespace d0
127} // namespace detail
128} // namespace tbb
129
130#endif // __TBB_detail__range_common_H
131

source code of include/oneapi/tbb/detail/_range_common.h