diff --git a/include/boost/capy/ex/run_async.hpp b/include/boost/capy/ex/run_async.hpp index 70fd8ed54..3951e552a 100644 --- a/include/boost/capy/ex/run_async.hpp +++ b/include/boost/capy/ex/run_async.hpp @@ -34,6 +34,19 @@ namespace boost { namespace capy { namespace detail { +/** Match types usable as `run_async` completion handlers. + + Excludes the types meaningful to the other `run_async` parameters, + so a stop token, memory resource pointer, or allocator argument + selects its dedicated overload by conversion instead of deducing + as an exact-match handler. +*/ +template +concept RunAsyncHandler = + !std::is_convertible_v && + !std::is_convertible_v && + !Allocator; + /// Function pointer type for type-erased frame deallocation. using dealloc_fn = void(*)(void*, std::size_t); @@ -517,6 +530,7 @@ run_async(Ex ex) @see executor */ template + requires detail::RunAsyncHandler

[[nodiscard]] auto run_async(Ex ex, H1 h1) { @@ -560,6 +574,7 @@ run_async(Ex ex, H1 h1) @see executor */ template + requires (detail::RunAsyncHandler

&& detail::RunAsyncHandler

) [[nodiscard]] auto run_async(Ex ex, H1 h1, H2 h2) { @@ -626,6 +641,7 @@ run_async(Ex ex, std::stop_token st) @see executor */ template + requires detail::RunAsyncHandler

[[nodiscard]] auto run_async(Ex ex, std::stop_token st, H1 h1) { @@ -653,6 +669,7 @@ run_async(Ex ex, std::stop_token st, H1 h1) @see executor */ template + requires (detail::RunAsyncHandler

&& detail::RunAsyncHandler

) [[nodiscard]] auto run_async(Ex ex, std::stop_token st, H1 h1, H2 h2) { diff --git a/test/unit/ex/run_async.cpp b/test/unit/ex/run_async.cpp index e54e26f15..3536f7f86 100644 --- a/test/unit/ex/run_async.cpp +++ b/test/unit/ex/run_async.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -507,6 +508,33 @@ struct run_async_test BOOST_TEST(result); } + static task + set_flag(bool& flag) + { + flag = true; + co_return; + } + + void + testDerivedResourcePointer() + { + int dispatch_count = 0; + sync_executor d(dispatch_count); + std::pmr::monotonic_buffer_resource arena; + bool ran = false; + + run_async(d, &arena)(set_flag(ran)); + BOOST_TEST(ran); + + ran = false; + run_async(d, std::stop_token{}, &arena)(set_flag(ran)); + BOOST_TEST(ran); + + ran = false; + run_async(d, &arena, [&] { ran = true; })(returns_void()); + BOOST_TEST(ran); + } + //---------------------------------------------------------- // Sync Dispatcher //---------------------------------------------------------- @@ -775,6 +803,7 @@ struct run_async_test // Allocator Propagation testAllocatorPropagation(); + testDerivedResourcePointer(); // Sync Dispatcher testSyncDispatcherBasic();