// Copyright (c) 2020 GeometryFactory (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL$ // $Id$ // 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 namespace CGAL { namespace internal { // To emulate either a "break" in sequential and a "return" in // parallel, we use an interal throw/catch mechanism struct stop_for_each : public std::exception { }; template void for_each (RangeRef range, const std::function::type>::reference)>& functor, const Sequential_tag&, const IteratorCategory&) { for (typename std::iterator_traits ::type>::reference r : range) try { functor(r); } catch (const stop_for_each&) { break; } } #ifdef CGAL_LINKED_WITH_TBB template void for_each (RangeRef range, const std::function::type>::reference)>& functor, const Parallel_tag&, const 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) try { functor (*(iterators[i])); } catch (const stop_for_each&) { return; } }); } template void for_each (RangeRef range, const std::function::type>::reference)>& functor, const Parallel_tag&, const 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) try { functor (*(range.begin() + i)); } catch (const stop_for_each&) { return; } }); } #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