Index: pstl/CMakeLists.txt =================================================================== --- pstl/CMakeLists.txt +++ pstl/CMakeLists.txt @@ -29,19 +29,19 @@ add_library(ParallelSTL INTERFACE) add_library(pstl::ParallelSTL ALIAS ParallelSTL) +target_compile_features(ParallelSTL INTERFACE cxx_std_17) if (PARALLELSTL_USE_PARALLEL_POLICIES) - if (PARALLELSTL_BACKEND STREQUAL "tbb") + if (PARALLELSTL_BACKEND STREQUAL "serial") + message(STATUS "Parallel STL uses the serial backend") + target_compile_definitions(ParallelSTL INTERFACE -D__PSTL_PAR_BACKEND_SERIAL) + elseif (PARALLELSTL_BACKEND STREQUAL "tbb") find_package(TBB 2018 REQUIRED tbb OPTIONAL_COMPONENTS tbbmalloc) message(STATUS "Parallel STL uses TBB ${TBB_VERSION} (interface version: ${TBB_INTERFACE_VERSION})") target_link_libraries(ParallelSTL INTERFACE TBB::tbb) + target_compile_definitions(ParallelSTL INTERFACE -D__PSTL_PAR_BACKEND_TBB) else() - if (TARGET ${PARALLELSTL_BACKEND}) - target_link_libraries(ParallelSTL INTERFACE ${PARALLELSTL_BACKEND}) - else() - find_package(${PARALLELSTL_BACKEND} REQUIRED) - target_link_libraries(ParallelSTL INTERFACE ${${PARALLELSTL_BACKEND}_IMPORTED_TARGETS}) - endif() + message(FATAL_ERROR "Requested unknown Parallel STL backend '${PARALLELSTL_BACKEND}'.") endif() else() target_compile_definitions(ParallelSTL INTERFACE PSTL_USE_PARALLEL_POLICIES=0) Index: pstl/include/pstl/internal/parallel_backend.h =================================================================== --- pstl/include/pstl/internal/parallel_backend.h +++ pstl/include/pstl/internal/parallel_backend.h @@ -10,7 +10,9 @@ #ifndef __PSTL_parallel_backend_H #define __PSTL_parallel_backend_H -#if __PSTL_PAR_BACKEND_TBB +#if defined(__PSTL_PAR_BACKEND_SERIAL) +#include "parallel_backend_serial.h" +#elif defined(__PSTL_PAR_BACKEND_TBB) #include "parallel_backend_tbb.h" #else __PSTL_PRAGMA_MESSAGE("Parallel backend was not specified"); Index: pstl/include/pstl/internal/parallel_backend_serial.h =================================================================== --- /dev/null +++ pstl/include/pstl/internal/parallel_backend_serial.h @@ -0,0 +1,123 @@ +// -*- C++ -*- +//===-- parallel_backend_serial.h -----------------------------------------===// +// +// 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 __PSTL_parallel_backend_serial_H +#define __PSTL_parallel_backend_serial_H + +#include +#include +#include +#include +#include + + +namespace __pstl { namespace __serial { + +template +class buffer +{ + std::allocator<_Tp> __allocator_; + _Tp* __ptr_; + const std::size_t __buf_size_; + buffer(const buffer&) = delete; + void operator=(const buffer&) = delete; + + public: + buffer(std::size_t __n) + : __allocator_() + , __ptr_(__allocator_.allocate(__n)) + , __buf_size_(__n) + { } + + operator bool() const { return __ptr_ != nullptr; } + _Tp* get() const { return __ptr_; } + ~buffer() { __allocator_.deallocate(__ptr_, __buf_size_); } +}; + +inline void cancel_execution() { } + +template +void parallel_for(_ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f) +{ + __f(__first, __last); +} + +template +_Value +parallel_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, const _Value& __identity, + const _RealBody& __real_body, const _Reduction&) +{ + if (__first == __last) { + return __identity; + } else { + return __real_body(__first, __last, __identity); + } +} + +template +_Tp +parallel_transform_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) +{ + return __reduce(__first, __last, __init); +} + +template +void +parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) +{ + _Tp __sum = __initial; + if (__n) + __sum = __combine(__sum, __reduce(_Index(0), __n)); + __apex(__sum); + if (__n) + __scan(_Index(0), __n, __initial); +} + +template +_Tp +parallel_transform_scan(_ExecutionPolicy&&, _Index __n, _UnaryOp, _Tp __init, _BinaryOp, _Reduce, _Scan __scan) +{ + return __scan(_Index(0), __n, __init); +} + +template +void +parallel_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort, std::size_t __nsort = 0) +{ + // TODO: What to do with __nsort? + __leaf_sort(__first, __last, __comp); +} + +template +void +parallel_merge(_ExecutionPolicy&&, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __out, + _Compare __comp, + _LeafMerge __leaf_merge) +{ + __leaf_merge(__first1, __last1, __first2, __last2, __out, __comp); +} + +template +void +parallel_invoke(_ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) +{ + std::forward<_F1>(__f1)(); + std::forward<_F2>(__f2)(); +} + +}} // namespace __pstl::__serial + +namespace __pstl { namespace par_backend { + using namespace __pstl::__serial; // TODO: We need a better way to customize the backend +}} + +#endif /* __PSTL_parallel_backend_serial_H */ Index: pstl/include/pstl/internal/pstl_config.h =================================================================== --- pstl/include/pstl/internal/pstl_config.h +++ pstl/include/pstl/internal/pstl_config.h @@ -23,12 +23,8 @@ #define __PSTL_USE_PAR_POLICIES 1 #endif -#if __PSTL_USE_PAR_POLICIES -#if !defined(__PSTL_PAR_BACKEND_TBB) -#define __PSTL_PAR_BACKEND_TBB 1 -#endif -#else -#undef __PSTL_PAR_BACKEND_TBB +#if !defined(__PSTL_PAR_BACKEND_SERIAL) && !defined(__PSTL_PAR_BACKEND_TBB) +# error "The parallel backend is neither serial nor TBB" #endif // Check the user-defined macro for warnings