[libcxx-commits] [libcxx] [libc++][pstl] Implementation of parallel std::uninitialized_(copy|move)(_n) based on parallel __for_each (PR #223229)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Sep 13 13:02:54 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Michael G. Kazakov (mikekazakov)
<details>
<summary>Changes</summary>
This PR adds an implementation of parallel versions of `std::uninitialized_copy`, `std::uninitialized_copy_n`, `std::uninitialized_move` and `std::uninitialized_move_n`.
Implementations are mostly one-liners under the hood, but require dealing with iterator ranges, hence `std::uninitialized_copy` and `std::uninitialized_move` are implemented in `cpu_algos`. `std::uninitialized_copy_n` and `std::uninitialized_move_n` are implemented in the `default` backend.
This PR also adds a helper function `__parallel_for_each_iter_pair` that allows applying a function over 2 iterator ranges in parallel, e.g. used like this:
```c++
__parallel_for_each_iter_pair<_Backend>(
first,
last,
result,
[](InputIterator brick_first, InputIterator brick_last, ForwardIterator brick_result) {
std::uninitialized_copy(brick_first, brick_last, brick_result);
});
```
Included tests check that:
- Semantics of the functions is correct.
- The functions correctly SFINAE out when the first argument is not an execution policy.
- The `noexcept` policy is followed.
- `static_assert` verifies iterators' categories.
Fixes #<!-- -->134592
Fixes #<!-- -->134593
Part of #<!-- -->99938
---
Patch is 45.97 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/223229.diff
16 Files Affected:
- (modified) libcxx/include/CMakeLists.txt (+1)
- (modified) libcxx/include/__memory/pstl.h (+61)
- (modified) libcxx/include/__pstl/backend_fwd.h (+28)
- (modified) libcxx/include/__pstl/backends/default.h (+52)
- (modified) libcxx/include/__pstl/backends/libdispatch.h (+9)
- (modified) libcxx/include/__pstl/backends/serial.h (+19)
- (modified) libcxx/include/__pstl/backends/std_thread.h (+9)
- (modified) libcxx/include/__pstl/cpu_algos/for_each.h (+19)
- (added) libcxx/include/__pstl/cpu_algos/uninitialized_algorithms.h (+97)
- (modified) libcxx/include/module.modulemap.in (+3)
- (modified) libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp (+20-1)
- (modified) libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp (+22)
- (added) libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/pstl.uninitialized_copy.pass.cpp (+145)
- (added) libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/pstl.uninitialized_copy_n.pass.cpp (+146)
- (added) libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/pstl.uninitialized_move.pass.cpp (+150)
- (added) libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/pstl.uninitialized_move_n.pass.cpp (+153)
``````````diff
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 113d4fde7ca59..2ec3881db7774 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -711,6 +711,7 @@ set(files
__pstl/cpu_algos/stable_sort.h
__pstl/cpu_algos/transform.h
__pstl/cpu_algos/transform_reduce.h
+ __pstl/cpu_algos/uninitialized_algorithms.h
__pstl/dispatch.h
__pstl/handle_exception.h
__random/bernoulli_distribution.h
diff --git a/libcxx/include/__memory/pstl.h b/libcxx/include/__memory/pstl.h
index c06f53bed7206..6c1fd6f10ee23 100644
--- a/libcxx/include/__memory/pstl.h
+++ b/libcxx/include/__memory/pstl.h
@@ -30,6 +30,7 @@ _LIBCPP_PUSH_MACROS
# include <__type_traits/remove_cvref.h>
# include <__utility/forward.h>
# include <__utility/move.h>
+# include <__utility/pair.h>
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -82,6 +83,36 @@ uninitialized_default_construct_n(_ExecutionPolicy&& __policy, _ForwardIterator
__pstl::__handle_exception<_Implementation>(std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n);
}
+template <class _ExecutionPolicy,
+ class _InputIterator,
+ class _ForwardIterator,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_copy(
+ _ExecutionPolicy&& __policy, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) {
+ _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(_InputIterator, "uninitialized_copy requires InputIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "uninitialized_copy requires ForwardIterators");
+ using _Implementation = __pstl::__dispatch<__pstl::__uninitialized_copy, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__result));
+}
+
+template <class _ExecutionPolicy,
+ class _InputIterator,
+ class _Size,
+ class _ForwardIterator,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator
+uninitialized_copy_n(_ExecutionPolicy&& __policy, _InputIterator __first, _Size __n, _ForwardIterator __result) {
+ _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(_InputIterator, "uninitialized_copy_n requires InputIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "uninitialized_copy_n requires ForwardIterators");
+ using _Implementation =
+ __pstl::__dispatch<__pstl::__uninitialized_copy_n, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n, std::move(__result));
+}
+
template <class _ExecutionPolicy,
class _ForwardIterator,
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
@@ -136,6 +167,36 @@ uninitialized_fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Siz
std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n, __value);
}
+template <class _ExecutionPolicy,
+ class _InputIterator,
+ class _ForwardIterator,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_move(
+ _ExecutionPolicy&& __policy, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) {
+ _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(_InputIterator, "uninitialized_move requires InputIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "uninitialized_move requires ForwardIterators");
+ using _Implementation = __pstl::__dispatch<__pstl::__uninitialized_move, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__result));
+}
+
+template <class _ExecutionPolicy,
+ class _InputIterator,
+ class _Size,
+ class _ForwardIterator,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
+uninitialized_move_n(_ExecutionPolicy&& __policy, _InputIterator __first, _Size __n, _ForwardIterator __result) {
+ _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(_InputIterator, "uninitialized_move_n requires InputIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "uninitialized_move_n requires ForwardIterators");
+ using _Implementation =
+ __pstl::__dispatch<__pstl::__uninitialized_move_n, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy), std::move(__first), __n, std::move(__result));
+}
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_HAS_EXPERIMENTAL_PSTL && _LIBCPP_STD_VER >= 17
diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index 40a335ae1f2ad..570afef8a8a34 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -430,6 +430,20 @@ struct __destroy_n;
// optional<__empty>
// operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept;
+template <class _Backend, class _ExecutionPolicy>
+struct __uninitialized_copy;
+// template <class _Policy, class _InputIterator, class _ForwardIterator>
+// optional<_ForwardIterator>
+// operator()(_Policy&& __policy, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) const
+// noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __uninitialized_copy_n;
+// template <class _Policy, class _InputIterator, class _Size, class _ForwardIterator>
+// optional<_ForwardIterator>
+// operator()(_Policy&& __policy, _InputIterator __first, _Size __n, _ForwardIterator __result) const
+// noexcept;
+
template <class _Backend, class _ExecutionPolicy>
struct __uninitialized_default_construct;
// template <class _Policy, class _ForwardIterator>
@@ -442,6 +456,20 @@ struct __uninitialized_default_construct_n;
// optional<__empty>
// operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n) const noexcept;
+template <class _Backend, class _ExecutionPolicy>
+struct __uninitialized_move;
+// template <class _Policy, class _InputIterator, class _ForwardIterator>
+// optional<_ForwardIterator>
+// operator()(_Policy&& __policy, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) const
+// noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __uninitialized_move_n;
+// template <class _Policy, class _InputIterator, class _Size, class _ForwardIterator>
+// optional<pair<_InputIterator, _ForwardIterator>>
+// operator()(_Policy&& __policy, _InputIterator __first, _Size __n, _ForwardIterator __result) const
+// noexcept;
+
template <class _Backend, class _ExecutionPolicy>
struct __uninitialized_value_construct;
// template <class _Policy, class _ForwardIterator>
diff --git a/libcxx/include/__pstl/backends/default.h b/libcxx/include/__pstl/backends/default.h
index b5d7045bbb9b8..dd67d5fcc84e4 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -29,6 +29,7 @@
#include <__iterator/reverse_iterator.h>
#include <__memory/addressof.h>
#include <__memory/construct_at.h>
+#include <__memory/uninitialized_algorithms.h>
#include <__optional/comparison.h>
#include <__optional/nullopt_t.h>
#include <__optional/optional.h>
@@ -151,6 +152,14 @@ namespace __pstl {
// - reverse_copy
// - rotate_copy
//
+// uninitialized_copy family
+// -------------------------------------
+// - uninitialized_copy_n
+//
+// uninitialized_move family
+// -------------------------------------
+// - uninitialized_move_n
+//
//////////////////////////////////////////////////////////////
// find_if family
@@ -906,6 +915,49 @@ struct __adjacent_difference<__default_backend_tag, _ExecutionPolicy> {
}
};
+//////////////////////////////////////////////////////////////
+// uninitialized_copy family
+//////////////////////////////////////////////////////////////
+
+template <class _ExecutionPolicy>
+struct __uninitialized_copy_n<__default_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _InputIterator, class _Size, class _ForwardIterator>
+ optional<_ForwardIterator>
+ operator()(_Policy&& __policy, _InputIterator __first, _Size __n, _ForwardIterator __result) const noexcept {
+ if constexpr (__has_random_access_iterator_category_or_concept<_InputIterator>::value &&
+ __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
+ using _UninitializedCopy = __dispatch<__uninitialized_copy, __current_configuration, _ExecutionPolicy>;
+ _InputIterator __last = __first + __n;
+ return _UninitializedCopy()(__policy, std::move(__first), std::move(__last), std::move(__result));
+ } else {
+ return std::uninitialized_copy_n(std::move(__first), __n, std::move(__result));
+ }
+ }
+};
+
+//////////////////////////////////////////////////////////////
+// uninitialized_move family
+//////////////////////////////////////////////////////////////
+
+template <class _ExecutionPolicy>
+struct __uninitialized_move_n<__default_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _InputIterator, class _Size, class _ForwardIterator>
+ optional<pair<_InputIterator, _ForwardIterator>>
+ operator()(_Policy&& __policy, _InputIterator __first, _Size __n, _ForwardIterator __result) const noexcept {
+ if constexpr (__has_random_access_iterator_category_or_concept<_InputIterator>::value &&
+ __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
+ using _UninitializedMove = __dispatch<__uninitialized_move, __current_configuration, _ExecutionPolicy>;
+ _InputIterator __last = __first + __n;
+ auto __res = _UninitializedMove()(__policy, std::move(__first), __last, std::move(__result));
+ if (!__res)
+ return nullopt; // Failed to run the parallel algorithm, propagate the failure
+ return pair{__last, *__res};
+ } else {
+ return std::uninitialized_move_n(std::move(__first), __n, std::move(__result));
+ }
+ }
+};
+
} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__pstl/backends/libdispatch.h b/libcxx/include/__pstl/backends/libdispatch.h
index dbd9fa34e1f87..5b245373eb16b 100644
--- a/libcxx/include/__pstl/backends/libdispatch.h
+++ b/libcxx/include/__pstl/backends/libdispatch.h
@@ -51,6 +51,7 @@
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>
+#include <__pstl/cpu_algos/uninitialized_algorithms.h>
#include <__utility/empty.h>
#include <__utility/exception_guard.h>
#include <__utility/move.h>
@@ -439,6 +440,14 @@ template <class _ExecutionPolicy>
struct __fill<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_fill<__libdispatch_backend_tag, _ExecutionPolicy> {};
+template <class _ExecutionPolicy>
+struct __uninitialized_copy<__libdispatch_backend_tag, _ExecutionPolicy>
+ : __cpu_parallel_uninitialized_copy<__libdispatch_backend_tag, _ExecutionPolicy> {};
+
+template <class _ExecutionPolicy>
+struct __uninitialized_move<__libdispatch_backend_tag, _ExecutionPolicy>
+ : __cpu_parallel_uninitialized_move<__libdispatch_backend_tag, _ExecutionPolicy> {};
+
} // namespace __pstl
_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__pstl/backends/serial.h b/libcxx/include/__pstl/backends/serial.h
index 85c73b0f15db5..c779d583089d2 100644
--- a/libcxx/include/__pstl/backends/serial.h
+++ b/libcxx/include/__pstl/backends/serial.h
@@ -24,6 +24,7 @@
#include <__algorithm/stable_sort.h>
#include <__algorithm/transform.h>
#include <__config>
+#include <__memory/uninitialized_algorithms.h>
#include <__numeric/transform_reduce.h>
#include <__optional/optional.h>
#include <__pstl/backend_fwd.h>
@@ -284,6 +285,24 @@ struct __transform_reduce_binary<__serial_backend_tag, _ExecutionPolicy> {
}
};
+template <class _ExecutionPolicy>
+struct __uninitialized_copy<__serial_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _InputIterator, class _ForwardIterator>
+ _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
+ operator()(_Policy&&, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) const noexcept {
+ return std::uninitialized_copy(std::move(__first), std::move(__last), std::move(__result));
+ }
+};
+
+template <class _ExecutionPolicy>
+struct __uninitialized_move<__serial_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _InputIterator, class _ForwardIterator>
+ _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
+ operator()(_Policy&&, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) const noexcept {
+ return std::uninitialized_move(std::move(__first), std::move(__last), std::move(__result));
+ }
+};
+
} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__pstl/backends/std_thread.h b/libcxx/include/__pstl/backends/std_thread.h
index bc7fc020867f8..bdbddb9d36300 100644
--- a/libcxx/include/__pstl/backends/std_thread.h
+++ b/libcxx/include/__pstl/backends/std_thread.h
@@ -30,6 +30,7 @@
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>
+#include <__pstl/cpu_algos/uninitialized_algorithms.h>
#include <__utility/empty.h>
#include <__utility/move.h>
@@ -170,6 +171,14 @@ template <class _ExecutionPolicy>
struct __fill<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_fill<__std_thread_backend_tag, _ExecutionPolicy> {};
+template <class _ExecutionPolicy>
+struct __uninitialized_copy<__std_thread_backend_tag, _ExecutionPolicy>
+ : __cpu_parallel_uninitialized_copy<__std_thread_backend_tag, _ExecutionPolicy> {};
+
+template <class _ExecutionPolicy>
+struct __uninitialized_move<__std_thread_backend_tag, _ExecutionPolicy>
+ : __cpu_parallel_uninitialized_move<__std_thread_backend_tag, _ExecutionPolicy> {};
+
} // namespace __pstl
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__pstl/cpu_algos/for_each.h b/libcxx/include/__pstl/cpu_algos/for_each.h
index 908f82f01e6c8..91ec0dfdc59f3 100644
--- a/libcxx/include/__pstl/cpu_algos/for_each.h
+++ b/libcxx/include/__pstl/cpu_algos/for_each.h
@@ -18,6 +18,7 @@
#include <__pstl/cpu_algos/cpu_traits.h>
#include <__type_traits/is_execution_policy.h>
#include <__utility/empty.h>
+#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -37,6 +38,24 @@ _LIBCPP_HIDE_FROM_ABI _Iterator __simd_for_each(_Iterator __first, _DifferenceTy
return __first + __n;
}
+// Applies the 3-legged function to sub-ranges of the input ranges in parallel:
+// f(sub_range1_first, sub_range1_last, sub_range2_first)
+template <class _Backend, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BrickFunction>
+_LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_for_each_iter_pair(
+ _RandomAccessIterator1 __first1,
+ _RandomAccessIterator1 __last1,
+ _RandomAccessIterator2 __first2,
+ _BrickFunction __f) {
+ return __cpu_traits<_Backend>::__for_each(
+ __first1,
+ __last1,
+ [__first1, __first2, __f = std::move(__f)](
+ _RandomAccessIterator1 __brick_first1, _RandomAccessIterator1 __brick_last1) {
+ _RandomAccessIterator2 __brick_first2 = __first2 + (__brick_first1 - __first1);
+ __f(__brick_first1, __brick_last1, __brick_first2);
+ });
+}
+
template <class _Backend, class _RawExecutionPolicy>
struct __cpu_parallel_for_each {
template <class _Policy, class _ForwardIterator, class _Function>
diff --git a/libcxx/include/__pstl/cpu_algos/uninitialized_algorithms.h b/libcxx/include/__pstl/cpu_algos/uninitialized_algorithms.h
new file mode 100644
index 0000000000000..861868c6ae6fa
--- /dev/null
+++ b/libcxx/include/__pstl/cpu_algos/uninitialized_algorithms.h
@@ -0,0 +1,97 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___PSTL_CPU_ALGOS_UNINITIALIZED_ALGORITHMS_H
+#define _LIBCPP___PSTL_CPU_ALGOS_UNINITIALIZED_ALGORITHMS_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__memory/uninitialized_algorithms.h>
+#include <__optional/nullopt_t.h>
+#include <__optional/optional.h>
+#include <__pstl/backend_fwd.h>
+#include <__pstl/cpu_algos/cpu_traits.h>
+#include <__pstl/cpu_algos/for_each.h>
+#include <__type_traits/is_execution_policy.h>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace __pstl {
+
+template <class _Backend, class _RawExecutionPolicy>
+struct __cpu_parallel_uninitialized_copy {
+ template <class _Policy, class _InputIterator, class _ForwardIterator>
+ _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
+ operator()(_Policy&&, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) const noexcept {
+ if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> &&
+ __has_random_access_iterator_category_or_concept<_InputIterator>::value &&
+ __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
+ auto __res = __pstl::__parallel_for_each_iter_pair<_Backend>(
+ __first,
+ __last,
+ __result,
+ [](_InputIterator __brick_first, _InputIterator __brick_last, _ForwardIterator __brick_result) {
+ std::uninitialized_copy(std::move(__brick_first), std::move(__brick_last), std::move(__brick_result));
+ });
+ if (!__res) {
+ return std::nullopt; // Failed to run the algorithm, propagate the error.
+ }
+ return __result + (__last - __first);
+ } else {
+ // Non-random access iterators cannot be processed in parallel, fall back to the sequential implementation.
+ return std::uninitialized_copy(std::move(__first), std::move(__last), std::move(__result));
+ }
+ }
+};
+
+template <class _Backend, class _RawExecutionPolicy>
+struct __cpu_parallel_uninitialized_move {
+ template <class _Policy, class _InputIterator, class _ForwardIterator>
+ _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
+ operator()(_Policy&&, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) const noexcept {
+ if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> &&
+ __has_random_access_iterator_category_or_concept<_InputIterator>::value &&
+ __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
+ auto __res = __pstl::__parallel_for_each_iter_pair<_Backend>(
+ __first,
+ __last,
+ __result,
+ [](_InputIterator __brick_first, _InputIterator __brick_last, _ForwardIterator __brick_result) {
+ std::uninitialized_move(std::move(__brick_first), std::move(__brick_last), std::move(__brick_result));
+ });
+ if (!__res) {
+ return std::nullopt; // Failed to run the algorithm, propagate the error.
+ }
+ return __result + (__last - __first);
+ } else {
+ // Non-random access iterators cannot be processed in parallel, fall back to the sequenti...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/223229
More information about the libcxx-commits
mailing list