1 /*
2     Copyright (c) 2005-2020 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_parallel_for_each_H
18 #define __TBB_parallel_for_each_H
19 
20 #include "parallel_do.h"
21 #include "parallel_for.h"
22 
23 namespace tbb {
24 
25 //! @cond INTERNAL
26 namespace internal {
27     // The class calls user function in operator()
28     template <typename Function, typename Iterator>
29     class parallel_for_each_body_do : internal::no_assign {
30         const Function &my_func;
31     public:
parallel_for_each_body_do(const Function & _func)32         parallel_for_each_body_do(const Function &_func) : my_func(_func) {}
33 
operator()34         void operator()(typename std::iterator_traits<Iterator>::reference value) const {
35             my_func(value);
36         }
37     };
38 
39     // The class calls user function in operator()
40     template <typename Function, typename Iterator>
41     class parallel_for_each_body_for : internal::no_assign {
42         const Function &my_func;
43     public:
parallel_for_each_body_for(const Function & _func)44         parallel_for_each_body_for(const Function &_func) : my_func(_func) {}
45 
operator()46         void operator()(tbb::blocked_range<Iterator> range) const {
47 #if __INTEL_COMPILER
48 #pragma ivdep
49 #endif
50             for(Iterator it = range.begin(), end = range.end(); it != end; ++it) {
51                 my_func(*it);
52             }
53         }
54     };
55 
56     template<typename Iterator, typename Function, typename Generic>
57     struct parallel_for_each_impl {
58 #if __TBB_TASK_GROUP_CONTEXT
doitparallel_for_each_impl59         static void doit(Iterator first, Iterator last, const Function& f, task_group_context &context) {
60             internal::parallel_for_each_body_do<Function, Iterator> body(f);
61             tbb::parallel_do(first, last, body, context);
62         }
63 #endif
doitparallel_for_each_impl64         static void doit(Iterator first, Iterator last, const Function& f) {
65             internal::parallel_for_each_body_do<Function, Iterator> body(f);
66             tbb::parallel_do(first, last, body);
67         }
68     };
69     template<typename Iterator, typename Function>
70     struct parallel_for_each_impl<Iterator, Function, std::random_access_iterator_tag> {
71 #if __TBB_TASK_GROUP_CONTEXT
72         static void doit(Iterator first, Iterator last, const Function& f, task_group_context &context) {
73             internal::parallel_for_each_body_for<Function, Iterator> body(f);
74             tbb::parallel_for(tbb::blocked_range<Iterator>(first, last), body, context);
75         }
76 #endif
77         static void doit(Iterator first, Iterator last, const Function& f) {
78             internal::parallel_for_each_body_for<Function, Iterator> body(f);
79             tbb::parallel_for(tbb::blocked_range<Iterator>(first, last), body);
80         }
81     };
82 } // namespace internal
83 //! @endcond
84 
85 /** \name parallel_for_each
86     **/
87 //@{
88 //! Calls function f for all items from [first, last) interval using user-supplied context
89 /** @ingroup algorithms */
90 #if __TBB_TASK_GROUP_CONTEXT
91 template<typename Iterator, typename Function>
92 void parallel_for_each(Iterator first, Iterator last, const Function& f, task_group_context &context) {
93     internal::parallel_for_each_impl<Iterator, Function, typename std::iterator_traits<Iterator>::iterator_category>::doit(first, last, f, context);
94 }
95 
96 //! Calls function f for all items from rng using user-supplied context
97 /** @ingroup algorithms */
98 template<typename Range, typename Function>
99 void parallel_for_each(Range& rng, const Function& f, task_group_context& context) {
100     parallel_for_each(tbb::internal::first(rng), tbb::internal::last(rng), f, context);
101 }
102 
103 //! Calls function f for all items from const rng user-supplied context
104 /** @ingroup algorithms */
105 template<typename Range, typename Function>
106 void parallel_for_each(const Range& rng, const Function& f, task_group_context& context) {
107     parallel_for_each(tbb::internal::first(rng), tbb::internal::last(rng), f, context);
108 }
109 #endif /* __TBB_TASK_GROUP_CONTEXT */
110 
111 //! Uses default context
112 template<typename Iterator, typename Function>
113 void parallel_for_each(Iterator first, Iterator last, const Function& f) {
114     internal::parallel_for_each_impl<Iterator, Function, typename std::iterator_traits<Iterator>::iterator_category>::doit(first, last, f);
115 }
116 
117 //! Uses default context
118 template<typename Range, typename Function>
119 void parallel_for_each(Range& rng, const Function& f) {
120     parallel_for_each(tbb::internal::first(rng), tbb::internal::last(rng), f);
121 }
122 
123 //! Uses default context
124 template<typename Range, typename Function>
125 void parallel_for_each(const Range& rng, const Function& f) {
126     parallel_for_each(tbb::internal::first(rng), tbb::internal::last(rng), f);
127 }
128 
129 //@}
130 
131 } // namespace
132 
133 #endif /* __TBB_parallel_for_each_H */
134