1 // Copyright (c) 2014-2015 Hartmut Kaiser 2 // Copyright (c) 2018 Taeguk Kwon 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 #if !defined(HPX_PARALLEL_TEST_ITERATOR_MAY_29_2014_0110PM) 8 #define HPX_PARALLEL_TEST_ITERATOR_MAY_29_2014_0110PM 9 10 #include <hpx/include/parallel_execution_policy.hpp> 11 #include <hpx/include/util.hpp> 12 13 #include <atomic> 14 #include <cstddef> 15 #include <iostream> 16 #include <numeric> 17 #include <random> 18 #include <utility> 19 #include <vector> 20 21 namespace test 22 { 23 /////////////////////////////////////////////////////////////////////////// 24 template <typename BaseIterator, typename IteratorTag> 25 struct test_iterator 26 : hpx::util::iterator_adaptor< 27 test_iterator<BaseIterator, IteratorTag>, 28 BaseIterator, void, IteratorTag> 29 { 30 private: 31 typedef hpx::util::iterator_adaptor< 32 test_iterator<BaseIterator, IteratorTag>, 33 BaseIterator, void, IteratorTag> 34 base_type; 35 36 public: test_iteratortest::test_iterator37 test_iterator() : base_type() {} test_iteratortest::test_iterator38 test_iterator(BaseIterator base) : base_type(base) {} 39 }; 40 41 /////////////////////////////////////////////////////////////////////////// 42 template <typename BaseContainer, typename IteratorTag> 43 struct test_container : BaseContainer 44 { 45 template <typename ... Ts> test_containertest::test_container46 test_container(Ts && ...ts) 47 : BaseContainer(std::forward<Ts>(ts)...) 48 {} 49 basetest::test_container50 BaseContainer& base() { return *this; } basetest::test_container51 BaseContainer const& base() const { return *this; } 52 53 typedef test_iterator< 54 typename BaseContainer::iterator, IteratorTag 55 > iterator; 56 typedef test_iterator< 57 typename BaseContainer::const_iterator, IteratorTag 58 > const_iterator; 59 begintest::test_container60 iterator begin() 61 { 62 return iterator(this->BaseContainer::begin()); 63 } begintest::test_container64 const_iterator begin() const 65 { 66 return const_iterator(this->BaseContainer::begin()); 67 } cbegintest::test_container68 const_iterator cbegin() const 69 { 70 return const_iterator(this->BaseContainer::cbegin()); 71 } 72 endtest::test_container73 iterator end() 74 { 75 return iterator(this->BaseContainer::end()); 76 } endtest::test_container77 const_iterator end() const 78 { 79 return const_iterator(this->BaseContainer::end()); 80 } cendtest::test_container81 const_iterator cend() const 82 { 83 return const_iterator(this->BaseContainer::cend()); 84 } 85 }; 86 87 /////////////////////////////////////////////////////////////////////////// 88 template <typename BaseIterator, typename IteratorTag> 89 struct decorated_iterator 90 : hpx::util::iterator_adaptor< 91 decorated_iterator<BaseIterator, IteratorTag>, 92 BaseIterator, void, IteratorTag> 93 { 94 private: 95 typedef hpx::util::iterator_adaptor< 96 decorated_iterator<BaseIterator, IteratorTag>, 97 BaseIterator, void, IteratorTag> 98 base_type; 99 100 public: decorated_iteratortest::decorated_iterator101 decorated_iterator() 102 {} 103 decorated_iteratortest::decorated_iterator104 decorated_iterator(BaseIterator base) 105 : base_type(base) 106 {} 107 decorated_iteratortest::decorated_iterator108 decorated_iterator(BaseIterator base, std::function<void()> f) 109 : base_type(base), m_callback(f) 110 {} 111 112 private: 113 friend class hpx::util::iterator_core_access; 114 dereferencetest::decorated_iterator115 typename base_type::reference dereference() const 116 { 117 if (m_callback) 118 m_callback(); 119 return *(this->base()); 120 } 121 122 private: 123 std::function<void()> m_callback; 124 }; 125 126 /////////////////////////////////////////////////////////////////////////// 127 struct count_instances 128 { count_instancestest::count_instances129 count_instances() 130 : value_(std::size_t(-1)) 131 { 132 ++instance_count; 133 } count_instancestest::count_instances134 count_instances(int value) 135 : value_(value) 136 { 137 ++instance_count; 138 } count_instancestest::count_instances139 count_instances(count_instances const& rhs) 140 : value_(rhs.value_) 141 { 142 ++instance_count; 143 } 144 operator =test::count_instances145 count_instances& operator=(count_instances const& rhs) 146 { 147 value_ = rhs.value_; 148 return *this; 149 } 150 ~count_instancestest::count_instances151 ~count_instances() 152 { 153 --instance_count; 154 } 155 156 std::size_t value_; 157 static std::atomic<std::size_t> instance_count; 158 }; 159 160 std::atomic<std::size_t> count_instances::instance_count(0); 161 162 /////////////////////////////////////////////////////////////////////////// 163 template <typename ExPolicy, typename IteratorTag> 164 struct test_num_exceptions 165 { calltest::test_num_exceptions166 static void call(ExPolicy, hpx::exception_list const& e) 167 { 168 // The static partitioner uses four times the number of 169 // threads/cores for the number chunks to create. 170 HPX_TEST_LTE(e.size(), 4 * hpx::get_num_worker_threads()); 171 } 172 }; 173 174 template <typename IteratorTag> 175 struct test_num_exceptions< 176 hpx::parallel::execution::sequenced_policy, IteratorTag> 177 { calltest::test_num_exceptions178 static void call(hpx::parallel::execution::sequenced_policy const&, 179 hpx::exception_list const& e) 180 { 181 HPX_TEST_EQ(e.size(), 1u); 182 } 183 }; 184 185 template <typename ExPolicy> 186 struct test_num_exceptions<ExPolicy, std::input_iterator_tag> 187 { calltest::test_num_exceptions188 static void call(ExPolicy, hpx::exception_list const& e) 189 { 190 HPX_TEST_EQ(e.size(), 1u); 191 } 192 }; 193 194 template <> 195 struct test_num_exceptions< 196 hpx::parallel::execution::sequenced_policy, std::input_iterator_tag> 197 { calltest::test_num_exceptions198 static void call(hpx::parallel::execution::sequenced_policy const&, 199 hpx::exception_list const& e) 200 { 201 HPX_TEST_EQ(e.size(), 1u); 202 } 203 }; 204 205 /////////////////////////////////////////////////////////////////////////// iota(std::size_t size,std::size_t start)206 inline std::vector<std::size_t> iota(std::size_t size, std::size_t start) 207 { 208 std::vector<std::size_t> c(size); 209 std::iota(std::begin(c), std::end(c), start); 210 return c; 211 } 212 random_iota(std::size_t size)213 inline std::vector<std::size_t> random_iota(std::size_t size) 214 { 215 std::vector<std::size_t> c(size); 216 std::iota(std::begin(c), std::end(c), 0); 217 std::random_device rd; 218 std::mt19937 g(rd()); 219 std::shuffle(std::begin(c), std::end(c), g); 220 return c; 221 } 222 223 template <typename Vector> random_iota(std::size_t size)224 inline Vector random_iota(std::size_t size) 225 { 226 Vector c(size); 227 std::iota(std::begin(c.base()), std::end(c.base()), 0); 228 std::random_device rd; 229 std::mt19937 g(rd()); 230 std::shuffle(std::begin(c.base()), std::end(c.base()), g); 231 return c; 232 } 233 random_fill(std::size_t size)234 inline std::vector<std::size_t> random_fill(std::size_t size) 235 { 236 std::vector<std::size_t> c(size); 237 std::generate(std::begin(c), std::end(c), std::rand); 238 return c; 239 } 240 241 /////////////////////////////////////////////////////////////////////////// make_ready(std::vector<hpx::promise<std::size_t>> & p,std::vector<std::size_t> & idx)242 inline void make_ready(std::vector<hpx::promise<std::size_t> >& p, 243 std::vector<std::size_t>& idx) 244 { 245 std::for_each(std::begin(idx), std::end(idx), 246 [&p](std::size_t i) 247 { 248 p[i].set_value(i); 249 }); 250 } 251 fill_with_futures(std::vector<hpx::promise<std::size_t>> & p)252 inline std::vector<hpx::future<std::size_t> > fill_with_futures( 253 std::vector<hpx::promise<std::size_t> >& p) 254 { 255 std::vector<hpx::future<std::size_t> > f; 256 std::transform(std::begin(p), std::end(p), std::back_inserter(f), 257 [](hpx::promise<std::size_t>& pr) 258 { 259 return pr.get_future(); 260 }); 261 262 return f; 263 } 264 265 /////////////////////////////////////////////////////////////////////////// 266 inline std::vector<std::size_t> fill_all_any_none(std::size_t size,std::size_t num_filled)267 fill_all_any_none(std::size_t size, std::size_t num_filled) 268 { 269 if (num_filled == 0) 270 return std::vector<std::size_t>(size, 0); 271 272 if (num_filled == size) 273 return std::vector<std::size_t>(size, 1); 274 275 std::vector<std::size_t> c(size, 0); 276 for (std::size_t i = 0; i < num_filled; /**/) 277 { 278 std::size_t pos = std::rand() % c.size(); //-V104 279 if (c[pos]) 280 continue; 281 282 c[pos] = 1; 283 ++i; 284 } 285 return c; 286 } 287 288 /////////////////////////////////////////////////////////////////////////// 289 template <typename InputIter1, typename InputIter2> equal(InputIter1 first1,InputIter1 last1,InputIter2 first2,InputIter2 last2)290 bool equal(InputIter1 first1, InputIter1 last1, 291 InputIter2 first2, InputIter2 last2) 292 { 293 if (std::distance(first1, last1) != std::distance(first2, last2)) 294 return false; 295 296 return std::equal(first1, last1, first2); 297 } 298 } 299 300 #endif 301