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