From 91d2c770496b35dbb265c664e782ee7441f48543 Mon Sep 17 00:00:00 2001 From: Rishabh Dwivedi Date: Mon, 1 Jan 2024 13:38:50 +0530 Subject: [PATCH] trying cpm package manager --- CMakeLists.txt | 18 +- build | 2 +- conanfile.txt | 6 - .../__detail/__atomic_intrusive_queue.hpp | 86 - lib/exec/__detail/__atomic_ref.hpp | 64 - lib/exec/__detail/__basic_sequence.hpp | 141 - lib/exec/__detail/__bit_cast.hpp | 51 - lib/exec/__detail/__bwos_lifo_queue.hpp | 494 -- lib/exec/__detail/__manual_lifetime.hpp | 74 - lib/exec/__detail/__sender_facade.hpp | 380 - lib/exec/__detail/__xorshift.hpp | 70 - lib/exec/any_sender_of.hpp | 1206 ---- lib/exec/async_scope.hpp | 731 -- lib/exec/at_coroutine_exit.hpp | 242 - lib/exec/create.hpp | 96 - lib/exec/env.hpp | 119 - lib/exec/finally.hpp | 298 - lib/exec/inline_scheduler.hpp | 26 - .../linux/__detail/memory_mapped_region.hpp | 66 - .../linux/__detail/safe_file_descriptor.hpp | 66 - lib/exec/linux/io_uring_context.hpp | 1174 ---- lib/exec/linux/memory_mapped_region.hpp | 47 - lib/exec/linux/safe_file_descriptor.hpp | 46 - lib/exec/materialize.hpp | 221 - lib/exec/on.hpp | 35 - lib/exec/on_coro_disposition.hpp | 212 - lib/exec/repeat_effect_until.hpp | 225 - lib/exec/scope.hpp | 34 - lib/exec/sequence/any_sequence_of.hpp | 365 - lib/exec/sequence/empty_sequence.hpp | 67 - lib/exec/sequence/ignore_all_values.hpp | 328 - lib/exec/sequence/iterate.hpp | 218 - lib/exec/sequence/transform_each.hpp | 205 - lib/exec/sequence_senders.hpp | 455 -- lib/exec/single_thread_context.hpp | 47 - lib/exec/static_thread_pool.hpp | 1317 ---- lib/exec/task.hpp | 515 -- lib/exec/timed_scheduler.hpp | 185 - lib/exec/trampoline_scheduler.hpp | 186 - lib/exec/variant_sender.hpp | 135 - lib/exec/when_any.hpp | 288 - lib/nvexec/README.md | 27 - lib/nvexec/detail/config.cuh | 28 - lib/nvexec/detail/cuda_atomic.cuh | 76 - lib/nvexec/detail/cuda_fwd.cuh | 74 - lib/nvexec/detail/memory.cuh | 369 - lib/nvexec/detail/queue.cuh | 133 - lib/nvexec/detail/throw_on_cuda_error.cuh | 51 - lib/nvexec/detail/variant.cuh | 233 - lib/nvexec/multi_gpu_context.cuh | 285 - lib/nvexec/nvtx.cuh | 165 - lib/nvexec/stream/algorithm_base.cuh | 142 - lib/nvexec/stream/bulk.cuh | 385 - lib/nvexec/stream/common.cuh | 811 --- lib/nvexec/stream/ensure_started.cuh | 368 - lib/nvexec/stream/launch.cuh | 188 - lib/nvexec/stream/let_xxx.cuh | 260 - lib/nvexec/stream/reduce.cuh | 159 - lib/nvexec/stream/schedule_from.cuh | 232 - lib/nvexec/stream/split.cuh | 350 - lib/nvexec/stream/start_detached.cuh | 44 - lib/nvexec/stream/submit.cuh | 67 - lib/nvexec/stream/sync_wait.cuh | 192 - lib/nvexec/stream/then.cuh | 204 - lib/nvexec/stream/transfer.cuh | 169 - lib/nvexec/stream/upon_error.cuh | 187 - lib/nvexec/stream/upon_stopped.cuh | 162 - lib/nvexec/stream/when_all.cuh | 431 -- lib/nvexec/stream_context.cuh | 334 - lib/stdexec/__detail/__basic_sender.hpp | 705 -- lib/stdexec/__detail/__concepts.hpp | 103 - lib/stdexec/__detail/__config.hpp | 371 - lib/stdexec/__detail/__domain.hpp | 255 - lib/stdexec/__detail/__env.hpp | 487 -- lib/stdexec/__detail/__execution_fwd.hpp | 215 - lib/stdexec/__detail/__force_include.hpp | 23 - lib/stdexec/__detail/__intrusive_ptr.hpp | 177 - lib/stdexec/__detail/__intrusive_queue.hpp | 243 - lib/stdexec/__detail/__meta.hpp | 1177 ---- lib/stdexec/__detail/__p2300.hpp | 343 - lib/stdexec/__detail/__ranges.hpp | 109 - lib/stdexec/__detail/__scope.hpp | 100 - lib/stdexec/__detail/__tuple.hpp | 103 - lib/stdexec/__detail/__type_traits.hpp | 177 - lib/stdexec/concepts.hpp | 246 - lib/stdexec/coroutine.hpp | 125 - lib/stdexec/execution.hpp | 6166 ----------------- lib/stdexec/functional.hpp | 369 - lib/stdexec/stop_token.hpp | 437 -- lib/tbbexec/tbb_thread_pool.hpp | 525 -- package.cmake | 1 - src/CMakeLists.txt | 1 - update_package | 3 - 93 files changed, 18 insertions(+), 29110 deletions(-) delete mode 100644 conanfile.txt delete mode 100644 lib/exec/__detail/__atomic_intrusive_queue.hpp delete mode 100644 lib/exec/__detail/__atomic_ref.hpp delete mode 100644 lib/exec/__detail/__basic_sequence.hpp delete mode 100644 lib/exec/__detail/__bit_cast.hpp delete mode 100644 lib/exec/__detail/__bwos_lifo_queue.hpp delete mode 100644 lib/exec/__detail/__manual_lifetime.hpp delete mode 100644 lib/exec/__detail/__sender_facade.hpp delete mode 100644 lib/exec/__detail/__xorshift.hpp delete mode 100644 lib/exec/any_sender_of.hpp delete mode 100644 lib/exec/async_scope.hpp delete mode 100644 lib/exec/at_coroutine_exit.hpp delete mode 100644 lib/exec/create.hpp delete mode 100644 lib/exec/env.hpp delete mode 100644 lib/exec/finally.hpp delete mode 100644 lib/exec/inline_scheduler.hpp delete mode 100644 lib/exec/linux/__detail/memory_mapped_region.hpp delete mode 100644 lib/exec/linux/__detail/safe_file_descriptor.hpp delete mode 100644 lib/exec/linux/io_uring_context.hpp delete mode 100644 lib/exec/linux/memory_mapped_region.hpp delete mode 100644 lib/exec/linux/safe_file_descriptor.hpp delete mode 100644 lib/exec/materialize.hpp delete mode 100644 lib/exec/on.hpp delete mode 100644 lib/exec/on_coro_disposition.hpp delete mode 100644 lib/exec/repeat_effect_until.hpp delete mode 100644 lib/exec/scope.hpp delete mode 100644 lib/exec/sequence/any_sequence_of.hpp delete mode 100644 lib/exec/sequence/empty_sequence.hpp delete mode 100644 lib/exec/sequence/ignore_all_values.hpp delete mode 100644 lib/exec/sequence/iterate.hpp delete mode 100644 lib/exec/sequence/transform_each.hpp delete mode 100644 lib/exec/sequence_senders.hpp delete mode 100644 lib/exec/single_thread_context.hpp delete mode 100644 lib/exec/static_thread_pool.hpp delete mode 100644 lib/exec/task.hpp delete mode 100644 lib/exec/timed_scheduler.hpp delete mode 100644 lib/exec/trampoline_scheduler.hpp delete mode 100644 lib/exec/variant_sender.hpp delete mode 100644 lib/exec/when_any.hpp delete mode 100644 lib/nvexec/README.md delete mode 100644 lib/nvexec/detail/config.cuh delete mode 100644 lib/nvexec/detail/cuda_atomic.cuh delete mode 100644 lib/nvexec/detail/cuda_fwd.cuh delete mode 100644 lib/nvexec/detail/memory.cuh delete mode 100644 lib/nvexec/detail/queue.cuh delete mode 100644 lib/nvexec/detail/throw_on_cuda_error.cuh delete mode 100644 lib/nvexec/detail/variant.cuh delete mode 100644 lib/nvexec/multi_gpu_context.cuh delete mode 100644 lib/nvexec/nvtx.cuh delete mode 100644 lib/nvexec/stream/algorithm_base.cuh delete mode 100644 lib/nvexec/stream/bulk.cuh delete mode 100644 lib/nvexec/stream/common.cuh delete mode 100644 lib/nvexec/stream/ensure_started.cuh delete mode 100644 lib/nvexec/stream/launch.cuh delete mode 100644 lib/nvexec/stream/let_xxx.cuh delete mode 100644 lib/nvexec/stream/reduce.cuh delete mode 100644 lib/nvexec/stream/schedule_from.cuh delete mode 100644 lib/nvexec/stream/split.cuh delete mode 100644 lib/nvexec/stream/start_detached.cuh delete mode 100644 lib/nvexec/stream/submit.cuh delete mode 100644 lib/nvexec/stream/sync_wait.cuh delete mode 100644 lib/nvexec/stream/then.cuh delete mode 100644 lib/nvexec/stream/transfer.cuh delete mode 100644 lib/nvexec/stream/upon_error.cuh delete mode 100644 lib/nvexec/stream/upon_stopped.cuh delete mode 100644 lib/nvexec/stream/when_all.cuh delete mode 100644 lib/nvexec/stream_context.cuh delete mode 100644 lib/stdexec/__detail/__basic_sender.hpp delete mode 100644 lib/stdexec/__detail/__concepts.hpp delete mode 100644 lib/stdexec/__detail/__config.hpp delete mode 100644 lib/stdexec/__detail/__domain.hpp delete mode 100644 lib/stdexec/__detail/__env.hpp delete mode 100644 lib/stdexec/__detail/__execution_fwd.hpp delete mode 100644 lib/stdexec/__detail/__force_include.hpp delete mode 100644 lib/stdexec/__detail/__intrusive_ptr.hpp delete mode 100644 lib/stdexec/__detail/__intrusive_queue.hpp delete mode 100644 lib/stdexec/__detail/__meta.hpp delete mode 100644 lib/stdexec/__detail/__p2300.hpp delete mode 100644 lib/stdexec/__detail/__ranges.hpp delete mode 100644 lib/stdexec/__detail/__scope.hpp delete mode 100644 lib/stdexec/__detail/__tuple.hpp delete mode 100644 lib/stdexec/__detail/__type_traits.hpp delete mode 100644 lib/stdexec/concepts.hpp delete mode 100644 lib/stdexec/coroutine.hpp delete mode 100644 lib/stdexec/execution.hpp delete mode 100644 lib/stdexec/functional.hpp delete mode 100644 lib/stdexec/stop_token.hpp delete mode 100644 lib/tbbexec/tbb_thread_pool.hpp delete mode 100644 package.cmake delete mode 100755 update_package diff --git a/CMakeLists.txt b/CMakeLists.txt index 150978f..e20300e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,12 +3,28 @@ project(mraylib CXX) include(cmake/StandardProjectSettings.cmake) # include(cmake/StaticAnalyzers.cmake) include(cmake/CompilerWarnings.cmake) -include(package.cmake) add_compile_options(-std=c++2b) # TODO: clang-tidy creating problem with the same # set(CMAKE_CXX_STANDARD 23) +# CPM +file( + DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v0.38.3/CPM.cmake + ${CMAKE_CURRENT_BINARY_DIR}/cmake/CPM.cmake + EXPECTED_HASH SHA256=cc155ce02e7945e7b8967ddfaff0b050e958a723ef7aad3766d368940cb15494 +) +include(${CMAKE_CURRENT_BINARY_DIR}/cmake/CPM.cmake) + +# Packages +CPMAddPackage( + NAME doctest + GITHUB_REPOSITORY doctest/doctest + GIT_TAG v2.4.11 +) +CPMAddPackage("gh:NVIDIA/stdexec#main") + add_library(project_options INTERFACE) add_library(project_warnings INTERFACE) diff --git a/build b/build index 430c999..8baf40b 100755 --- a/build +++ b/build @@ -3,6 +3,6 @@ build_type=$1 [ "$build_type" ] || build_type="Release" echo "Using CMAKE_BUILD_TYPE $build_type" -cmake . -B bin -DCMAKE_TOOLCHAIN_FILE=bin/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=$build_type && +cmake . -B bin -DCMAKE_BUILD_TYPE=$build_type && cp bin/compile_commands.json . && cmake --build bin diff --git a/conanfile.txt b/conanfile.txt deleted file mode 100644 index 988c0f3..0000000 --- a/conanfile.txt +++ /dev/null @@ -1,6 +0,0 @@ -[requires] -doctest/2.4.11 - -[generators] -CMakeDeps -CMakeToolchain diff --git a/lib/exec/__detail/__atomic_intrusive_queue.hpp b/lib/exec/__detail/__atomic_intrusive_queue.hpp deleted file mode 100644 index 8b8beee..0000000 --- a/lib/exec/__detail/__atomic_intrusive_queue.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2023 Maikel Nadolski - * Copyright (c) 2023 NVIDIA Corporation - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include "../../stdexec/__detail/__intrusive_queue.hpp" - -namespace exec { - template - class __atomic_intrusive_queue; - - template - class alignas(64) __atomic_intrusive_queue<_NextPtr> { - public: - using __node_pointer = _Tp *; - using __atomic_node_pointer = std::atomic<_Tp *>; - - [[nodiscard]] bool empty() const noexcept { - return __head_.load(std::memory_order_relaxed) == nullptr; - } - - struct try_push_result { - bool __success; - bool __was_empty; - }; - - try_push_result try_push_front(__node_pointer t) noexcept { - __node_pointer __old_head = __head_.load(std::memory_order_relaxed); - t->*_NextPtr = __old_head; - return { - __head_.compare_exchange_strong(__old_head, t, std::memory_order_acq_rel), - __old_head == nullptr}; - } - - bool push_front(__node_pointer t) noexcept { - __node_pointer __old_head = __head_.load(std::memory_order_relaxed); - do { - t->*_NextPtr = __old_head; - } while (!__head_.compare_exchange_weak(__old_head, t, std::memory_order_acq_rel)); - return __old_head == nullptr; - } - - void prepend(stdexec::__intrusive_queue<_NextPtr> queue) noexcept { - __node_pointer __new_head = queue.front(); - __node_pointer __tail = queue.back(); - __node_pointer __old_head = __head_.load(std::memory_order_relaxed); - __tail->*_NextPtr = __old_head; - while (!__head_.compare_exchange_weak(__old_head, __new_head, std::memory_order_acq_rel)) { - __tail->*_NextPtr = __old_head; - } - queue.clear(); - } - - stdexec::__intrusive_queue<_NextPtr> pop_all() noexcept { - return stdexec::__intrusive_queue<_NextPtr>::make(reset_head()); - } - - stdexec::__intrusive_queue<_NextPtr> pop_all_reversed() noexcept { - return stdexec::__intrusive_queue<_NextPtr>::make_reversed(reset_head()); - } - - private: - __node_pointer reset_head() noexcept { - __node_pointer __old_head = __head_.load(std::memory_order_relaxed); - while (!__head_.compare_exchange_weak(__old_head, nullptr, std::memory_order_acq_rel)) { - ; - } - return __old_head; - } - - __atomic_node_pointer __head_{nullptr}; - }; -} \ No newline at end of file diff --git a/lib/exec/__detail/__atomic_ref.hpp b/lib/exec/__detail/__atomic_ref.hpp deleted file mode 100644 index b45d433..0000000 --- a/lib/exec/__detail/__atomic_ref.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2023 Maikel Nadolski - * Copyright (c) 2023 NVIDIA Corporation - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include - -#if __cpp_lib_atomic_ref >= 201806L -template -using __atomic_ref = std::atomic_ref; -#else -#include - -// clang-12 does not know about std::atomic_ref yet -// Here we implement only what we need -template -class __atomic_ref { - _Ty* __ptr_; - - static constexpr int __map_memory_order(std::memory_order __order) { - constexpr int __map[] = { - __ATOMIC_RELAXED, - __ATOMIC_CONSUME, - __ATOMIC_ACQUIRE, - __ATOMIC_RELEASE, - __ATOMIC_ACQ_REL, - __ATOMIC_SEQ_CST, - }; - return __map[static_cast(__order)]; - } - - public: - __atomic_ref(_Ty& __ref) noexcept - : __ptr_(&__ref) { - } - - __atomic_ref(const __atomic_ref&) = delete; - __atomic_ref& operator=(const __atomic_ref&) = delete; - - __atomic_ref(__atomic_ref&&) = delete; - __atomic_ref& operator=(__atomic_ref&&) = delete; - - _Ty load(std::memory_order __order = std::memory_order_seq_cst) const noexcept { - return __atomic_load_n(__ptr_, __map_memory_order(__order)); - } - - void store(_Ty __desired, std::memory_order __order = std::memory_order_seq_cst) noexcept { - __atomic_store_n(__ptr_, __desired, __map_memory_order(__order)); - } -}; -#endif diff --git a/lib/exec/__detail/__basic_sequence.hpp b/lib/exec/__detail/__basic_sequence.hpp deleted file mode 100644 index d4c5605..0000000 --- a/lib/exec/__detail/__basic_sequence.hpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2023 NVIDIA Corporation - * Copyright (c) 2023 Maikel Nadolski - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include "../sequence_senders.hpp" - -#include "../../stdexec/__detail/__basic_sender.hpp" - -namespace exec { - ////////////////////////////////////////////////////////////////////////////////////////////////// - // __seqexpr - template - struct __seqexpr { - using __id = __seqexpr; - using __t = __seqexpr; - }; - - template - struct __seqexpr<_ImplFn> { - using sender_concept = sequence_sender_t; - using __t = __seqexpr; - using __id = __seqexpr; - using __tag_t = stdexec::__call_result_t<_ImplFn, stdexec::__cp, stdexec::__detail::__get_tag>; - - static __tag_t __tag() noexcept { - return {}; - } - - mutable _ImplFn __impl_; - - STDEXEC_ATTRIBUTE((host, device)) - explicit __seqexpr(_ImplFn __impl) - : __impl_((_ImplFn&&) __impl) { - } - - template _Tag, stdexec::same_as<__seqexpr> _Self> - friend auto tag_invoke(_Tag, const _Self& __self) noexcept // - -> stdexec::__msecond< - stdexec::__if_c>, // - decltype(__self.__tag().get_env(__self))> { - static_assert(noexcept(__self.__tag().get_env(__self))); - return __tag_t::get_env(__self); - } - - template < - stdexec::same_as _Tag, - stdexec::__decays_to<__seqexpr> _Self, - class _Env> - friend auto tag_invoke(_Tag, _Self&& __self, _Env&& __env) // - -> stdexec::__msecond< - stdexec::__if_c>, - decltype(__self.__tag().get_completion_signatures((_Self&&) __self, (_Env&&) __env))> { - return {}; - } - - template < - stdexec::same_as _Tag, - stdexec::__decays_to<__seqexpr> _Self, - class _Env> - friend auto tag_invoke(_Tag, _Self&& __self, _Env&& __env) // - -> stdexec::__msecond< - stdexec::__if_c>, - decltype(__self.__tag().get_item_types((_Self&&) __self, (_Env&&) __env))> { - return {}; - } - - template < - stdexec::same_as _Tag, - stdexec::__decays_to<__seqexpr> _Self, - /*receiver*/ class _Receiver> - friend auto tag_invoke(_Tag, _Self&& __self, _Receiver&& __rcvr) // - noexcept(noexcept(__self.__tag().subscribe((_Self&&) __self, (_Receiver&&) __rcvr))) // - -> stdexec::__msecond< - stdexec::__if_c>, - decltype(__self.__tag().subscribe((_Self&&) __self, (_Receiver&&) __rcvr))> { - return __tag_t::subscribe((_Self&&) __self, (_Receiver&&) __rcvr); - } - - template - STDEXEC_DEFINE_EXPLICIT_THIS_MEMFN(auto apply)(this _Sender&& __sndr, _ApplyFn&& __fun) // - noexcept(stdexec::__nothrow_callable< - stdexec::__detail::__impl_of<_Sender>, - stdexec::__copy_cvref_fn<_Sender>, - _ApplyFn>) // - -> stdexec::__call_result_t< - stdexec::__detail::__impl_of<_Sender>, - stdexec::__copy_cvref_fn<_Sender>, - _ApplyFn> { // - return ((_Sender&&) __sndr) - .__impl_(stdexec::__copy_cvref_fn<_Sender>(), (_ApplyFn&&) __fun); // - } - }; - - template - STDEXEC_ATTRIBUTE((host, device)) - __seqexpr(_ImplFn) -> __seqexpr<_ImplFn>; - -#if STDEXEC_NVHPC() || (STDEXEC_GCC() && __GNUC__ < 13) - namespace __detail { - template - struct make_sequence_expr_t { - template - constexpr auto operator()(_Data __data = {}, _Children... __children) const { - return __seqexpr{stdexec::__detail::__make_tuple( - _Tag(), stdexec::__detail::__mbc(__data), stdexec::__detail::__mbc(__children)...)}; - } - }; - } -#else - namespace __detail { - template - struct make_sequence_expr_t { - template - constexpr auto operator()(_Data __data = {}, _Children... __children) const { - return __seqexpr{ - stdexec::__detail::__make_tuple(_Tag(), (_Data&&) __data, (_Children&&) __children...)}; - } - }; - } -#endif - - template - inline constexpr __detail::make_sequence_expr_t<_Tag, _Domain> make_sequence_expr{}; - - template - using __seqexpr_t = stdexec::__result_of, _Data, _Children...>; -} \ No newline at end of file diff --git a/lib/exec/__detail/__bit_cast.hpp b/lib/exec/__detail/__bit_cast.hpp deleted file mode 100644 index 04e0734..0000000 --- a/lib/exec/__detail/__bit_cast.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023 Maikel Nadolski - * Copyright (c) 2023 NVIDIA Corporation - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#if __has_include() -#include -#if __cpp_lib_bit_cast >= 201806L -#define STDEXEC_HAS_BIT_CAST -#endif -#endif - -#include -#include - -#include "../../stdexec/__detail/__config.hpp" - -namespace exec { - - template - concept __trivially_copyable = STDEXEC_IS_TRIVIALLY_COPYABLE(_Ty); - -#if defined(STDEXEC_HAS_BIT_CAST) - using std::bit_cast; -#else - template <__trivially_copyable _To, __trivially_copyable _From> - requires(sizeof(_To) == sizeof(_From)) - [[nodiscard]] constexpr _To bit_cast(const _From& __from) noexcept { -#if STDEXEC_HAS_BUILTIN(__builtin_bit_cast) || (_MSC_VER >= 1926) - return __builtin_bit_cast(_To, __from); -#else - _To __to; - std::memcpy(&__to, &__from, sizeof(_From)); - return __to; -#endif - } -#endif -} diff --git a/lib/exec/__detail/__bwos_lifo_queue.hpp b/lib/exec/__detail/__bwos_lifo_queue.hpp deleted file mode 100644 index eeff2ad..0000000 --- a/lib/exec/__detail/__bwos_lifo_queue.hpp +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (c) 2023 Maikel Nadolski - * Copyright (c) 2023 NVIDIA Corporation - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include "../../stdexec/__detail/__config.hpp" - -#include -#include -#include -#include -#include -#include -#include - -// The below code for spin_loop_pause is taken from https://github.com/max0x7ba/atomic_queue/blob/master/include/atomic_queue/defs.h -// Copyright (c) 2019 Maxim Egorushkin. MIT License. - -#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) -#if STDEXEC_MSVC() -#include -#endif -namespace exec::bwos { - static inline void spin_loop_pause() noexcept { -#if STDEXEC_MSVC() - _mm_pause(); -#else - __builtin_ia32_pause(); -#endif - } -} -#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM64) -namespace exec::bwos { - static inline void spin_loop_pause() noexcept { -#if ( \ - defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ - || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ - || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) \ - || defined(__ARM_ARCH_8A__) || defined(__aarch64__)) - asm volatile("yield" ::: "memory"); -#elif defined(_M_ARM64) - __yield(); -#else - asm volatile("nop" ::: "memory"); -#endif - } -} -#else -namespace exec::bwos { - static inline void spin_loop_pause() noexcept { - } -} -#endif - -/** - * This is an implementation of the BWOS queue as described in - * BWoS: Formally Verified Block-based Work Stealing for Parallel Processing (Wang et al. 2023) - */ - -namespace exec::bwos { - inline constexpr std::size_t hardware_destructive_interference_size = 64; - inline constexpr std::size_t hardware_constructive_interference_size = 64; - - enum class lifo_queue_error_code { - success, - done, - empty, - full, - conflict, - }; - - template - struct fetch_result { - lifo_queue_error_code status; - Tp value; - }; - - struct takeover_result { - std::size_t front; - std::size_t back; - }; - - template > - class lifo_queue { - public: - explicit lifo_queue( - std::size_t num_blocks, - std::size_t block_size, - Allocator allocator = Allocator()); - - Tp pop_back() noexcept; - - Tp steal_front() noexcept; - - bool push_back(Tp value) noexcept; - - template - Iterator push_back(Iterator first, Sentinel last) noexcept; - - std::size_t get_available_capacity() const noexcept; - std::size_t get_free_capacity() const noexcept; - - std::size_t block_size() const noexcept; - std::size_t num_blocks() const noexcept; - - private: - template - using allocator_of_t = typename std::allocator_traits::template rebind_alloc; - - struct block_type { - explicit block_type(std::size_t block_size, Allocator allocator = Allocator()); - - block_type(const block_type &); - block_type &operator=(const block_type &); - - block_type(block_type &&) noexcept; - block_type &operator=(block_type &&) noexcept; - - lifo_queue_error_code put(Tp value) noexcept; - - template - Iterator bulk_put(Iterator first, Sentinel last) noexcept; - - fetch_result get() noexcept; - - fetch_result steal() noexcept; - - takeover_result takeover() noexcept; - bool is_writable() const noexcept; - - std::size_t free_capacity() const noexcept; - - void grant() noexcept; - - bool reclaim() noexcept; - - bool is_stealable() const noexcept; - - std::size_t block_size() const noexcept; - - alignas(hardware_destructive_interference_size) std::atomic head_{}; - alignas(hardware_destructive_interference_size) std::atomic tail_{}; - alignas(hardware_destructive_interference_size) std::atomic steal_head_{}; - alignas(hardware_destructive_interference_size) std::atomic steal_tail_{}; - std::vector ring_buffer_{}; - }; - - bool advance_get_index() noexcept; - bool advance_steal_index(std::size_t expected_thief_counter) noexcept; - bool advance_put_index() noexcept; - - alignas(hardware_destructive_interference_size) std::atomic owner_block_{1}; - alignas(hardware_destructive_interference_size) std::atomic thief_block_{0}; - std::vector> blocks_{}; - std::size_t mask_{}; - }; - - ///////////////////////////////////////////////////////////////////////////// - // Implementation of lifo_queue member methods - - template - lifo_queue::lifo_queue( - std::size_t num_blocks, - std::size_t block_size, - Allocator allocator) - : blocks_( - std::max(static_cast(2), std::bit_ceil(num_blocks)), - block_type(block_size, allocator), - allocator_of_t(allocator)) - , mask_(blocks_.size() - 1) { - blocks_[owner_block_].reclaim(); - } - - template - Tp lifo_queue::pop_back() noexcept { - do { - std::size_t owner_index = owner_block_.load(std::memory_order_relaxed) & mask_; - block_type ¤t_block = blocks_[owner_index]; - auto [ec, value] = current_block.get(); - if (ec == lifo_queue_error_code::success) { - return value; - } - if (ec == lifo_queue_error_code::done) { - return Tp{}; - } - } while (advance_get_index()); - return Tp{}; - } - - template - Tp lifo_queue::steal_front() noexcept { - std::size_t thief = 0; - do { - thief = thief_block_.load(std::memory_order_relaxed); - std::size_t thief_index = thief & mask_; - block_type &block = blocks_[thief_index]; - fetch_result result = block.steal(); - while (result.status != lifo_queue_error_code::done) { - if (result.status == lifo_queue_error_code::success) { - return result.value; - } - if (result.status == lifo_queue_error_code::empty) { - return Tp{}; - } - result = block.steal(); - } - } while (advance_steal_index(thief)); - return Tp{}; - } - - template - bool lifo_queue::push_back(Tp value) noexcept { - do { - std::size_t owner_index = owner_block_.load(std::memory_order_relaxed) & mask_; - block_type ¤t_block = blocks_[owner_index]; - auto ec = current_block.put(value); - if (ec == lifo_queue_error_code::success) { - return true; - } - } while (advance_put_index()); - return false; - } - - template - template - Iterator lifo_queue::push_back(Iterator first, Sentinel last) noexcept { - do { - std::size_t owner_index = owner_block_.load(std::memory_order_relaxed) & mask_; - block_type ¤t_block = blocks_[owner_index]; - first = current_block.bulk_put(first, last); - } while (first != last && advance_put_index()); - return first; - } - - template - std::size_t lifo_queue::get_free_capacity() const noexcept { - std::size_t owner_counter = owner_block_.load(std::memory_order_relaxed); - std::size_t owner_index = owner_counter & mask_; - std::size_t local_capacity = blocks_[owner_index].free_capacity(); - std::size_t thief_counter = thief_block_.load(std::memory_order_relaxed); - std::size_t diff = owner_counter - thief_counter; - std::size_t rest = blocks_.size() - diff - 1; - return local_capacity + rest * block_size(); - } - - template - std::size_t lifo_queue::get_available_capacity() const noexcept { - return num_blocks() * block_size(); - } - - template - std::size_t lifo_queue::block_size() const noexcept { - return blocks_[0].block_size(); - } - - template - std::size_t lifo_queue::num_blocks() const noexcept { - return blocks_.size(); - } - - template - bool lifo_queue::advance_get_index() noexcept { - std::size_t owner_counter = owner_block_.load(std::memory_order_relaxed); - std::size_t predecessor = owner_counter - 1ul; - std::size_t predecessor_index = predecessor & mask_; - block_type &previous_block = blocks_[predecessor_index]; - takeover_result result = previous_block.takeover(); - if (result.front != result.back) { - std::size_t thief_counter = thief_block_.load(std::memory_order_relaxed); - if (thief_counter == predecessor) { - predecessor += blocks_.size(); - thief_counter += blocks_.size() - 1ul; - thief_block_.store(thief_counter, std::memory_order_relaxed); - } - owner_block_.store(predecessor, std::memory_order_relaxed); - return true; - } - return false; - } - - template - bool lifo_queue::advance_put_index() noexcept { - std::size_t owner_counter = owner_block_.load(std::memory_order_relaxed); - std::size_t next_counter = owner_counter + 1ul; - std::size_t thief_counter = thief_block_.load(std::memory_order_relaxed); - STDEXEC_ASSERT(thief_counter < next_counter); - if (next_counter - thief_counter >= blocks_.size()) { - return false; - } - std::size_t next_index = next_counter & mask_; - block_type &next_block = blocks_[next_index]; - if (!next_block.is_writable()) [[unlikely]] { - return false; - } - std::size_t owner_index = owner_counter & mask_; - block_type ¤t_block = blocks_[owner_index]; - current_block.grant(); - owner_block_.store(next_counter, std::memory_order_relaxed); - next_block.reclaim(); - return true; - } - - template - bool lifo_queue::advance_steal_index(std::size_t expected_thief_counter) noexcept { - std::size_t thief_counter = expected_thief_counter; - std::size_t next_counter = thief_counter + 1; - std::size_t next_index = next_counter & mask_; - block_type &next_block = blocks_[next_index]; - if (next_block.is_stealable()) { - thief_block_.compare_exchange_strong(thief_counter, next_counter, std::memory_order_relaxed); - return true; - } - return thief_block_.load(std::memory_order_relaxed) != thief_counter; - } - - ///////////////////////////////////////////////////////////////////////////// - // Implementation of lifo_queue::block_type member methods - - template - lifo_queue::block_type::block_type(std::size_t block_size, Allocator allocator) - : head_{0} - , tail_{0} - , steal_head_{0} - , steal_tail_{block_size} - , ring_buffer_(block_size, allocator) { - } - - template - lifo_queue::block_type::block_type(const block_type &other) { - head_.store(other.head_.load(std::memory_order_relaxed), std::memory_order_relaxed); - tail_.store(other.tail_.load(std::memory_order_relaxed), std::memory_order_relaxed); - steal_tail_.store(other.steal_tail_.load(std::memory_order_relaxed), std::memory_order_relaxed); - steal_head_.store(other.steal_head_.load(std::memory_order_relaxed), std::memory_order_relaxed); - ring_buffer_ = other.ring_buffer_; - } - - template - typename lifo_queue::block_type & - lifo_queue::block_type::operator=(const block_type &other) { - head_.store(other.head_.load(std::memory_order_relaxed), std::memory_order_relaxed); - tail_.store(other.tail_.load(std::memory_order_relaxed), std::memory_order_relaxed); - steal_tail_.store(other.steal_tail_.load(std::memory_order_relaxed), std::memory_order_relaxed); - steal_head_.store(other.steal_head_.load(std::memory_order_relaxed), std::memory_order_relaxed); - ring_buffer_ = other.ring_buffer_; - return *this; - } - - template - lifo_queue::block_type::block_type(block_type &&other) noexcept { - head_.store(other.head_.load(std::memory_order_relaxed), std::memory_order_relaxed); - tail_.store(other.tail_.load(std::memory_order_relaxed), std::memory_order_relaxed); - steal_tail_.store(other.steal_tail_.load(std::memory_order_relaxed), std::memory_order_relaxed); - steal_head_.store(other.steal_head_.load(std::memory_order_relaxed), std::memory_order_relaxed); - ring_buffer_ = std::exchange(std::move(other.ring_buffer_), {}); - } - - template - typename lifo_queue::block_type & - lifo_queue::block_type::operator=(block_type &&other) noexcept { - head_.store(other.head_.load(std::memory_order_relaxed), std::memory_order_relaxed); - tail_.store(other.tail_.load(std::memory_order_relaxed), std::memory_order_relaxed); - steal_tail_.store(other.steal_tail_.load(std::memory_order_relaxed), std::memory_order_relaxed); - steal_head_.store(other.steal_head_.load(std::memory_order_relaxed), std::memory_order_relaxed); - ring_buffer_ = std::exchange(std::move(other.ring_buffer_), {}); - return *this; - } - - template - lifo_queue_error_code lifo_queue::block_type::put(Tp value) noexcept { - std::uint64_t back = tail_.load(std::memory_order_relaxed); - if (back < block_size()) [[likely]] { - ring_buffer_[back] = static_cast(value); - tail_.store(back + 1, std::memory_order_release); - return lifo_queue_error_code::success; - } - return lifo_queue_error_code::full; - } - - template - template - Iterator lifo_queue::block_type::bulk_put(Iterator first, Sentinel last) noexcept { - std::uint64_t back = tail_.load(std::memory_order_relaxed); - while (first != last && back < block_size()) { - ring_buffer_[back] = static_cast(*first); - ++back; - ++first; - } - tail_.store(back, std::memory_order_release); - return first; - } - - template - fetch_result lifo_queue::block_type::get() noexcept { - std::uint64_t front = head_.load(std::memory_order_relaxed); - if (front == block_size()) [[unlikely]] { - return {lifo_queue_error_code::done, nullptr}; - } - std::uint64_t back = tail_.load(std::memory_order_relaxed); - if (front == back) [[unlikely]] { - return {lifo_queue_error_code::empty, nullptr}; - } - Tp value = static_cast(ring_buffer_[back - 1]); - tail_.store(back - 1, std::memory_order_release); - return {lifo_queue_error_code::success, value}; - } - - template - fetch_result lifo_queue::block_type::steal() noexcept { - std::uint64_t spos = steal_tail_.load(std::memory_order_relaxed); - fetch_result result{}; - if (spos == block_size()) [[unlikely]] { - result.status = lifo_queue_error_code::done; - return result; - } - std::uint64_t back = tail_.load(std::memory_order_acquire); - if (spos == back) [[unlikely]] { - result.status = lifo_queue_error_code::empty; - return result; - } - if (!steal_tail_.compare_exchange_strong(spos, spos + 1, std::memory_order_relaxed)) { - result.status = lifo_queue_error_code::conflict; - return result; - } - result.value = static_cast(ring_buffer_[spos]); - steal_head_.fetch_add(1, std::memory_order_release); - result.status = lifo_queue_error_code::success; - return result; - } - - template - takeover_result lifo_queue::block_type::takeover() noexcept { - std::uint64_t spos = steal_tail_.exchange(block_size(), std::memory_order_relaxed); - if (spos == block_size()) [[unlikely]] { - return {head_.load(std::memory_order_relaxed), tail_.load(std::memory_order_relaxed)}; - } - head_.store(spos, std::memory_order_relaxed); - return {spos, tail_.load(std::memory_order_relaxed)}; - } - - template - bool lifo_queue::block_type::is_writable() const noexcept { - std::uint64_t expected_steal = block_size(); - std::uint64_t spos = steal_tail_.load(std::memory_order_relaxed); - return spos == expected_steal; - } - - template - std::size_t lifo_queue::block_type::free_capacity() const noexcept { - std::uint64_t back = tail_.load(std::memory_order_relaxed); - return block_size() - back; - } - - template - bool lifo_queue::block_type::reclaim() noexcept { - std::uint64_t expected_steal_head_ = tail_.load(std::memory_order_relaxed); - while (steal_head_.load(std::memory_order_acquire) != expected_steal_head_) { - spin_loop_pause(); - } - head_.store(0, std::memory_order_relaxed); - tail_.store(0, std::memory_order_relaxed); - steal_tail_.store(block_size(), std::memory_order_relaxed); - steal_head_.store(0, std::memory_order_relaxed); - return false; - } - - template - std::size_t lifo_queue::block_type::block_size() const noexcept { - return ring_buffer_.size(); - } - - template - void lifo_queue::block_type::grant() noexcept { - std::uint64_t old_head = head_.exchange(block_size(), std::memory_order_relaxed); - steal_tail_.store(old_head, std::memory_order_release); - } - - template - bool lifo_queue::block_type::is_stealable() const noexcept { - return steal_tail_.load(std::memory_order_acquire) != block_size(); - } -} \ No newline at end of file diff --git a/lib/exec/__detail/__manual_lifetime.hpp b/lib/exec/__detail/__manual_lifetime.hpp deleted file mode 100644 index 509cf97..0000000 --- a/lib/exec/__detail/__manual_lifetime.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2023 Maikel Nadolski - * Copyright (c) 2023 NVIDIA Corporation - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include - -namespace exec { - - template - class __manual_lifetime { - public: - __manual_lifetime() noexcept { - } - - ~__manual_lifetime() { - } - - __manual_lifetime(const __manual_lifetime&) = delete; - __manual_lifetime& operator=(const __manual_lifetime&) = delete; - - __manual_lifetime(__manual_lifetime&&) = delete; - __manual_lifetime& operator=(__manual_lifetime&&) = delete; - - template - _Ty& __construct(_Args&&... __args) noexcept( - stdexec::__nothrow_constructible_from<_Ty, _Args...>) { - return *::new (static_cast(std::addressof(__value_))) _Ty((_Args&&) __args...); - } - - template - _Ty& __construct_with(_Func&& func) { - return *::new (static_cast(std::addressof(__value_))) _Ty(((_Func&&) func)()); - } - - void __destroy() noexcept { - __value_.~_Ty(); - } - - _Ty& __get() & noexcept { - return __value_; - } - - _Ty&& __get() && noexcept { - return (_Ty&&) __value_; - } - - const _Ty& __get() const & noexcept { - return __value_; - } - - const _Ty&& __get() const && noexcept { - return (const _Ty&&) __value_; - } - - private: - union { - _Ty __value_; - }; - }; -} diff --git a/lib/exec/__detail/__sender_facade.hpp b/lib/exec/__detail/__sender_facade.hpp deleted file mode 100644 index dbacdd3..0000000 --- a/lib/exec/__detail/__sender_facade.hpp +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2022 NVIDIA Corporation - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include "../../stdexec/execution.hpp" - -STDEXEC_PRAGMA_PUSH() -STDEXEC_PRAGMA_IGNORE_EDG(1302) -STDEXEC_PRAGMA_IGNORE_EDG(497) - -namespace exec { - struct _FAILURE_TO_CONNECT_ { - template - struct _WHAT_ { - struct __t { - using __id = _WHAT_; - using sender_concept = stdexec::sender_t; - using completion_signatures = _WHAT_; - }; - }; - template - using __f = stdexec::__t<_WHAT_<_Message...>>; - }; - - struct _TYPE_IS_NOT_A_VALID_SENDER_WITH_CURRENT_ENVIRONMENT_ { - template - struct _WITH_ { }; - }; - - namespace __stl { - using namespace stdexec; - - struct __data_placeholder; - - template - inline constexpr bool __never_true = false; - - template - struct __receiver_placeholder { - template <__completion_tag _Tag, class... _As> - friend void tag_invoke(_Tag, __receiver_placeholder, _As&&...) noexcept { - static_assert( - __never_true<_Tag, _As...>, "we should never be instantiating the body of this function"); - } - - template _Self> - [[noreturn]] friend _Env tag_invoke(get_env_t, _Self) noexcept { - static_assert( - __never_true<_Self>, "we should never be instantiating the body of this function"); - std::terminate(); - } - }; - - template - using __data_t = - decltype(__declval<_Kernel&>().get_data(__declval<_Receiver&>(), (_Completions*) nullptr)); - - struct __with_dummy_transform_sender { - int transform_sender; - }; - - template - struct __test_for_transform_sender - : _Kernel - , __with_dummy_transform_sender { }; - - template - concept __lacks_transform_sender = // - requires { - { - &__test_for_transform_sender<_Kernel>::transform_sender - } -> same_as::*>; - }; - - template - using __tfx_sender_ = decltype(__declval<_Kernel&>().transform_sender( - __declval<_Sender>(), - __declval<__data_placeholder&>(), - __declval<__receiver_placeholder<_Env>&>())); - - struct __sender_transform_failed { - using __t = __sender_transform_failed; - }; - - template - auto __transform_sender_t_() { - if constexpr (__lacks_transform_sender<_Kernel>) { - return __mtype<_Sender>{}; - } else { - if constexpr (__mvalid<__tfx_sender_, _Kernel, _Sender, _Env>) { - return __mtype<__tfx_sender_<_Kernel, _Sender, _Env>>{}; - } else { - return __sender_transform_failed{}; - } - } - STDEXEC_UNREACHABLE(); - } - - template - auto __transform_sender(_Kernel& __kernel, _Sender&& __sndr, _Data& __data, _Receiver& __rcvr) { - if constexpr (__lacks_transform_sender<_Kernel>) { - return (_Sender&&) __sndr; - } else { - return __kernel.transform_sender((_Sender&&) __sndr, __data, __rcvr); - } - STDEXEC_UNREACHABLE(); - } - - template - using __transform_sender_t = - stdexec::__t())>; - - template - using __set_result_t = decltype(__declval<_Kernel&>().set_result( - _Tag{}, - __declval<__data_placeholder&>(), - __declval<_Receiver&>(), - __declval<_As>()...)); - - template - using __env_t = decltype(__declval<_Kernel&>().get_env(__declval<_Env>())); - - template - auto __completions_from_sig(_Tag (*)(_As...)) - -> __set_result_t<_Kernel, __receiver_placeholder<_Env>, _Tag, _As...>; - - template - using __completions_from_sig_t = decltype(__stl::__completions_from_sig((_Sig*) nullptr)); - - template - auto __all_completions(_Completions*...) - -> __minvoke< __mconcat<__munique<__q>>, _Completions...>; - - template - auto __compute_completions_(completion_signatures<_Sigs...>*) - -> decltype(__stl::__all_completions( - static_cast<__completions_from_sig_t<_Kernel, _Env, _Sigs>>(nullptr)...)); - - template - auto __compute_completions_(_NoCompletions*) -> _NoCompletions; - - template - using __compute_completions_t = - decltype(__stl::__compute_completions_<_Kernel, _Env>((_Completions*) nullptr)); - - template - struct __receiver { - using _Receiver = stdexec::__t<_ReceiverId>; - - struct __state { - template - __state(_Kernel __kernel, _Receiver __rcvr, completion_signatures<_Sigs...>* __cmpl) - : __rcvr_((_Receiver&&) __rcvr) - , __kernel_{(_Kernel&&) __kernel} - , __data_(__kernel_.get_data(__rcvr_, __cmpl)) { - } - - _Receiver __rcvr_; - STDEXEC_ATTRIBUTE((no_unique_address)) _Kernel __kernel_; - STDEXEC_ATTRIBUTE((no_unique_address)) _Data __data_; - }; - - struct __t { - using receiver_concept = stdexec::receiver_t; - using __id = __receiver; - __state* __state_; - - template < // - __completion_tag _Tag, - same_as<__t> _Self, - class... _As> - requires __mvalid<__set_result_t, _Kernel, _Receiver, _Tag, _As...> - friend void tag_invoke(_Tag __tag, _Self __self, _As&&... __as) noexcept { - __state& __st = *__self.__state_; - (void) __st.__kernel_.set_result(__tag, __st.__data_, __st.__rcvr_, (_As&&) __as...); - } - - template _Tag, same_as<__t> _Self> - friend auto tag_invoke(_Tag, _Self __self) noexcept - -> __env_t<_Kernel, env_of_t<_Receiver>> { - __state& __st = *__self.__state_; - static_assert(noexcept(__st.__kernel_.get_env(stdexec::get_env(__st.__rcvr_)))); - return __st.__kernel_.get_env(stdexec::get_env(__st.__rcvr_)); - } - }; - }; - - template - struct __operation { - using _Receiver = stdexec::__t<_ReceiverId>; - - using __env_t = __stl::__env_t<_Kernel, env_of_t<_Receiver>>; - using __sender_t = __transform_sender_t<_Kernel, _Sender, env_of_t<_Receiver>>; - using __base_completions_t = completion_signatures_of_t<__sender_t, __env_t>; - using __completions_t = __compute_completions_t<_Kernel, __env_t, __base_completions_t>; - using __data_t = __stl::__data_t<_Kernel, _Receiver, __completions_t>; - using __receiver_id = __receiver<_Kernel, __data_t, _ReceiverId>; - using __receiver_t = stdexec::__t<__receiver_id>; - using __state_t = typename __receiver_id::__state; - - struct __t : __immovable { - using __id = __operation; - __state_t __state_; - connect_result_t<__sender_t, __receiver_t> __op_; - - __t(_Sender&& __sndr, _Kernel __kernel, _Receiver __rcvr) - : __state_{(_Kernel&&) __kernel, (_Receiver&&) __rcvr, (__completions_t*) nullptr} - , __op_(stdexec::connect( - __stl::__transform_sender( - __state_.__kernel_, - (_Sender&&) __sndr, - __state_.__data_, - __state_.__rcvr_), - __receiver_t{&__state_})) { - } - - friend void tag_invoke(start_t, __t& __self) noexcept { - __self.__state_.__kernel_.start( - __self.__op_, __self.__state_.__data_, __self.__state_.__rcvr_); - } - }; - }; - - template - __minvoke<__id_<>, _Self> __is_derived_sender_(const _Self&); - - template - concept __is_derived_sender = // - requires(_Self&& __self) { - { __is_derived_sender_((_Self&&) __self) } -> same_as<_DerivedId>; - }; - - template - struct __sender { - template - using __operation_t = // - stdexec::__t< - __operation< __copy_cvref_t<_Self, _Sender>, _Kernel, stdexec::__id<_Receiver>>>; - - struct __t { - using __id = _DerivedId; - using sender_concept = stdexec::sender_t; - _Sender __sndr_; - _Kernel __kernel_; - - template - requires constructible_from<_Kernel, _As...> - __t(_Sender __sndr, _As&&... __as) - : __sndr_((_Sender&&) __sndr) - , __kernel_{(_As&&) __as...} { - } - - template <__is_derived_sender<_DerivedId> _Self, receiver _Receiver> - friend auto tag_invoke(connect_t, _Self&& __self, _Receiver __rcvr) - -> __operation_t<_Self, _Receiver> { - return {((_Self&&) __self).__sndr_, ((_Self&&) __self).__kernel_, (_Receiver&&) __rcvr}; - } - - template - using __new_sender_t = __transform_sender_t<_Kernel, __copy_cvref_t<_Self, _Sender>, _Env>; - - template - using __new_env_t = __env_t<_Kernel, _Env>; - - template - using __pre_completions_t = - __call_result_t; - - template - using __completions_t = __compute_completions_t<_Kernel, _NewEnv, _PreCompletions>; - - template - using __diagnostic_t = // - __minvoke< // - _FAILURE_TO_CONNECT_, // - _TYPE_IS_NOT_A_VALID_SENDER_WITH_CURRENT_ENVIRONMENT_::_WITH_<_DerivedId, _Env>>; - - template <__is_derived_sender<_DerivedId> _Self, class _Env> - static auto __new_completion_sigs_type() { - using _NewSender = __new_sender_t<_Self, _Env>; - if constexpr (sender<_NewSender>) { - using _NewEnv = __new_env_t<_Env>; - if constexpr (__mvalid<__pre_completions_t, _NewSender, _NewEnv>) { - using _Completions = - __completions_t<_NewEnv, __pre_completions_t<_NewSender, _NewEnv>>; - if constexpr (__valid_completion_signatures<_Completions, _Env>) { - return (_Completions(*)()) nullptr; - } else { - // assume this is an error message and return it directly - return (_Completions(*)()) nullptr; - } - } else { - return (__diagnostic_t<_Env>(*)()) nullptr; - } - } else if constexpr (same_as<_NewSender, __sender_transform_failed>) { - return (__diagnostic_t<_Env>(*)()) nullptr; - } else { - // assume this is an error message and return it directly - return (_NewSender(*)()) nullptr; - } - } - - template - using __new_completions_t = decltype(__new_completion_sigs_type<_Self, _Env>()()); - - template <__is_derived_sender<_DerivedId> _Self, class _Env> - friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env&&) - -> __new_completions_t<_Self, _Env> { - return {}; - } - - friend auto tag_invoke(stdexec::get_env_t, const __t& __self) noexcept - -> env_of_t { - return stdexec::get_env(__self.__sndr_); - } - }; - }; - } // namespace __stl - - template - using __sender_facade = __stl::__sender<_DerivedId, _Sender, _Kernel>; - - struct __default_kernel { - struct __no_data { }; - - template - static _Sender&& transform_sender( // - _Sender&& __sndr, // - [[maybe_unused]] stdexec::__ignore __data, // - [[maybe_unused]] stdexec::__ignore __rcvr) noexcept { - return (_Sender&&) __sndr; - } - - template - static _Env get_env(_Env&& __env) noexcept { - static_assert(stdexec::__nothrow_move_constructible<_Env>); - return (_Env&&) __env; - } - - static __no_data get_data( // - [[maybe_unused]] stdexec::__ignore __rcvr, // - [[maybe_unused]] void* __compl_sigs) noexcept { - return {}; - } - - template - static void start( // - _Op& __op, // - [[maybe_unused]] stdexec::__ignore __data, // - [[maybe_unused]] stdexec::__ignore __rcvr) noexcept { // - stdexec::start(__op); - } - - template - static auto set_result( // - _Tag __tag, // - [[maybe_unused]] stdexec::__ignore __data, // - _Receiver& __rcvr, // - _As&&... __as) noexcept // - -> stdexec::completion_signatures<_Tag(_As...)>* { - __tag((_Receiver&&) __rcvr, (_As&&) __as...); - return {}; - } - }; -} // namespace exec - -STDEXEC_PRAGMA_POP() diff --git a/lib/exec/__detail/__xorshift.hpp b/lib/exec/__detail/__xorshift.hpp deleted file mode 100644 index 6b95b85..0000000 --- a/lib/exec/__detail/__xorshift.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2023 Maikel Nadolski - * Copyright (c) 2023 NVIDIA Corporation - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* I have taken and modified this code from https://gist.github.com/Leandros/6dc334c22db135b033b57e9ee0311553 */ -/* Copyright (c) 2018 Arvid Gerstmann. */ -/* This code is licensed under MIT license. */ - -#include -#include - -namespace exec { - - class xorshift { - public: - using result_type = std::uint32_t; - - static constexpr result_type(min)() { - return 0; - } - - static constexpr result_type(max)() { - return UINT32_MAX; - } - - friend bool operator==(xorshift const &, xorshift const &) = default; - - xorshift() - : m_seed(0xc1f651c67c62c6e0ull) { - } - - explicit xorshift(std::random_device &rd) { - seed(rd); - } - - void seed(std::random_device &rd) { - m_seed = std::uint64_t(rd()) << 31 | std::uint64_t(rd()); - } - - result_type operator()() { - std::uint64_t result = m_seed * 0xd989bcacc137dcd5ull; - m_seed ^= m_seed >> 11; - m_seed ^= m_seed << 31; - m_seed ^= m_seed >> 18; - return std::uint32_t(result >> 32ull); - } - - void discard(unsigned long long n) { - for (unsigned long long i = 0; i < n; ++i) - operator()(); - } - - private: - std::uint64_t m_seed; - }; - -} // namespace exec \ No newline at end of file diff --git a/lib/exec/any_sender_of.hpp b/lib/exec/any_sender_of.hpp deleted file mode 100644 index 0e7c82c..0000000 --- a/lib/exec/any_sender_of.hpp +++ /dev/null @@ -1,1206 +0,0 @@ -/* Copyright (c) 2023 Maikel Nadolski - * Copyright (c) 2023 NVIDIA Corporation - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include "../stdexec/execution.hpp" -#include "./sequence_senders.hpp" - -#include - -namespace exec { - namespace __any { - using namespace stdexec; - - struct __create_vtable_t { - template - requires __tag_invocable_r, __mtype<_Tp>> - constexpr const _VTable* operator()(__mtype<_VTable>, __mtype<_Tp>) const noexcept { - return stdexec::tag_invoke(__create_vtable_t{}, __mtype<_VTable>{}, __mtype<_Tp>{}); - } - }; - - inline constexpr __create_vtable_t __create_vtable{}; - - template - struct __query_vfun; - - template - struct __query_vfun<_Tag (*const)(_Ret (*)(_As...))> { - _Ret (*__fn_)(void*, _As...); - - _Ret operator()(_Tag, void* __rcvr, _As&&... __as) const { - return __fn_(__rcvr, (_As&&) __as...); - } - }; - - template - struct __query_vfun<_Tag (*)(_Ret (*)(_As...))> { - _Ret (*__fn_)(void*, _As...); - - _Ret operator()(_Tag, void* __rcvr, _As&&... __as) const { - return __fn_(__rcvr, (_As&&) __as...); - } - }; - - template - struct __query_vfun<_Tag (*const)(_Ret (*)(_As...) noexcept)> { - _Ret (*__fn_)(void*, _As...) noexcept; - - _Ret operator()(_Tag, void* __rcvr, _As&&... __as) const noexcept { - return __fn_(__rcvr, (_As&&) __as...); - } - }; - - template - struct __query_vfun<_Tag (*)(_Ret (*)(_As...) noexcept)> { - _Ret (*__fn_)(void*, _As...) noexcept; - - _Ret operator()(_Tag, void* __rcvr, _As&&... __as) const noexcept { - return __fn_(__rcvr, (_As&&) __as...); - } - }; - - template - struct __query_vfun_fn; - - template - requires __callable - struct __query_vfun_fn<_EnvProvider> { - template - requires __callable<_Tag, env_of_t, _As...> - constexpr _Ret (*operator()(_Tag (*)(_Ret (*)(_As...))) const noexcept)(void*, _As...) { - return +[](void* __env_provider, _As... __as) -> _Ret { - return _Tag{}(get_env(*(const _EnvProvider*) __env_provider), (_As&&) __as...); - }; - } - - template - requires __callable<_Tag, env_of_t, _As...> - constexpr _Ret ( - *operator()(_Tag (*)(_Ret (*)(_As...) noexcept)) const noexcept)(void*, _As...) noexcept { - return +[](void* __env_provider, _As... __as) noexcept -> _Ret { - static_assert(__nothrow_callable<_Tag, const env_of_t<_EnvProvider>&, _As...>); - return _Tag{}(get_env(*(const _EnvProvider*) __env_provider), (_As&&) __as...); - }; - } - }; - - template - requires(!__callable) - struct __query_vfun_fn<_Queryable> { - template - requires __callable<_Tag, const _Queryable&, _As...> - constexpr _Ret (*operator()(_Tag (*)(_Ret (*)(_As...))) const noexcept)(void*, _As...) { - return +[](void* __queryable, _As... __as) -> _Ret { - return _Tag{}(*(const _Queryable*) __queryable, (_As&&) __as...); - }; - } - - template - requires __callable<_Tag, const _Queryable&, _As...> - constexpr _Ret ( - *operator()(_Tag (*)(_Ret (*)(_As...) noexcept)) const noexcept)(void*, _As...) noexcept { - return +[](void* __env_provider, _As... __as) noexcept -> _Ret { - static_assert(__nothrow_callable<_Tag, const _Queryable&, _As...>); - return _Tag{}(*(const _Queryable*) __env_provider, (_As&&) __as...); - }; - } - }; - - template - struct __storage_vfun; - - template - struct __storage_vfun<_Tag(void (*)(_As...))> { - void (*__fn_)(void*, _As...) = [](void*, _As...) { - }; - - void operator()(_Tag, void* __storage, _As&&... __as) const { - return __fn_(__storage, (_As&&) __as...); - } - }; - - template - struct __storage_vfun<_Tag(void (*)(_As...) noexcept)> { - void (*__fn_)(void*, _As...) noexcept = [](void*, _As...) noexcept { - }; - - void operator()(_Tag, void* __storage, _As&&... __as) const noexcept { - return __fn_(__storage, (_As&&) __as...); - } - }; - - template - struct __storage_vfun_fn { - template - requires __callable<_Tag, __mtype<_Tp>, _Storage&, _As...> - constexpr void (*operator()(_Tag (*)(void (*)(_As...))) const noexcept)(void*, _As...) { - return +[](void* __storage, _As... __as) -> void { - return _Tag{}(__mtype<_Tp>{}, *(_Storage*) __storage, (_As&&) __as...); - }; - } - - template - requires __callable<_Tag, __mtype<_Tp>, _Storage&, _As...> - constexpr void ( - *operator()(_Tag (*)(void (*)(_As...) noexcept)) const noexcept)(void*, _As...) noexcept { - return +[](void* __storage, _As... __as) noexcept -> void { - static_assert(__nothrow_callable<_Tag, __mtype<_Tp>, _Storage&, _As...>); - return _Tag{}(__mtype<_Tp>{}, *(_Storage*) __storage, (_As&&) __as...); - }; - } - }; - - struct __delete_t { - template - requires tag_invocable<__delete_t, __mtype<_Tp>, _Storage&> - void operator()(__mtype<_Tp>, _Storage& __storage) noexcept { - static_assert(nothrow_tag_invocable<__delete_t, __mtype<_Tp>, _Storage&>); - stdexec::tag_invoke(__delete_t{}, __mtype<_Tp>{}, __storage); - } - }; - - inline constexpr __delete_t __delete{}; - - struct __copy_construct_t { - template - requires tag_invocable<__copy_construct_t, __mtype<_Tp>, _Storage&, const _Storage&> - void operator()(__mtype<_Tp>, _Storage& __self, const _Storage& __from) noexcept( - nothrow_tag_invocable<__copy_construct_t, __mtype<_Tp>, _Storage&, const _Storage&>) { - stdexec::tag_invoke(__copy_construct_t{}, __mtype<_Tp>{}, __self, __from); - } - }; - - inline constexpr __copy_construct_t __copy_construct{}; - - struct __move_construct_t { - template - requires tag_invocable<__move_construct_t, __mtype<_Tp>, _Storage&, _Storage&&> - void operator()(__mtype<_Tp>, _Storage& __self, __midentity<_Storage&&> __from) noexcept { - static_assert( - nothrow_tag_invocable<__move_construct_t, __mtype<_Tp>, _Storage&, _Storage&&>); - stdexec::tag_invoke(__move_construct_t{}, __mtype<_Tp>{}, __self, (_Storage&&) __from); - } - }; - - inline constexpr __move_construct_t __move_construct{}; - - template - struct __storage_vtable; - - template - requires requires { _ParentVTable::operator(); } - struct __storage_vtable<_ParentVTable, _StorageCPOs...> - : _ParentVTable - , __storage_vfun<_StorageCPOs>... { - using _ParentVTable::operator(); - using __storage_vfun<_StorageCPOs>::operator()...; - }; - - template - requires(!requires { _ParentVTable::operator(); }) - struct __storage_vtable<_ParentVTable, _StorageCPOs...> - : _ParentVTable - , __storage_vfun<_StorageCPOs>... { - using __storage_vfun<_StorageCPOs>::operator()...; - }; - - template - inline constexpr __storage_vtable<_ParentVTable, _StorageCPOs...> __null_storage_vtbl{}; - - template - constexpr const __storage_vtable<_ParentVTable, _StorageCPOs...>* - __default_storage_vtable(__storage_vtable<_ParentVTable, _StorageCPOs...>*) noexcept { - return &__null_storage_vtbl<_ParentVTable, _StorageCPOs...>; - } - - template - static const __storage_vtable<_ParentVTable, _StorageCPOs...> __storage_vtbl{ - {*__create_vtable(__mtype<_ParentVTable>{}, __mtype<_Tp>{})}, - {__storage_vfun_fn<_Storage, _Tp>{}((_StorageCPOs*) nullptr)}...}; - - template < - class _Vtable, - class _Allocator, - bool _Copyable = false, - std::size_t _Alignment = alignof(std::max_align_t), - std::size_t _InlineSize = 3 * sizeof(void*)> - struct __storage { - class __t; - }; - - template < - class _Vtable, - class _Allocator, - std::size_t _Alignment = alignof(std::max_align_t), - std::size_t _InlineSize = 3 * sizeof(void*)> - struct __immovable_storage { - class __t : __immovable { - static constexpr std::size_t __buffer_size = std::max(_InlineSize, sizeof(void*)); - static constexpr std::size_t __alignment = std::max(_Alignment, alignof(void*)); - using __with_delete = __delete_t(void() noexcept); - using __vtable_t = __storage_vtable<_Vtable, __with_delete>; - - template - static constexpr bool __is_small = - sizeof(_Tp) <= __buffer_size && alignof(_Tp) <= __alignment; - - template - static constexpr const __vtable_t* __get_vtable_of_type() noexcept { - return &__storage_vtbl<__t, __decay_t<_Tp>, _Vtable, __with_delete>; - } - public: - using __id = __immovable_storage; - - __t() = default; - - template <__not_decays_to<__t> _Tp> - requires __callable<__create_vtable_t, __mtype<_Vtable>, __mtype<__decay_t<_Tp>>> - __t(_Tp&& __object) - : __vtable_{__get_vtable_of_type<_Tp>()} { - using _Dp = __decay_t<_Tp>; - if constexpr (__is_small<_Dp>) { - __construct_small<_Dp>((_Tp&&) __object); - } else { - __construct_large<_Dp>((_Tp&&) __object); - } - } - - template - requires __callable<__create_vtable_t, __mtype<_Vtable>, __mtype<_Tp>> - __t(std::in_place_type_t<_Tp>, _Args&&... __args) - : __vtable_{__get_vtable_of_type<_Tp>()} { - if constexpr (__is_small<_Tp>) { - __construct_small<_Tp>((_Args&&) __args...); - } else { - __construct_large<_Tp>((_Args&&) __args...); - } - } - - ~__t() { - __reset(); - } - - void __reset() noexcept { - (*__vtable_)(__delete, this); - __object_pointer_ = nullptr; - __vtable_ = __default_storage_vtable((__vtable_t*) nullptr); - } - - const _Vtable* __get_vtable() const noexcept { - return __vtable_; - } - - void* __get_object_pointer() const noexcept { - return __object_pointer_; - } - - private: - template - void __construct_small(_As&&... __args) { - static_assert(sizeof(_Tp) <= __buffer_size && alignof(_Tp) <= __alignment); - _Tp* __pointer = static_cast<_Tp*>(static_cast(&__buffer_[0])); - using _Alloc = typename std::allocator_traits<_Allocator>::template rebind_alloc<_Tp>; - _Alloc __alloc{__allocator_}; - std::allocator_traits<_Alloc>::construct(__alloc, __pointer, (_As&&) __args...); - __object_pointer_ = __pointer; - } - - template - void __construct_large(_As&&... __args) { - using _Alloc = typename std::allocator_traits<_Allocator>::template rebind_alloc<_Tp>; - _Alloc __alloc{__allocator_}; - _Tp* __pointer = std::allocator_traits<_Alloc>::allocate(__alloc, 1); - try { - std::allocator_traits<_Alloc>::construct(__alloc, __pointer, (_As&&) __args...); - } catch (...) { - std::allocator_traits<_Alloc>::deallocate(__alloc, __pointer, 1); - throw; - } - __object_pointer_ = __pointer; - } - - template - friend void tag_invoke(__delete_t, __mtype<_Tp>, __t& __self) noexcept { - if (!__self.__object_pointer_) { - return; - } - using _Alloc = typename std::allocator_traits<_Allocator>::template rebind_alloc<_Tp>; - _Alloc __alloc{__self.__allocator_}; - _Tp* __pointer = static_cast<_Tp*>(std::exchange(__self.__object_pointer_, nullptr)); - std::allocator_traits<_Alloc>::destroy(__alloc, __pointer); - if constexpr (!__is_small<_Tp>) { - std::allocator_traits<_Alloc>::deallocate(__alloc, __pointer, 1); - } - } - private: - const __vtable_t* __vtable_{__default_storage_vtable((__vtable_t*) nullptr)}; - void* __object_pointer_{nullptr}; - alignas(__alignment) std::byte __buffer_[__buffer_size]{}; - STDEXEC_ATTRIBUTE((no_unique_address)) _Allocator __allocator_{}; - }; - }; - - template < - class _Vtable, - class _Allocator, - bool _Copyable, - std::size_t _Alignment, - std::size_t _InlineSize> - class __storage<_Vtable, _Allocator, _Copyable, _Alignment, _InlineSize>::__t - : __if_c<_Copyable, __, __move_only> { - static_assert( - STDEXEC_IS_CONVERTIBLE_TO(typename std::allocator_traits<_Allocator>::void_pointer, void*)); - - static constexpr std::size_t __buffer_size = std::max(_InlineSize, sizeof(void*)); - static constexpr std::size_t __alignment = std::max(_Alignment, alignof(void*)); - using __with_copy = __copy_construct_t(void(const __t&)); - using __with_move = __move_construct_t(void(__t&&) noexcept); - using __with_delete = __delete_t(void() noexcept); - - template - static constexpr bool __is_small = sizeof(_Tp) <= __buffer_size && alignof(_Tp) <= __alignment - && std::is_nothrow_move_constructible_v<_Tp>; - - using __vtable_t = __if_c< - _Copyable, - __storage_vtable<_Vtable, __with_delete, __with_move, __with_copy>, - __storage_vtable<_Vtable, __with_delete, __with_move>>; - - template - static constexpr const __vtable_t* __get_vtable_of_type() noexcept { - if constexpr (_Copyable) { - return &__storage_vtbl< - __t, - __decay_t<_Tp>, - _Vtable, - __with_delete, - __with_move, - __with_copy>; - } else { - return &__storage_vtbl<__t, __decay_t<_Tp>, _Vtable, __with_delete, __with_move>; - } - } - - public: - using __id = __storage; - - __t() = default; - - template <__not_decays_to<__t> _Tp> - requires __callable<__create_vtable_t, __mtype<_Vtable>, __mtype<__decay_t<_Tp>>> - __t(_Tp&& __object) - : __vtable_{__get_vtable_of_type<_Tp>()} { - using _Dp = __decay_t<_Tp>; - if constexpr (__is_small<_Dp>) { - __construct_small<_Dp>((_Tp&&) __object); - } else { - __construct_large<_Dp>((_Tp&&) __object); - } - } - - template - requires __callable<__create_vtable_t, __mtype<_Vtable>, __mtype<_Tp>> - __t(std::in_place_type_t<_Tp>, _Args&&... __args) - : __vtable_{__get_vtable_of_type<_Tp>()} { - if constexpr (__is_small<_Tp>) { - __construct_small<_Tp>((_Args&&) __args...); - } else { - __construct_large<_Tp>((_Args&&) __args...); - } - } - - __t(const __t& __other) - requires(_Copyable) - { - (*__other.__vtable_)(__copy_construct, this, __other); - } - - __t& operator=(const __t& __other) - requires(_Copyable) - { - __t tmp(__other); - return *this = std::move(tmp); - } - - __t(__t&& __other) noexcept { - (*__other.__vtable_)(__move_construct, this, (__t&&) __other); - } - - __t& operator=(__t&& __other) noexcept { - __reset(); - (*__other.__vtable_)(__move_construct, this, (__t&&) __other); - return *this; - } - - ~__t() { - __reset(); - } - - void __reset() noexcept { - (*__vtable_)(__delete, this); - __object_pointer_ = nullptr; - __vtable_ = __default_storage_vtable((__vtable_t*) nullptr); - } - - const _Vtable* __get_vtable() const noexcept { - return __vtable_; - } - - void* __get_object_pointer() const noexcept { - return __object_pointer_; - } - - private: - template - void __construct_small(_As&&... __args) { - static_assert(sizeof(_Tp) <= __buffer_size && alignof(_Tp) <= __alignment); - _Tp* __pointer = static_cast<_Tp*>(static_cast(&__buffer_[0])); - using _Alloc = typename std::allocator_traits<_Allocator>::template rebind_alloc<_Tp>; - _Alloc __alloc{__allocator_}; - std::allocator_traits<_Alloc>::construct(__alloc, __pointer, (_As&&) __args...); - __object_pointer_ = __pointer; - } - - template - void __construct_large(_As&&... __args) { - using _Alloc = typename std::allocator_traits<_Allocator>::template rebind_alloc<_Tp>; - _Alloc __alloc{__allocator_}; - _Tp* __pointer = std::allocator_traits<_Alloc>::allocate(__alloc, 1); - try { - std::allocator_traits<_Alloc>::construct(__alloc, __pointer, (_As&&) __args...); - } catch (...) { - std::allocator_traits<_Alloc>::deallocate(__alloc, __pointer, 1); - throw; - } - __object_pointer_ = __pointer; - } - - template - friend void tag_invoke(__delete_t, __mtype<_Tp>, __t& __self) noexcept { - if (!__self.__object_pointer_) { - return; - } - using _Alloc = typename std::allocator_traits<_Allocator>::template rebind_alloc<_Tp>; - _Alloc __alloc{__self.__allocator_}; - _Tp* __pointer = static_cast<_Tp*>(std::exchange(__self.__object_pointer_, nullptr)); - std::allocator_traits<_Alloc>::destroy(__alloc, __pointer); - if constexpr (!__is_small<_Tp>) { - std::allocator_traits<_Alloc>::deallocate(__alloc, __pointer, 1); - } - } - - template - friend void - tag_invoke(__move_construct_t, __mtype<_Tp>, __t& __self, __t&& __other) noexcept { - if (!__other.__object_pointer_) { - return; - } - _Tp* __pointer = static_cast<_Tp*>(std::exchange(__other.__object_pointer_, nullptr)); - if constexpr (__is_small<_Tp>) { - _Tp& __other_object = *__pointer; - __self.template __construct_small<_Tp>((_Tp&&) __other_object); - using _Alloc = typename std::allocator_traits<_Allocator>::template rebind_alloc<_Tp>; - _Alloc __alloc{__self.__allocator_}; - std::allocator_traits<_Alloc>::destroy(__alloc, __pointer); - } else { - __self.__object_pointer_ = __pointer; - } - __self.__vtable_ = std::exchange( - __other.__vtable_, __default_storage_vtable((__vtable_t*) nullptr)); - } - - template - requires _Copyable - friend void tag_invoke(__copy_construct_t, __mtype<_Tp>, __t& __self, const __t& __other) { - if (!__other.__object_pointer_) { - return; - } - const _Tp& __other_object = *static_cast(__other.__object_pointer_); - if constexpr (__is_small<_Tp>) { - __self.template __construct_small<_Tp>(__other_object); - } else { - __self.template __construct_large<_Tp>(__other_object); - } - __self.__vtable_ = __other.__vtable_; - } - - const __vtable_t* __vtable_{__default_storage_vtable((__vtable_t*) nullptr)}; - void* __object_pointer_{nullptr}; - alignas(__alignment) std::byte __buffer_[__buffer_size]{}; - STDEXEC_ATTRIBUTE((no_unique_address)) _Allocator __allocator_{}; - }; - - struct __empty_vtable { - template - friend const __empty_vtable* - tag_invoke(__create_vtable_t, __mtype<__empty_vtable>, __mtype<_Sender>) noexcept { - static const __empty_vtable __vtable_{}; - return &__vtable_; - } - }; - - template > - using __immovable_storage_t = __t<__immovable_storage<_VTable, _Allocator>>; - - template > - using __unique_storage_t = __t<__storage<_VTable, _Allocator>>; - - template > - using __copyable_storage_t = __t<__storage<_VTable, _Allocator, true>>; - - template - _Tag __tag_type(_Tag (*)(_As...)); - - template - _Tag __tag_type(_Tag (*)(_As...) noexcept); - - template - concept __is_stop_token_query = requires { - { __tag_type(static_cast<_Query>(nullptr)) } -> same_as; - }; - - template - concept __is_not_stop_token_query = !__is_stop_token_query<_Query>; - - - template - using __is_not_stop_token_query_v = __mbool<__is_not_stop_token_query<_Query>>; - - namespace __rec { - template - struct __rcvr_vfun; - - template - struct __vtable { - class __t; - }; - - template - struct __ref; - - template - struct __rcvr_vfun<_Tag(_As...)> { - void (*__fn_)(void*, _As...) noexcept; - }; - - template - struct __rcvr_vfun_fn { - template - constexpr void (*operator()(_Tag (*)(_As...)) const noexcept)(void*, _As...) noexcept { - return +[](void* __rcvr, _As... __as) noexcept -> void { - _Tag{}((_Rcvr&&) *(_Rcvr*) __rcvr, (_As&&) __as...); - }; - } - }; - - template - struct __vtable, _Queries...> { - class __t - : public __rcvr_vfun<_Sigs>... - , public __query_vfun<_Queries>... { - public: - using __query_vfun<_Queries>::operator()...; - - private: - template - requires receiver_of<_Rcvr, completion_signatures<_Sigs...>> - && (__callable<__query_vfun_fn<_Rcvr>, _Queries> && ...) - friend const __t* tag_invoke(__create_vtable_t, __mtype<__t>, __mtype<_Rcvr>) noexcept { - static const __t __vtable_{ - {__rcvr_vfun_fn<_Rcvr>{}((_Sigs*) nullptr)}..., - {__query_vfun_fn<_Rcvr>{}((_Queries) nullptr)}...}; - return &__vtable_; - } - }; - }; - - template - requires(__is_not_stop_token_query<_Queries> && ...) - struct __ref, _Queries...> { -#if !STDEXEC_MSVC() - // MSVCBUG https://developercommunity.visualstudio.com/t/Private-member-inaccessible-when-used-in/10448363 - - private: -#endif - using __vtable_t = stdexec::__t<__vtable, _Queries...>>; - - struct __env_t { - const __vtable_t* __vtable_; - void* __rcvr_; - in_place_stop_token __token_; - - template - requires __callable - friend auto tag_invoke(_Tag, const __env_t& __self, _As&&... __as) noexcept( - __nothrow_callable) - -> __call_result_t { - return (*__self.__vtable_)(_Tag{}, __self.__rcvr_, (_As&&) __as...); - } - - friend in_place_stop_token tag_invoke(get_stop_token_t, const __env_t& __self) noexcept { - return __self.__token_; - } - } __env_; - public: - using receiver_concept = stdexec::receiver_t; - using __id = __ref; - using __t = __ref; - - template <__none_of<__ref, const __ref, __env_t, const __env_t> _Rcvr> - requires receiver_of<_Rcvr, completion_signatures<_Sigs...>> - && (__callable<__query_vfun_fn<_Rcvr>, _Queries> && ...) - __ref(_Rcvr& __rcvr) noexcept - : __env_{ - __create_vtable(__mtype<__vtable_t>{}, __mtype<_Rcvr>{}), - &__rcvr, - stdexec::get_stop_token(stdexec::get_env(__rcvr))} { - } - - template < __completion_tag _Tag, __decays_to<__ref> _Self, class... _As> - requires __one_of<_Tag(_As...), _Sigs...> - friend void tag_invoke(_Tag, _Self&& __self, _As&&... __as) noexcept { - (*static_cast*>(__self.__env_.__vtable_)->__fn_)( - ((_Self&&) __self).__env_.__rcvr_, (_As&&) __as...); - } - - template Self> - friend const __env_t& tag_invoke(get_env_t, const Self& __self) noexcept { - return __self.__env_; - } - }; - - __mbool __test_never_stop_token(get_stop_token_t (*)(never_stop_token (*)() noexcept)); - - template - __mbool __test_never_stop_token(_Tag (*)(_Ret (*)(_As...) noexcept)); - - template - __mbool __test_never_stop_token(_Tag (*)(_Ret (*)(_As...))); - - template - using __is_never_stop_token_query = - decltype(__test_never_stop_token(static_cast<_Query>(nullptr))); - - template - requires(__is_stop_token_query<_Queries> || ...) - struct __ref, _Queries...> { -#if !STDEXEC_MSVC() - // MSVCBUG https://developercommunity.visualstudio.com/t/Private-member-inaccessible-when-used-in/10448363 - - private: -#endif - using _FilteredQueries = - __minvoke<__remove_if<__q<__is_never_stop_token_query>>, _Queries...>; - using __vtable_t = stdexec::__t< - __mapply<__mbind_front_q<__vtable, completion_signatures<_Sigs...>>, _FilteredQueries>>; - - struct __env_t { - const __vtable_t* __vtable_; - void* __rcvr_; - - template - requires __callable - friend auto tag_invoke(_Tag, const __env_t& __self, _As&&... __as) noexcept( - __nothrow_callable) - -> __call_result_t { - return (*__self.__vtable_)(_Tag{}, __self.__rcvr_, (_As&&) __as...); - } - } __env_; - public: - using receiver_concept = stdexec::receiver_t; - using __id = __ref; - using __t = __ref; - - template <__none_of<__ref, const __ref, __env_t, const __env_t> _Rcvr> - requires receiver_of<_Rcvr, completion_signatures<_Sigs...>> - && (__callable<__query_vfun_fn<_Rcvr>, _Queries> && ...) - __ref(_Rcvr& __rcvr) noexcept - : __env_{__create_vtable(__mtype<__vtable_t>{}, __mtype<_Rcvr>{}), &__rcvr} { - } - - template < __completion_tag _Tag, __decays_to<__ref> _Self, class... _As> - requires __one_of<_Tag(_As...), _Sigs...> - friend void tag_invoke(_Tag, _Self&& __self, _As&&... __as) noexcept { - (*static_cast*>(__self.__env_.__vtable_)->__fn_)( - ((_Self&&) __self).__env_.__rcvr_, (_As&&) __as...); - } - - template Self> - friend const __env_t& tag_invoke(get_env_t, const Self& __self) noexcept { - return __self.__env_; - } - }; - } // __rec - - class __operation_vtable { - public: - void (*__start_)(void*) noexcept; - - private: - template - friend const __operation_vtable* - tag_invoke(__create_vtable_t, __mtype<__operation_vtable>, __mtype<_Op>) noexcept { - static __operation_vtable __vtable{[](void* __object_pointer) noexcept -> void { - STDEXEC_ASSERT(__object_pointer); - _Op& __op = *static_cast<_Op*>(__object_pointer); - static_assert(operation_state<_Op>); - start(__op); - }}; - return &__vtable; - } - }; - - using __immovable_operation_storage = __immovable_storage_t<__operation_vtable>; - - template - using __receiver_ref = __mapply<__mbind_front<__q<__rec::__ref>, _Sigs>, _Queries>; - - struct __on_stop_t { - stdexec::in_place_stop_source& __source_; - - void operator()() const noexcept { - __source_.request_stop(); - } - }; - - template - struct __operation_base { - STDEXEC_ATTRIBUTE((no_unique_address)) _Receiver __rcvr_; - stdexec::in_place_stop_source __stop_source_{}; - using __stop_callback = typename stdexec::stop_token_of_t< - stdexec::env_of_t<_Receiver>>::template callback_type<__on_stop_t>; - std::optional<__stop_callback> __on_stop_{}; - }; - - template - using __env_t = __make_env_t<_Env, __with>; - - template - struct __stoppable_receiver { - using _Receiver = stdexec::__t<_ReceiverId>; - - struct __t { - using receiver_concept = stdexec::receiver_t; - __operation_base<_Receiver>* __op_; - - template _SetNext, same_as<__t> _Self, class _Item> - requires __callable<_SetNext, _Receiver&, _Item> - friend auto tag_invoke(_SetNext, _Self& __self, _Item&& __item) { - return _SetNext{}(__self.__op_->__rcvr_, static_cast<_Item&&>(__item)); - } - - template _SetValue, same_as<__t> _Self, class... _Args> - requires __callable<_SetValue, _Receiver&&, _Args...> - friend void tag_invoke(_SetValue, _Self&& __self, _Args&&... __args) noexcept { - __self.__op_->__on_stop_.reset(); - _SetValue{}( - static_cast<_Receiver&&>(__self.__op_->__rcvr_), static_cast<_Args&&>(__args)...); - } - - template _SetError, same_as<__t> _Self, class _Error> - requires __callable<_SetError, _Receiver&&, _Error> - friend void tag_invoke(_SetError, _Self&& __self, _Error&& __err) noexcept { - __self.__op_->__on_stop_.reset(); - _SetError{}( - static_cast<_Receiver&&>(__self.__op_->__rcvr_), static_cast<_Error&&>(__err)); - } - - template _SetStopped, same_as<__t> _Self> - requires __callable<_SetStopped, _Receiver&&> - friend void tag_invoke(_SetStopped, _Self&& __self) noexcept { - __self.__op_->__on_stop_.reset(); - _SetStopped{}(static_cast<_Receiver&&>(__self.__op_->__rcvr_)); - } - - template _GetEnv, same_as<__t> _Self> - friend __env_t> tag_invoke(_GetEnv, const _Self& __self) noexcept { - return __make_env( - get_env(__self.__op_->__rcvr_), - __mkprop(__self.__op_->__stop_source_.get_token(), get_stop_token)); - } - }; - }; - - template - using __stoppable_receiver_t = stdexec::__t<__stoppable_receiver<_ReceiverId>>; - - template - struct __operation { - using _Receiver = stdexec::__t<_ReceiverId>; - - class __t : public __operation_base<_Receiver> { - public: - using __id = __operation; - - template - __t(_Sender&& __sender, _Receiver&& __receiver) - : __operation_base<_Receiver>{static_cast<_Receiver&&>(__receiver)} - , __rec_{this} - , __storage_{__sender.__connect(__rec_)} { - } - - private: - __stoppable_receiver_t<_ReceiverId> __rec_; - __immovable_operation_storage __storage_{}; - - friend void tag_invoke(start_t, __t& __self) noexcept { - __self.__on_stop_.emplace( - stdexec::get_stop_token(stdexec::get_env(__self.__rcvr_)), - __on_stop_t{__self.__stop_source_}); - STDEXEC_ASSERT(__self.__storage_.__get_vtable()->__start_); - __self.__storage_.__get_vtable()->__start_(__self.__storage_.__get_object_pointer()); - } - }; - }; - - template - struct __operation<_ReceiverId, false> { - using _Receiver = stdexec::__t<_ReceiverId>; - - class __t { - public: - using __id = __operation; - - template - __t(_Sender&& __sender, _Receiver&& __receiver) - : __rec_{static_cast<_Receiver&&>(__receiver)} - , __storage_{__sender.__connect(__rec_)} { - } - - private: - STDEXEC_ATTRIBUTE((no_unique_address)) _Receiver __rec_; - __immovable_operation_storage __storage_{}; - - friend void tag_invoke(start_t, __t& __self) noexcept { - STDEXEC_ASSERT(__self.__storage_.__get_vtable()->__start_); - __self.__storage_.__get_vtable()->__start_(__self.__storage_.__get_object_pointer()); - } - }; - }; - - template - class __query_vtable; - - template