Skip to content

Commit

Permalink
forward receiver queries in debug_async_scope
Browse files Browse the repository at this point in the history
  • Loading branch information
janondrusek committed Jun 7, 2023
1 parent 4ed2411 commit e3e8fc0
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
8 changes: 8 additions & 0 deletions include/unifex/detail/debug_async_scope.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ struct _receiver<Receiver>::type final {
}

void set_done() noexcept { op_->complete(unifex::set_done); }

template(typename CPO) //
(requires is_receiver_query_cpo_v<CPO>) //
friend auto tag_invoke(CPO cpo, const type& r) noexcept(
is_nothrow_callable_v<CPO, const Receiver&>)
-> callable_result_t<CPO, const Receiver&> {
return std::move(cpo)(std::as_const(r.op_->receiver_));
}
};

template <typename Sender, typename Receiver>
Expand Down
37 changes: 37 additions & 0 deletions test/debug_async_scope_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unifex/async_manual_reset_event.hpp>
#include <unifex/inplace_stop_token.hpp>
#include <unifex/just_from.hpp>
#include <unifex/nest.hpp>
#include <unifex/scheduler_concepts.hpp>
#include <unifex/single_thread_context.hpp>
#include <unifex/spawn_detached.hpp>
#include <unifex/sync_wait.hpp>
#include <unifex/v1/async_scope.hpp>
Expand Down Expand Up @@ -53,6 +55,41 @@ TEST(Debug, DISABLED_SyncWaitDeadlockV1Meth) {
}));
}

TEST(Debug, DISABLED_SyncWaitDeadlockV1TooLate) {
single_thread_context ctx;
v1::debug_async_scope scope;
async_manual_reset_event evt;
std::atomic_bool scheduled{false};

// wait for evt to be set on a background thread; note that the `async_wait()`
// _Sender_ is unstoppable
auto fut = scope.spawn_on(
ctx.get_scheduler(),
sequence(
just_from([&scheduled]() noexcept { scheduled = true; }),
evt.async_wait()));

// wait for the scheduled op to be started
while (!scheduled) {
continue;
}
// send a stop request to all the Senders spawned within the scope; this will
// trigger the future to cancel itself, but not the unstoppable `async_wait()`
scope.request_stop();

// with the scope joined, pending futures should all immediately
// complete with done. result has no value.
auto result = sync_wait(std::move(fut));
ASSERT_FALSE(result.has_value());

// but the scope itself won't complete until the spawned work is actually
// done so we will be stuck waiting for the event to be signaled
sync_wait(scope.cleanup());

// it's too late. this should be called before `scope.cleanup()`
evt.set();
}

TEST(Debug, DISABLED_SyncWaitDeadlockV2) {
v2::debug_async_scope scope;
spawn_detached(
Expand Down

0 comments on commit e3e8fc0

Please sign in to comment.