1 //  Copyright (c) 2014-2015 Hartmut Kaiser
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #if !defined(HPX_PARALLEL_TEST_FOREACH_MAY26_15_1414)
7 #define HPX_PARALLEL_TEST_FOREACH_MAY26_15_1414
8 
9 #include <hpx/include/parallel_container_algorithm.hpp>
10 #include <hpx/util/lightweight_test.hpp>
11 #include <hpx/util/iterator_range.hpp>
12 
13 #include <atomic>
14 #include <cstddef>
15 #include <iterator>
16 #include <utility>
17 #include <vector>
18 
19 #include "test_utils.hpp"
20 
21 ////////////////////////////////////////////////////////////////////////////////
22 template <typename ExPolicy, typename IteratorTag, typename Proj>
test_for_each(ExPolicy && policy,IteratorTag,Proj && proj)23 void test_for_each(ExPolicy && policy, IteratorTag, Proj && proj)
24 {
25     BOOST_STATIC_ASSERT(hpx::parallel::execution::is_execution_policy<ExPolicy>::value);
26 
27     typedef std::vector<std::size_t>::iterator base_iterator;
28     typedef test::test_iterator<base_iterator, IteratorTag> iterator;
29 
30     std::vector<std::size_t> c(10007);
31     std::fill(std::begin(c), std::end(c), std::size_t(42));
32 
33     std::atomic<std::size_t> count(0);
34 
35     iterator result =
36         hpx::parallel::for_each(std::forward<ExPolicy>(policy),
37             hpx::util::make_iterator_range(
38                 iterator(std::begin(c)), iterator(std::end(c))
39             ),
40             [&count, &proj](std::size_t v) {
41                 HPX_TEST_EQ(v, proj(std::size_t(42)));
42                 ++count;
43             },
44             proj);
45 
46     HPX_TEST(result == iterator(std::end(c)));
47     HPX_TEST_EQ(count, c.size());
48 }
49 
50 template <typename ExPolicy, typename IteratorTag, typename Proj>
test_for_each_async(ExPolicy && p,IteratorTag,Proj && proj)51 void test_for_each_async(ExPolicy && p, IteratorTag, Proj && proj)
52 {
53     typedef std::vector<std::size_t>::iterator base_iterator;
54     typedef test::test_iterator<base_iterator, IteratorTag> iterator;
55 
56     std::vector<std::size_t> c(10007);
57     std::fill(std::begin(c), std::end(c), std::size_t(42));
58 
59     std::atomic<std::size_t> count(0);
60 
61     hpx::future<iterator> f =
62         hpx::parallel::for_each(std::forward<ExPolicy>(p),
63             hpx::util::make_iterator_range(
64                 iterator(std::begin(c)), iterator(std::end(c))
65             ),
66             [&count, &proj](std::size_t v) {
67                 HPX_TEST_EQ(v, proj(std::size_t(42)));
68                 ++count;
69             },
70             proj);
71     f.wait();
72 
73     HPX_TEST(f.get() == iterator(std::end(c)));
74     HPX_TEST_EQ(count, c.size());
75 }
76 
77 ////////////////////////////////////////////////////////////////////////////////
78 template <typename ExPolicy, typename IteratorTag, typename Proj>
test_for_each_exception(ExPolicy policy,IteratorTag,Proj && proj)79 void test_for_each_exception(ExPolicy policy, IteratorTag, Proj && proj)
80 {
81     BOOST_STATIC_ASSERT(hpx::parallel::execution::is_execution_policy<ExPolicy>::value);
82 
83     typedef std::vector<std::size_t>::iterator base_iterator;
84     typedef test::test_iterator<base_iterator, IteratorTag> iterator;
85 
86     std::vector<std::size_t> c(10007);
87     std::fill(std::begin(c), std::end(c), std::size_t(42));
88 
89     bool caught_exception = false;
90     try {
91         hpx::parallel::for_each(policy,
92             hpx::util::make_iterator_range(
93                 iterator(std::begin(c)), iterator(std::end(c))
94             ),
95             [](std::size_t v) { throw std::runtime_error("test"); },
96             proj);
97 
98         HPX_TEST(false);
99     }
100     catch(hpx::exception_list const& e) {
101         caught_exception = true;
102         test::test_num_exceptions<ExPolicy, IteratorTag>::call(policy, e);
103     }
104     catch(...) {
105         HPX_TEST(false);
106     }
107 
108     HPX_TEST(caught_exception);
109 }
110 
111 template <typename ExPolicy, typename IteratorTag, typename Proj>
test_for_each_exception_async(ExPolicy p,IteratorTag,Proj && proj)112 void test_for_each_exception_async(ExPolicy p, IteratorTag, Proj && proj)
113 {
114     typedef std::vector<std::size_t>::iterator base_iterator;
115     typedef test::test_iterator<base_iterator, IteratorTag> iterator;
116 
117     std::vector<std::size_t> c(10007);
118     std::fill(std::begin(c), std::end(c), std::size_t(42));
119 
120     bool caught_exception = false;
121     bool returned_from_algorithm = false;
122     try {
123         hpx::future<void> f =
124             hpx::parallel::for_each(p,
125                 hpx::util::make_iterator_range(
126                     iterator(std::begin(c)), iterator(std::end(c))
127                 ),
128                 [](std::size_t v) { throw std::runtime_error("test"); },
129                 proj);
130         returned_from_algorithm = true;
131         f.get();
132 
133         HPX_TEST(false);
134     }
135     catch(hpx::exception_list const& e) {
136         caught_exception = true;
137         test::test_num_exceptions<ExPolicy, IteratorTag>::call(p, e);
138     }
139     catch(...) {
140         HPX_TEST(false);
141     }
142 
143     HPX_TEST(caught_exception);
144     HPX_TEST(returned_from_algorithm);
145 }
146 
147 ////////////////////////////////////////////////////////////////////////////////
148 template <typename ExPolicy, typename IteratorTag, typename Proj>
test_for_each_bad_alloc(ExPolicy policy,IteratorTag,Proj && proj)149 void test_for_each_bad_alloc(ExPolicy policy, IteratorTag, Proj && proj)
150 {
151     BOOST_STATIC_ASSERT(hpx::parallel::execution::is_execution_policy<ExPolicy>::value);
152 
153     typedef std::vector<std::size_t>::iterator base_iterator;
154     typedef test::test_iterator<base_iterator, IteratorTag> iterator;
155 
156     std::vector<std::size_t> c(10007);
157     std::fill(std::begin(c), std::end(c), std::size_t(42));
158 
159     bool caught_exception = false;
160     try {
161         hpx::parallel::for_each(policy,
162             hpx::util::make_iterator_range(
163                 iterator(std::begin(c)), iterator(std::end(c))
164             ),
165             [](std::size_t v) { throw std::bad_alloc(); },
166             proj);
167 
168         HPX_TEST(false);
169     }
170     catch(std::bad_alloc const&) {
171         caught_exception = true;
172     }
173     catch(...) {
174         HPX_TEST(false);
175     }
176 
177     HPX_TEST(caught_exception);
178 }
179 
180 template <typename ExPolicy, typename IteratorTag, typename Proj>
test_for_each_bad_alloc_async(ExPolicy p,IteratorTag,Proj && proj)181 void test_for_each_bad_alloc_async(ExPolicy p, IteratorTag, Proj && proj)
182 {
183     typedef std::vector<std::size_t>::iterator base_iterator;
184     typedef test::test_iterator<base_iterator, IteratorTag> iterator;
185 
186     std::vector<std::size_t> c(10007);
187     std::fill(std::begin(c), std::end(c), std::size_t(42));
188 
189     bool caught_exception = false;
190     bool returned_from_algorithm = false;
191     try {
192         hpx::future<void> f =
193             hpx::parallel::for_each(p,
194                 hpx::util::make_iterator_range(
195                     iterator(std::begin(c)), iterator(std::end(c))
196                 ),
197                 [](std::size_t v) { throw std::bad_alloc(); },
198                 proj);
199         returned_from_algorithm = true;
200         f.get();
201 
202         HPX_TEST(false);
203     }
204     catch(std::bad_alloc const&) {
205         caught_exception = true;
206     }
207     catch(...) {
208         HPX_TEST(false);
209     }
210 
211     HPX_TEST(caught_exception);
212     HPX_TEST(returned_from_algorithm);
213 }
214 
215 #endif
216