diff --git a/include/beman/task/detail/awaiter.hpp b/include/beman/task/detail/awaiter.hpp index 4eff758..a6f4d9d 100644 --- a/include/beman/task/detail/awaiter.hpp +++ b/include/beman/task/detail/awaiter.hpp @@ -48,6 +48,7 @@ struct awaiter_op_t { template class awaiter : public ::beman::task::detail::state_base { public: + using allocator_type = typename ::beman::task::detail::state_base::allocator_type; using stop_token_type = typename ::beman::task::detail::state_base::stop_token_type; using scheduler_type = typename ::beman::task::detail::state_base::scheduler_type; @@ -87,6 +88,14 @@ class awaiter : public ::beman::task::detail::state_base { auto actual_complete() -> std::coroutine_handle<> { return this->no_completion_set() ? this->parent.promise().unhandled_stopped() : ::std::move(this->parent); } + auto do_get_allocator() -> allocator_type override { + if constexpr (requires { + ::beman::execution::get_allocator(::beman::execution::get_env(this->parent.promise())); + }) + return ::beman::execution::get_allocator(::beman::execution::get_env(this->parent.promise())); + else + return allocator_type{}; + } auto do_get_scheduler() -> scheduler_type override { return *this->scheduler; } auto do_set_scheduler(scheduler_type other) -> scheduler_type override { return ::std::exchange(*this->scheduler, other); diff --git a/include/beman/task/detail/promise_type.hpp b/include/beman/task/detail/promise_type.hpp index 27467a9..0c2f60d 100644 --- a/include/beman/task/detail/promise_type.hpp +++ b/include/beman/task/detail/promise_type.hpp @@ -50,9 +50,6 @@ class promise_type using stop_source_type = ::beman::task::detail::stop_source_of_t; using stop_token_type = decltype(std::declval().get_token()); - template - promise_type(const A&... a) : allocator(::beman::task::detail::find_allocator(a...)) {} - constexpr auto initial_suspend() noexcept -> ::std::suspend_always { return {}; } constexpr auto final_suspend() noexcept -> ::beman::task::detail::final_awaiter { return {}; } @@ -106,7 +103,7 @@ class promise_type } auto get_scheduler() const noexcept -> scheduler_type { return this->get_state()->get_scheduler(); } - auto get_allocator() const noexcept -> allocator_type { return this->allocator; } + auto get_allocator() const noexcept -> allocator_type { return this->get_state()->get_allocator(); } auto get_stop_token() const noexcept -> stop_token_type { return this->get_state()->get_stop_token(); } auto get_environment() const noexcept -> const Environment& { assert(this); @@ -117,7 +114,6 @@ class promise_type private: using env_t = ::beman::task::detail::promise_env; - allocator_type allocator{}; ::std::optional scheduler{}; }; } // namespace beman::task::detail diff --git a/include/beman/task/detail/state.hpp b/include/beman/task/detail/state.hpp index 714a077..567fac0 100644 --- a/include/beman/task/detail/state.hpp +++ b/include/beman/task/detail/state.hpp @@ -20,6 +20,7 @@ struct state : ::beman::task::detail::state_base, ::beman::task::detail::s using operation_state_concept = ::beman::execution::operation_state_t; using promise_type = ::beman::task::detail::promise_type; using scheduler_type = typename ::beman::task::detail::state_base::scheduler_type; + using allocator_type = typename ::beman::task::detail::state_base::allocator_type; using stop_source_type = ::beman::task::detail::stop_source_of_t; using stop_token_type = decltype(std::declval().get_token()); using stop_token_t = @@ -46,6 +47,12 @@ struct state : ::beman::task::detail::state_base, ::beman::task::detail::s this->result_complete(::std::move(this->receiver)); return std::noop_coroutine(); } + auto do_get_allocator() -> allocator_type override { + if constexpr (requires { ::beman::execution::get_allocator(::beman::execution::get_env(this->receiver)); }) + return ::beman::execution::get_allocator(::beman::execution::get_env(this->receiver)); + else + return allocator_type{}; + } auto do_get_scheduler() -> scheduler_type override { return this->scheduler; } auto do_set_scheduler(scheduler_type other) -> scheduler_type override { return ::std::exchange(this->scheduler, other); diff --git a/include/beman/task/detail/state_base.hpp b/include/beman/task/detail/state_base.hpp index 53c7096..6a43b42 100644 --- a/include/beman/task/detail/state_base.hpp +++ b/include/beman/task/detail/state_base.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -18,11 +19,13 @@ class state_base : public ::beman::task::detail::result_type<::beman::task::deta Value, ::beman::task::detail::error_types_of_t> { public: + using allocator_type = ::beman::task::detail::allocator_of_t; using stop_source_type = ::beman::task::detail::stop_source_of_t; using stop_token_type = decltype(std::declval().get_token()); using scheduler_type = ::beman::task::detail::scheduler_of_t; auto complete() -> std::coroutine_handle<> { return this->do_complete(); } + auto get_allocator() -> allocator_type { return this->do_get_allocator(); } auto get_stop_token() -> stop_token_type { return this->do_get_stop_token(); } auto get_environment() -> Environment& { assert(this); @@ -43,6 +46,7 @@ class state_base : public ::beman::task::detail::result_type<::beman::task::deta // NOLINTBEGIN(portability-template-virtual-member-function) virtual auto do_complete() -> std::coroutine_handle<> = 0; + virtual auto do_get_allocator() -> allocator_type = 0; virtual auto do_get_stop_token() -> stop_token_type = 0; virtual auto do_get_environment() -> Environment& = 0; virtual auto do_get_scheduler() -> scheduler_type = 0; diff --git a/tests/beman/task/promise_base.test.cpp b/tests/beman/task/promise_base.test.cpp index 77a7535..7e4e00b 100644 --- a/tests/beman/task/promise_base.test.cpp +++ b/tests/beman/task/promise_base.test.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include +#include #include #include #include @@ -48,6 +49,7 @@ struct env { template struct state : bt::state_base> { using Environment = env; + using allocator_type = ::beman::task::detail::allocator_of_t; using stop_source_type = ::beman::task::detail::stop_source_of_t; using stop_token_type = decltype(std::declval().get_token()); using scheduler_type = ::beman::task::detail::scheduler_of_t; @@ -62,6 +64,7 @@ struct state : bt::state_base> { this->completed = true; return std::noop_coroutine(); } + allocator_type do_get_allocator() override { return allocator_type{}; } stop_token_type do_get_stop_token() override { this->token = true; return this->source.get_token(); diff --git a/tests/beman/task/promise_type.test.cpp b/tests/beman/task/promise_type.test.cpp index a6c002b..eb8dc86 100644 --- a/tests/beman/task/promise_type.test.cpp +++ b/tests/beman/task/promise_type.test.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include +#include #include #include #include @@ -128,7 +129,8 @@ struct test_error : std::exception { struct test_task : beman::task::detail::state_base { - using promise_type = beman::task::detail::promise_type; + using promise_type = ::beman::task::detail::promise_type; + using allocator_type = ::beman::task::detail::allocator_of_t; beman::task::detail::handle handle; explicit test_task(beman::task::detail::handle h) : handle(std::move(h)) {} @@ -153,6 +155,7 @@ struct test_task : beman::task::detail::state_base { this->latch.count_down(); return std::noop_coroutine(); } + allocator_type do_get_allocator() override { return allocator_type{}; } stop_token_type do_get_stop_token() override { return this->source.get_token(); } environment& do_get_environment() override { return this->env; } auto do_get_scheduler() -> scheduler_type override { return scheduler_type(bt::inline_scheduler()); } diff --git a/tests/beman/task/state_base.test.cpp b/tests/beman/task/state_base.test.cpp index eae9623..5f24109 100644 --- a/tests/beman/task/state_base.test.cpp +++ b/tests/beman/task/state_base.test.cpp @@ -3,6 +3,7 @@ #include #include +#include #ifdef NDEBUG #undef NDEBUG #endif @@ -16,6 +17,7 @@ namespace { struct environment {}; struct state : beman::task::detail::state_base { + using allocator_type = ::beman::task::detail::allocator_of_t; stop_source_type source; environment env; bool completed{}; @@ -26,6 +28,7 @@ struct state : beman::task::detail::state_base { this->completed = true; return std::noop_coroutine(); } + allocator_type do_get_allocator() override { return allocator_type{}; } stop_token_type do_get_stop_token() override { this->token = true; return this->source.get_token();