(root)/
gcc-13.2.0/
libstdc++-v3/
include/
pstl/
parallel_impl.h
       1  // -*- C++ -*-
       2  //===-- parallel_impl.h ---------------------------------------------------===//
       3  //
       4  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
       5  // See https://llvm.org/LICENSE.txt for license information.
       6  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
       7  //
       8  //===----------------------------------------------------------------------===//
       9  
      10  #ifndef _PSTL_PARALLEL_IMPL_H
      11  #define _PSTL_PARALLEL_IMPL_H
      12  
      13  #include <atomic>
      14  // This header defines the minimum set of parallel routines required to support Parallel STL,
      15  // implemented on top of Intel(R) Threading Building Blocks (Intel(R) TBB) library
      16  
      17  namespace __pstl
      18  {
      19  namespace __internal
      20  {
      21  
      22  //------------------------------------------------------------------------
      23  // parallel_find
      24  //-----------------------------------------------------------------------
      25  /** Return extremum value returned by brick f[i,j) for subranges [i,j) of [first,last)
      26  Each f[i,j) must return a value in [i,j). */
      27  template <class _ExecutionPolicy, class _Index, class _Brick, class _Compare>
      28  _Index
      29  __parallel_find(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f, _Compare __comp, bool __b_first)
      30  {
      31      typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType;
      32      const _DifferenceType __n = __last - __first;
      33      _DifferenceType __initial_dist = __b_first ? __n : -1;
      34      std::atomic<_DifferenceType> __extremum(__initial_dist);
      35      // TODO: find out what is better here: parallel_for or parallel_reduce
      36      __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
      37                                    [__comp, __f, __first, &__extremum](_Index __i, _Index __j) {
      38                                        // See "Reducing Contention Through Priority Updates", PPoPP '13, for discussion of
      39                                        // why using a shared variable scales fairly well in this situation.
      40                                        if (__comp(__i - __first, __extremum))
      41                                        {
      42                                            _Index __res = __f(__i, __j);
      43                                            // If not '__last' returned then we found what we want so put this to extremum
      44                                            if (__res != __j)
      45                                            {
      46                                                const _DifferenceType __k = __res - __first;
      47                                                for (_DifferenceType __old = __extremum; __comp(__k, __old);
      48                                                     __old = __extremum)
      49                                                {
      50                                                    __extremum.compare_exchange_weak(__old, __k);
      51                                                }
      52                                            }
      53                                        }
      54                                    });
      55      return __extremum != __initial_dist ? __first + __extremum : __last;
      56  }
      57  
      58  //------------------------------------------------------------------------
      59  // parallel_or
      60  //------------------------------------------------------------------------
      61  //! Return true if brick f[i,j) returns true for some subrange [i,j) of [first,last)
      62  template <class _ExecutionPolicy, class _Index, class _Brick>
      63  bool
      64  __parallel_or(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f)
      65  {
      66      std::atomic<bool> __found(false);
      67      __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
      68                                    [__f, &__found](_Index __i, _Index __j) {
      69                                        if (!__found.load(std::memory_order_relaxed) && __f(__i, __j))
      70                                        {
      71                                            __found.store(true, std::memory_order_relaxed);
      72                                            __par_backend::__cancel_execution();
      73                                        }
      74                                    });
      75      return __found;
      76  }
      77  
      78  } // namespace __internal
      79  } // namespace __pstl
      80  
      81  #endif /* _PSTL_PARALLEL_IMPL_H */