1*e4b17023SJohn Marino // -*- C++ -*- 2*e4b17023SJohn Marino 3*e4b17023SJohn Marino // Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. 4*e4b17023SJohn Marino // 5*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library. This library is free 6*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the terms 7*e4b17023SJohn Marino // of the GNU General Public License as published by the Free Software 8*e4b17023SJohn Marino // Foundation; either version 3, or (at your option) any later 9*e4b17023SJohn Marino // version. 10*e4b17023SJohn Marino 11*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful, but 12*e4b17023SJohn Marino // WITHOUT ANY WARRANTY; without even the implied warranty of 13*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*e4b17023SJohn Marino // General Public License for more details. 15*e4b17023SJohn Marino 16*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional 17*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version 18*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation. 19*e4b17023SJohn Marino 20*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and 21*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program; 22*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>. 24*e4b17023SJohn Marino 25*e4b17023SJohn Marino /** @file parallel/find.h 26*e4b17023SJohn Marino * @brief Parallel implementation base for std::find(), std::equal() 27*e4b17023SJohn Marino * and related functions. 28*e4b17023SJohn Marino * This file is a GNU parallel extension to the Standard C++ Library. 29*e4b17023SJohn Marino */ 30*e4b17023SJohn Marino 31*e4b17023SJohn Marino // Written by Felix Putze and Johannes Singler. 32*e4b17023SJohn Marino 33*e4b17023SJohn Marino #ifndef _GLIBCXX_PARALLEL_FIND_H 34*e4b17023SJohn Marino #define _GLIBCXX_PARALLEL_FIND_H 1 35*e4b17023SJohn Marino 36*e4b17023SJohn Marino #include <bits/stl_algobase.h> 37*e4b17023SJohn Marino 38*e4b17023SJohn Marino #include <parallel/features.h> 39*e4b17023SJohn Marino #include <parallel/parallel.h> 40*e4b17023SJohn Marino #include <parallel/compatibility.h> 41*e4b17023SJohn Marino #include <parallel/equally_split.h> 42*e4b17023SJohn Marino 43*e4b17023SJohn Marino namespace __gnu_parallel 44*e4b17023SJohn Marino { 45*e4b17023SJohn Marino /** 46*e4b17023SJohn Marino * @brief Parallel std::find, switch for different algorithms. 47*e4b17023SJohn Marino * @param __begin1 Begin iterator of first sequence. 48*e4b17023SJohn Marino * @param __end1 End iterator of first sequence. 49*e4b17023SJohn Marino * @param __begin2 Begin iterator of second sequence. Must have same 50*e4b17023SJohn Marino * length as first sequence. 51*e4b17023SJohn Marino * @param __pred Find predicate. 52*e4b17023SJohn Marino * @param __selector _Functionality (e. g. std::find_if(), std::equal(),...) 53*e4b17023SJohn Marino * @return Place of finding in both sequences. 54*e4b17023SJohn Marino */ 55*e4b17023SJohn Marino template<typename _RAIter1, 56*e4b17023SJohn Marino typename _RAIter2, 57*e4b17023SJohn Marino typename _Pred, 58*e4b17023SJohn Marino typename _Selector> 59*e4b17023SJohn Marino inline std::pair<_RAIter1, _RAIter2> __find_template(_RAIter1 __begin1,_RAIter1 __end1,_RAIter2 __begin2,_Pred __pred,_Selector __selector)60*e4b17023SJohn Marino __find_template(_RAIter1 __begin1, _RAIter1 __end1, 61*e4b17023SJohn Marino _RAIter2 __begin2, _Pred __pred, _Selector __selector) 62*e4b17023SJohn Marino { 63*e4b17023SJohn Marino switch (_Settings::get().find_algorithm) 64*e4b17023SJohn Marino { 65*e4b17023SJohn Marino case GROWING_BLOCKS: 66*e4b17023SJohn Marino return __find_template(__begin1, __end1, __begin2, __pred, 67*e4b17023SJohn Marino __selector, growing_blocks_tag()); 68*e4b17023SJohn Marino case CONSTANT_SIZE_BLOCKS: 69*e4b17023SJohn Marino return __find_template(__begin1, __end1, __begin2, __pred, 70*e4b17023SJohn Marino __selector, constant_size_blocks_tag()); 71*e4b17023SJohn Marino case EQUAL_SPLIT: 72*e4b17023SJohn Marino return __find_template(__begin1, __end1, __begin2, __pred, 73*e4b17023SJohn Marino __selector, equal_split_tag()); 74*e4b17023SJohn Marino default: 75*e4b17023SJohn Marino _GLIBCXX_PARALLEL_ASSERT(false); 76*e4b17023SJohn Marino return std::make_pair(__begin1, __begin2); 77*e4b17023SJohn Marino } 78*e4b17023SJohn Marino } 79*e4b17023SJohn Marino 80*e4b17023SJohn Marino #if _GLIBCXX_FIND_EQUAL_SPLIT 81*e4b17023SJohn Marino 82*e4b17023SJohn Marino /** 83*e4b17023SJohn Marino * @brief Parallel std::find, equal splitting variant. 84*e4b17023SJohn Marino * @param __begin1 Begin iterator of first sequence. 85*e4b17023SJohn Marino * @param __end1 End iterator of first sequence. 86*e4b17023SJohn Marino * @param __begin2 Begin iterator of second sequence. Second __sequence 87*e4b17023SJohn Marino * must have same length as first sequence. 88*e4b17023SJohn Marino * @param __pred Find predicate. 89*e4b17023SJohn Marino * @param __selector _Functionality (e. g. std::find_if(), std::equal(),...) 90*e4b17023SJohn Marino * @return Place of finding in both sequences. 91*e4b17023SJohn Marino */ 92*e4b17023SJohn Marino template<typename _RAIter1, 93*e4b17023SJohn Marino typename _RAIter2, 94*e4b17023SJohn Marino typename _Pred, 95*e4b17023SJohn Marino typename _Selector> 96*e4b17023SJohn Marino std::pair<_RAIter1, _RAIter2> __find_template(_RAIter1 __begin1,_RAIter1 __end1,_RAIter2 __begin2,_Pred __pred,_Selector __selector,equal_split_tag)97*e4b17023SJohn Marino __find_template(_RAIter1 __begin1, _RAIter1 __end1, 98*e4b17023SJohn Marino _RAIter2 __begin2, _Pred __pred, 99*e4b17023SJohn Marino _Selector __selector, equal_split_tag) 100*e4b17023SJohn Marino { 101*e4b17023SJohn Marino _GLIBCXX_CALL(__end1 - __begin1) 102*e4b17023SJohn Marino 103*e4b17023SJohn Marino typedef std::iterator_traits<_RAIter1> _TraitsType; 104*e4b17023SJohn Marino typedef typename _TraitsType::difference_type _DifferenceType; 105*e4b17023SJohn Marino typedef typename _TraitsType::value_type _ValueType; 106*e4b17023SJohn Marino 107*e4b17023SJohn Marino _DifferenceType __length = __end1 - __begin1; 108*e4b17023SJohn Marino _DifferenceType __result = __length; 109*e4b17023SJohn Marino _DifferenceType* __borders; 110*e4b17023SJohn Marino 111*e4b17023SJohn Marino omp_lock_t __result_lock; 112*e4b17023SJohn Marino omp_init_lock(&__result_lock); 113*e4b17023SJohn Marino 114*e4b17023SJohn Marino _ThreadIndex __num_threads = __get_max_threads(); 115*e4b17023SJohn Marino # pragma omp parallel num_threads(__num_threads) 116*e4b17023SJohn Marino { 117*e4b17023SJohn Marino # pragma omp single 118*e4b17023SJohn Marino { 119*e4b17023SJohn Marino __num_threads = omp_get_num_threads(); 120*e4b17023SJohn Marino __borders = new _DifferenceType[__num_threads + 1]; 121*e4b17023SJohn Marino __equally_split(__length, __num_threads, __borders); 122*e4b17023SJohn Marino } //single 123*e4b17023SJohn Marino 124*e4b17023SJohn Marino _ThreadIndex __iam = omp_get_thread_num(); 125*e4b17023SJohn Marino _DifferenceType __start = __borders[__iam], 126*e4b17023SJohn Marino __stop = __borders[__iam + 1]; 127*e4b17023SJohn Marino 128*e4b17023SJohn Marino _RAIter1 __i1 = __begin1 + __start; 129*e4b17023SJohn Marino _RAIter2 __i2 = __begin2 + __start; 130*e4b17023SJohn Marino for (_DifferenceType __pos = __start; __pos < __stop; ++__pos) 131*e4b17023SJohn Marino { 132*e4b17023SJohn Marino # pragma omp flush(__result) 133*e4b17023SJohn Marino // Result has been set to something lower. 134*e4b17023SJohn Marino if (__result < __pos) 135*e4b17023SJohn Marino break; 136*e4b17023SJohn Marino 137*e4b17023SJohn Marino if (__selector(__i1, __i2, __pred)) 138*e4b17023SJohn Marino { 139*e4b17023SJohn Marino omp_set_lock(&__result_lock); 140*e4b17023SJohn Marino if (__pos < __result) 141*e4b17023SJohn Marino __result = __pos; 142*e4b17023SJohn Marino omp_unset_lock(&__result_lock); 143*e4b17023SJohn Marino break; 144*e4b17023SJohn Marino } 145*e4b17023SJohn Marino ++__i1; 146*e4b17023SJohn Marino ++__i2; 147*e4b17023SJohn Marino } 148*e4b17023SJohn Marino } //parallel 149*e4b17023SJohn Marino 150*e4b17023SJohn Marino omp_destroy_lock(&__result_lock); 151*e4b17023SJohn Marino delete[] __borders; 152*e4b17023SJohn Marino 153*e4b17023SJohn Marino return std::pair<_RAIter1, _RAIter2>(__begin1 + __result, 154*e4b17023SJohn Marino __begin2 + __result); 155*e4b17023SJohn Marino } 156*e4b17023SJohn Marino 157*e4b17023SJohn Marino #endif 158*e4b17023SJohn Marino 159*e4b17023SJohn Marino #if _GLIBCXX_FIND_GROWING_BLOCKS 160*e4b17023SJohn Marino 161*e4b17023SJohn Marino /** 162*e4b17023SJohn Marino * @brief Parallel std::find, growing block size variant. 163*e4b17023SJohn Marino * @param __begin1 Begin iterator of first sequence. 164*e4b17023SJohn Marino * @param __end1 End iterator of first sequence. 165*e4b17023SJohn Marino * @param __begin2 Begin iterator of second sequence. Second __sequence 166*e4b17023SJohn Marino * must have same length as first sequence. 167*e4b17023SJohn Marino * @param __pred Find predicate. 168*e4b17023SJohn Marino * @param __selector _Functionality (e. g. std::find_if(), std::equal(),...) 169*e4b17023SJohn Marino * @return Place of finding in both sequences. 170*e4b17023SJohn Marino * @see __gnu_parallel::_Settings::find_sequential_search_size 171*e4b17023SJohn Marino * @see __gnu_parallel::_Settings::find_scale_factor 172*e4b17023SJohn Marino * 173*e4b17023SJohn Marino * There are two main differences between the growing blocks and 174*e4b17023SJohn Marino * the constant-size blocks variants. 175*e4b17023SJohn Marino * 1. For GB, the block size grows; for CSB, the block size is fixed. 176*e4b17023SJohn Marino * 2. For GB, the blocks are allocated dynamically; 177*e4b17023SJohn Marino * for CSB, the blocks are allocated in a predetermined manner, 178*e4b17023SJohn Marino * namely spacial round-robin. 179*e4b17023SJohn Marino */ 180*e4b17023SJohn Marino template<typename _RAIter1, 181*e4b17023SJohn Marino typename _RAIter2, 182*e4b17023SJohn Marino typename _Pred, 183*e4b17023SJohn Marino typename _Selector> 184*e4b17023SJohn Marino std::pair<_RAIter1, _RAIter2> __find_template(_RAIter1 __begin1,_RAIter1 __end1,_RAIter2 __begin2,_Pred __pred,_Selector __selector,growing_blocks_tag)185*e4b17023SJohn Marino __find_template(_RAIter1 __begin1, _RAIter1 __end1, 186*e4b17023SJohn Marino _RAIter2 __begin2, _Pred __pred, _Selector __selector, 187*e4b17023SJohn Marino growing_blocks_tag) 188*e4b17023SJohn Marino { 189*e4b17023SJohn Marino _GLIBCXX_CALL(__end1 - __begin1) 190*e4b17023SJohn Marino 191*e4b17023SJohn Marino typedef std::iterator_traits<_RAIter1> _TraitsType; 192*e4b17023SJohn Marino typedef typename _TraitsType::difference_type _DifferenceType; 193*e4b17023SJohn Marino typedef typename _TraitsType::value_type _ValueType; 194*e4b17023SJohn Marino 195*e4b17023SJohn Marino const _Settings& __s = _Settings::get(); 196*e4b17023SJohn Marino 197*e4b17023SJohn Marino _DifferenceType __length = __end1 - __begin1; 198*e4b17023SJohn Marino 199*e4b17023SJohn Marino _DifferenceType 200*e4b17023SJohn Marino __sequential_search_size = std::min<_DifferenceType> 201*e4b17023SJohn Marino (__length, __s.find_sequential_search_size); 202*e4b17023SJohn Marino 203*e4b17023SJohn Marino // Try it sequentially first. 204*e4b17023SJohn Marino std::pair<_RAIter1, _RAIter2> 205*e4b17023SJohn Marino __find_seq_result = __selector._M_sequential_algorithm 206*e4b17023SJohn Marino (__begin1, __begin1 + __sequential_search_size, 207*e4b17023SJohn Marino __begin2, __pred); 208*e4b17023SJohn Marino 209*e4b17023SJohn Marino if (__find_seq_result.first != (__begin1 + __sequential_search_size)) 210*e4b17023SJohn Marino return __find_seq_result; 211*e4b17023SJohn Marino 212*e4b17023SJohn Marino // Index of beginning of next free block (after sequential find). 213*e4b17023SJohn Marino _DifferenceType __next_block_start = __sequential_search_size; 214*e4b17023SJohn Marino _DifferenceType __result = __length; 215*e4b17023SJohn Marino 216*e4b17023SJohn Marino omp_lock_t __result_lock; 217*e4b17023SJohn Marino omp_init_lock(&__result_lock); 218*e4b17023SJohn Marino 219*e4b17023SJohn Marino const float __scale_factor = __s.find_scale_factor; 220*e4b17023SJohn Marino 221*e4b17023SJohn Marino _ThreadIndex __num_threads = __get_max_threads(); 222*e4b17023SJohn Marino # pragma omp parallel shared(__result) num_threads(__num_threads) 223*e4b17023SJohn Marino { 224*e4b17023SJohn Marino # pragma omp single 225*e4b17023SJohn Marino __num_threads = omp_get_num_threads(); 226*e4b17023SJohn Marino 227*e4b17023SJohn Marino // Not within first __k elements -> start parallel. 228*e4b17023SJohn Marino _ThreadIndex __iam = omp_get_thread_num(); 229*e4b17023SJohn Marino 230*e4b17023SJohn Marino _DifferenceType __block_size = 231*e4b17023SJohn Marino std::max<_DifferenceType>(1, __scale_factor * __next_block_start); 232*e4b17023SJohn Marino _DifferenceType __start = __fetch_and_add<_DifferenceType> 233*e4b17023SJohn Marino (&__next_block_start, __block_size); 234*e4b17023SJohn Marino 235*e4b17023SJohn Marino // Get new block, update pointer to next block. 236*e4b17023SJohn Marino _DifferenceType __stop = 237*e4b17023SJohn Marino std::min<_DifferenceType>(__length, __start + __block_size); 238*e4b17023SJohn Marino 239*e4b17023SJohn Marino std::pair<_RAIter1, _RAIter2> __local_result; 240*e4b17023SJohn Marino 241*e4b17023SJohn Marino while (__start < __length) 242*e4b17023SJohn Marino { 243*e4b17023SJohn Marino # pragma omp flush(__result) 244*e4b17023SJohn Marino // Get new value of result. 245*e4b17023SJohn Marino if (__result < __start) 246*e4b17023SJohn Marino { 247*e4b17023SJohn Marino // No chance to find first element. 248*e4b17023SJohn Marino break; 249*e4b17023SJohn Marino } 250*e4b17023SJohn Marino 251*e4b17023SJohn Marino __local_result = __selector._M_sequential_algorithm 252*e4b17023SJohn Marino (__begin1 + __start, __begin1 + __stop, 253*e4b17023SJohn Marino __begin2 + __start, __pred); 254*e4b17023SJohn Marino 255*e4b17023SJohn Marino if (__local_result.first != (__begin1 + __stop)) 256*e4b17023SJohn Marino { 257*e4b17023SJohn Marino omp_set_lock(&__result_lock); 258*e4b17023SJohn Marino if ((__local_result.first - __begin1) < __result) 259*e4b17023SJohn Marino { 260*e4b17023SJohn Marino __result = __local_result.first - __begin1; 261*e4b17023SJohn Marino 262*e4b17023SJohn Marino // Result cannot be in future blocks, stop algorithm. 263*e4b17023SJohn Marino __fetch_and_add<_DifferenceType>(&__next_block_start, 264*e4b17023SJohn Marino __length); 265*e4b17023SJohn Marino } 266*e4b17023SJohn Marino omp_unset_lock(&__result_lock); 267*e4b17023SJohn Marino } 268*e4b17023SJohn Marino 269*e4b17023SJohn Marino _DifferenceType __block_size = 270*e4b17023SJohn Marino std::max<_DifferenceType>(1, __scale_factor * __next_block_start); 271*e4b17023SJohn Marino 272*e4b17023SJohn Marino // Get new block, update pointer to next block. 273*e4b17023SJohn Marino __start = __fetch_and_add<_DifferenceType>(&__next_block_start, 274*e4b17023SJohn Marino __block_size); 275*e4b17023SJohn Marino __stop = 276*e4b17023SJohn Marino std::min<_DifferenceType>(__length, __start + __block_size); 277*e4b17023SJohn Marino } 278*e4b17023SJohn Marino } //parallel 279*e4b17023SJohn Marino 280*e4b17023SJohn Marino omp_destroy_lock(&__result_lock); 281*e4b17023SJohn Marino 282*e4b17023SJohn Marino // Return iterator on found element. 283*e4b17023SJohn Marino return 284*e4b17023SJohn Marino std::pair<_RAIter1, _RAIter2>(__begin1 + __result, 285*e4b17023SJohn Marino __begin2 + __result); 286*e4b17023SJohn Marino } 287*e4b17023SJohn Marino 288*e4b17023SJohn Marino #endif 289*e4b17023SJohn Marino 290*e4b17023SJohn Marino #if _GLIBCXX_FIND_CONSTANT_SIZE_BLOCKS 291*e4b17023SJohn Marino 292*e4b17023SJohn Marino /** 293*e4b17023SJohn Marino * @brief Parallel std::find, constant block size variant. 294*e4b17023SJohn Marino * @param __begin1 Begin iterator of first sequence. 295*e4b17023SJohn Marino * @param __end1 End iterator of first sequence. 296*e4b17023SJohn Marino * @param __begin2 Begin iterator of second sequence. Second __sequence 297*e4b17023SJohn Marino * must have same length as first sequence. 298*e4b17023SJohn Marino * @param __pred Find predicate. 299*e4b17023SJohn Marino * @param __selector _Functionality (e. g. std::find_if(), std::equal(),...) 300*e4b17023SJohn Marino * @return Place of finding in both sequences. 301*e4b17023SJohn Marino * @see __gnu_parallel::_Settings::find_sequential_search_size 302*e4b17023SJohn Marino * @see __gnu_parallel::_Settings::find_block_size 303*e4b17023SJohn Marino * There are two main differences between the growing blocks and the 304*e4b17023SJohn Marino * constant-size blocks variants. 305*e4b17023SJohn Marino * 1. For GB, the block size grows; for CSB, the block size is fixed. 306*e4b17023SJohn Marino * 2. For GB, the blocks are allocated dynamically; for CSB, the 307*e4b17023SJohn Marino * blocks are allocated in a predetermined manner, namely spacial 308*e4b17023SJohn Marino * round-robin. 309*e4b17023SJohn Marino */ 310*e4b17023SJohn Marino template<typename _RAIter1, 311*e4b17023SJohn Marino typename _RAIter2, 312*e4b17023SJohn Marino typename _Pred, 313*e4b17023SJohn Marino typename _Selector> 314*e4b17023SJohn Marino std::pair<_RAIter1, _RAIter2> __find_template(_RAIter1 __begin1,_RAIter1 __end1,_RAIter2 __begin2,_Pred __pred,_Selector __selector,constant_size_blocks_tag)315*e4b17023SJohn Marino __find_template(_RAIter1 __begin1, _RAIter1 __end1, 316*e4b17023SJohn Marino _RAIter2 __begin2, _Pred __pred, _Selector __selector, 317*e4b17023SJohn Marino constant_size_blocks_tag) 318*e4b17023SJohn Marino { 319*e4b17023SJohn Marino _GLIBCXX_CALL(__end1 - __begin1) 320*e4b17023SJohn Marino typedef std::iterator_traits<_RAIter1> _TraitsType; 321*e4b17023SJohn Marino typedef typename _TraitsType::difference_type _DifferenceType; 322*e4b17023SJohn Marino typedef typename _TraitsType::value_type _ValueType; 323*e4b17023SJohn Marino 324*e4b17023SJohn Marino const _Settings& __s = _Settings::get(); 325*e4b17023SJohn Marino 326*e4b17023SJohn Marino _DifferenceType __length = __end1 - __begin1; 327*e4b17023SJohn Marino 328*e4b17023SJohn Marino _DifferenceType __sequential_search_size = std::min<_DifferenceType> 329*e4b17023SJohn Marino (__length, __s.find_sequential_search_size); 330*e4b17023SJohn Marino 331*e4b17023SJohn Marino // Try it sequentially first. 332*e4b17023SJohn Marino std::pair<_RAIter1, _RAIter2> 333*e4b17023SJohn Marino __find_seq_result = __selector._M_sequential_algorithm 334*e4b17023SJohn Marino (__begin1, __begin1 + __sequential_search_size, __begin2, __pred); 335*e4b17023SJohn Marino 336*e4b17023SJohn Marino if (__find_seq_result.first != (__begin1 + __sequential_search_size)) 337*e4b17023SJohn Marino return __find_seq_result; 338*e4b17023SJohn Marino 339*e4b17023SJohn Marino _DifferenceType __result = __length; 340*e4b17023SJohn Marino omp_lock_t __result_lock; 341*e4b17023SJohn Marino omp_init_lock(&__result_lock); 342*e4b17023SJohn Marino 343*e4b17023SJohn Marino // Not within first __sequential_search_size elements -> start parallel. 344*e4b17023SJohn Marino 345*e4b17023SJohn Marino _ThreadIndex __num_threads = __get_max_threads(); 346*e4b17023SJohn Marino # pragma omp parallel shared(__result) num_threads(__num_threads) 347*e4b17023SJohn Marino { 348*e4b17023SJohn Marino # pragma omp single 349*e4b17023SJohn Marino __num_threads = omp_get_num_threads(); 350*e4b17023SJohn Marino 351*e4b17023SJohn Marino _ThreadIndex __iam = omp_get_thread_num(); 352*e4b17023SJohn Marino _DifferenceType __block_size = __s.find_initial_block_size; 353*e4b17023SJohn Marino 354*e4b17023SJohn Marino // First element of thread's current iteration. 355*e4b17023SJohn Marino _DifferenceType __iteration_start = __sequential_search_size; 356*e4b17023SJohn Marino 357*e4b17023SJohn Marino // Where to work (initialization). 358*e4b17023SJohn Marino _DifferenceType __start = __iteration_start + __iam * __block_size; 359*e4b17023SJohn Marino _DifferenceType __stop = std::min<_DifferenceType>(__length, 360*e4b17023SJohn Marino __start 361*e4b17023SJohn Marino + __block_size); 362*e4b17023SJohn Marino 363*e4b17023SJohn Marino std::pair<_RAIter1, _RAIter2> __local_result; 364*e4b17023SJohn Marino 365*e4b17023SJohn Marino while (__start < __length) 366*e4b17023SJohn Marino { 367*e4b17023SJohn Marino // Get new value of result. 368*e4b17023SJohn Marino # pragma omp flush(__result) 369*e4b17023SJohn Marino // No chance to find first element. 370*e4b17023SJohn Marino if (__result < __start) 371*e4b17023SJohn Marino break; 372*e4b17023SJohn Marino 373*e4b17023SJohn Marino __local_result = __selector._M_sequential_algorithm 374*e4b17023SJohn Marino (__begin1 + __start, __begin1 + __stop, 375*e4b17023SJohn Marino __begin2 + __start, __pred); 376*e4b17023SJohn Marino 377*e4b17023SJohn Marino if (__local_result.first != (__begin1 + __stop)) 378*e4b17023SJohn Marino { 379*e4b17023SJohn Marino omp_set_lock(&__result_lock); 380*e4b17023SJohn Marino if ((__local_result.first - __begin1) < __result) 381*e4b17023SJohn Marino __result = __local_result.first - __begin1; 382*e4b17023SJohn Marino omp_unset_lock(&__result_lock); 383*e4b17023SJohn Marino // Will not find better value in its interval. 384*e4b17023SJohn Marino break; 385*e4b17023SJohn Marino } 386*e4b17023SJohn Marino 387*e4b17023SJohn Marino __iteration_start += __num_threads * __block_size; 388*e4b17023SJohn Marino 389*e4b17023SJohn Marino // Where to work. 390*e4b17023SJohn Marino __start = __iteration_start + __iam * __block_size; 391*e4b17023SJohn Marino __stop = std::min<_DifferenceType>(__length, 392*e4b17023SJohn Marino __start + __block_size); 393*e4b17023SJohn Marino } 394*e4b17023SJohn Marino } //parallel 395*e4b17023SJohn Marino 396*e4b17023SJohn Marino omp_destroy_lock(&__result_lock); 397*e4b17023SJohn Marino 398*e4b17023SJohn Marino // Return iterator on found element. 399*e4b17023SJohn Marino return std::pair<_RAIter1, _RAIter2>(__begin1 + __result, 400*e4b17023SJohn Marino __begin2 + __result); 401*e4b17023SJohn Marino } 402*e4b17023SJohn Marino #endif 403*e4b17023SJohn Marino } // end namespace 404*e4b17023SJohn Marino 405*e4b17023SJohn Marino #endif /* _GLIBCXX_PARALLEL_FIND_H */ 406