// Copyright (c) 2020 GeometryFactory (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.1/STL_Extension/include/CGAL/for_each.h $ // $Id: for_each.h 6ae64e7 2020-03-27T16:41:53+01:00 Andreas Fabri // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Simon Giraudot #ifndef CGAL_FOR_EACH_H #define CGAL_FOR_EACH_H #include #ifdef CGAL_LINKED_WITH_TBB #include #include #include #endif // CGAL_LINKED_WITH_TBB /* CGAL::for_each(Range, Function) does the following: - if Sequential_tag is used, apply Function to all elements of Range - if Parallel_tag is used: * static assert that TBB is available * if Range has random access iterators, use a TBB parallel_for loop to apply Function to all elements of Range * if Range doesn't have random access iterators, first copy the iterators in a vector and then use a TBB parallel_for loop to apply Function to all elements of Range The loop is interrupted if `functor` returns false (it carries on until the end otherwise). */ namespace CGAL { namespace internal { template void for_each (RangeRef range, const std::function::type>::reference)>& functor, const Sequential_tag&, IteratorCategory) { for (typename std::iterator_traits ::type>::reference r : range) if (!functor(r)) break; } #ifdef CGAL_LINKED_WITH_TBB template void for_each (RangeRef range, const Fct& functor, const Parallel_tag&, IteratorCategory) { std::size_t range_size = std::distance (range.begin(), range.end()); std::vector::type> iterators; iterators.reserve (range_size); for (typename Range_iterator_type::type it = range.begin(); it != range.end(); ++ it) iterators.push_back (it); tbb::parallel_for (tbb::blocked_range(0, range_size), [&](const tbb::blocked_range& r) { for (std::size_t i = r.begin(); i != r.end(); ++ i) if (!functor (*(iterators[i]))) break; }); } template void for_each (RangeRef range, const Fct& functor, const Parallel_tag&, std::random_access_iterator_tag) { std::size_t range_size = std::distance (range.begin(), range.end()); tbb::parallel_for (tbb::blocked_range(0, range_size), [&](const tbb::blocked_range& r) { for (std::size_t i = r.begin(); i != r.end(); ++ i) if (!functor (*(range.begin() + i))) break; }); } #endif } // namespace internal template void for_each (const Range& range, const std::function::reference)>& functor) { #ifndef CGAL_LINKED_WITH_TBB CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #endif internal::for_each (range, functor, ConcurrencyTag(), typename std::iterator_traits::iterator_category()); } template void for_each (Range& range, const std::function::reference)>& functor) { #ifndef CGAL_LINKED_WITH_TBB CGAL_static_assertion_msg (!(boost::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); #endif internal::for_each (range, functor, ConcurrencyTag(), typename std::iterator_traits::iterator_category()); } } // namespace CGAL #endif // CGAL_FOR_EACH_H