#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H
#include <__algorithm/lower_bound.h>
+#include <__algorithm/max.h>
#include <__algorithm/upper_bound.h>
#include <__atomic/atomic.h>
#include <__config>
#include <__exception/terminate.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/move_iterator.h>
+#include <__memory/allocator.h>
#include <__memory/construct_at.h>
#include <__memory/unique_ptr.h>
-#include <__memory_resource/memory_resource.h>
#include <__numeric/reduce.h>
#include <__utility/exception_guard.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#include <__utility/terminate_on_exception.h>
#include <cstddef>
#include <new>
-#include <vector>
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
ptrdiff_t __first_chunk_size_;
};
-[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI pmr::memory_resource* __get_memory_resource();
[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI __chunk_partitions __partition_chunks(ptrdiff_t __size);
template <class _RandomAccessIterator, class _Functor>
}
using __merge_range_t = __merge_range<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3>;
+ auto const __n_ranges = __partitions.__chunk_count_ + 1;
- vector<__merge_range_t> __ranges;
- __ranges.reserve(__partitions.__chunk_count_ + 1);
+ // TODO: use __uninitialized_buffer
+ auto __destroy = [=](__merge_range_t* __ptr) {
+ std::destroy_n(__ptr, __n_ranges);
+ std::allocator<__merge_range_t>().deallocate(__ptr, __n_ranges);
+ };
+ unique_ptr<__merge_range_t[], decltype(__destroy)> __ranges(
+ std::allocator<__merge_range_t>().allocate(__n_ranges), __destroy);
// TODO: Improve the case where the smaller range is merged into just a few (or even one) chunks of the larger case
std::__terminate_on_exception([&] {
- __ranges.emplace_back(__first1, __first2, __result);
+ __merge_range_t* __r = __ranges.get();
+ std::__construct_at(__r++, __first1, __first2, __result);
bool __iterate_first_range = __last1 - __first1 > __last2 - __first2;
};
// handle first chunk
- __ranges.emplace_back(__compute_chunk(__partitions.__first_chunk_size_));
+ std::__construct_at(__r++, __compute_chunk(__partitions.__first_chunk_size_));
// handle 2 -> N - 1 chunks
for (ptrdiff_t __i = 0; __i != __partitions.__chunk_count_ - 2; ++__i)
- __ranges.emplace_back(__compute_chunk(__partitions.__chunk_size_));
+ std::__construct_at(__r++, __compute_chunk(__partitions.__chunk_size_));
// handle last chunk
- __ranges.emplace_back(__last1, __last2, __result);
+ std::__construct_at(__r, __last1, __last2, __result);
__libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __index) {
auto __first_iters = __ranges[__index];
_Value __init,
_Combiner __combiner,
_Reduction __reduction) {
+ if (__first == __last)
+ return __init;
+
auto __partitions = __libdispatch::__partition_chunks(__last - __first);
auto __destroy = [__count = __partitions.__chunk_count_](_Value* __ptr) {
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
+_LIBCPP_POP_MACROS
+
#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H
#include <__algorithm/pstl_backends/cpu_backends/libdispatch.h>
#include <__config>
#include <dispatch/dispatch.h>
-#include <memory_resource>
#include <thread>
_LIBCPP_BEGIN_NAMESPACE_STD
namespace __par_backend::inline __libdispatch {
-pmr::memory_resource* __get_memory_resource() {
- static std::pmr::synchronized_pool_resource pool{pmr::new_delete_resource()};
- return &pool;
-}
void __dispatch_apply(size_t chunk_count, void* context, void (*func)(void* context, size_t chunk)) noexcept {
::dispatch_apply_f(chunk_count, DISPATCH_APPLY_AUTO, context, func);
}
__chunk_partitions __partition_chunks(ptrdiff_t element_count) {
+ if (element_count == 0) {
+ return __chunk_partitions{1, 0, 0};
+ } else if (element_count == 1) {
+ return __chunk_partitions{1, 0, 1};
+ }
+
__chunk_partitions partitions;
partitions.__chunk_count_ = [&] {
ptrdiff_t cores = std::max(1u, thread::hardware_concurrency());
#include <cstddef>
int main(int, char**) {
- for (std::ptrdiff_t i = 0; i != 2ll << 20; ++i) {
+ {
+ auto chunks = std::__par_backend::__libdispatch::__partition_chunks(0);
+ assert(chunks.__chunk_count_ == 1);
+ assert(chunks.__first_chunk_size_ == 0);
+ assert(chunks.__chunk_size_ == 0);
+ }
+
+ {
+ auto chunks = std::__par_backend::__libdispatch::__partition_chunks(1);
+ assert(chunks.__chunk_count_ == 1);
+ assert(chunks.__first_chunk_size_ == 1);
+ assert(chunks.__chunk_size_ == 0);
+ }
+
+ for (std::ptrdiff_t i = 2; i != 2ll << 20; ++i) {
auto chunks = std::__par_backend::__libdispatch::__partition_chunks(i);
+ assert(chunks.__chunk_count_ >= 1);
assert(chunks.__chunk_count_ <= i);
assert((chunks.__chunk_count_ - 1) * chunks.__chunk_size_ + chunks.__first_chunk_size_ == i);
}