diff --git a/nano/core_test/async.cpp b/nano/core_test/async.cpp index e0be0a732..cef6e082f 100644 --- a/nano/core_test/async.cpp +++ b/nano/core_test/async.cpp @@ -56,10 +56,30 @@ TEST (async, cancellation) cancellation.emit (); - ASSERT_EQ (fut.wait_for (500ms), std::future_status::ready); + ASSERT_EQ (fut.wait_for (1s), std::future_status::ready); ASSERT_NO_THROW (fut.get ()); } +// Test that cancellation signal behaves well when the cancellation is emitted after the task has completed +TEST (async, cancellation_lifetime) +{ + test_context ctx; + + nano::async::cancellation cancellation{ ctx.strand }; + { + auto fut = asio::co_spawn ( + ctx.strand, + [&] () -> asio::awaitable { + co_await nano::async::sleep_for (100ms); + }, + asio::bind_cancellation_slot (cancellation.slot (), asio::use_future)); + ASSERT_EQ (fut.wait_for (1s), std::future_status::ready); + fut.get (); + } + auto cancel_fut = cancellation.emit (); + ASSERT_EQ (cancel_fut.wait_for (1s), std::future_status::ready); +} + TEST (async, task) { nano::test::system system; diff --git a/nano/lib/async.hpp b/nano/lib/async.hpp index b217ba881..818d6bcaf 100644 --- a/nano/lib/async.hpp +++ b/nano/lib/async.hpp @@ -30,7 +30,7 @@ class cancellation public: explicit cancellation (nano::async::strand & strand) : strand{ strand }, - signal{ std::make_unique () } + signal{ std::make_shared () } { } @@ -49,12 +49,11 @@ public: }; public: - void emit (asio::cancellation_type type = asio::cancellation_type::all) + auto emit (asio::cancellation_type type = asio::cancellation_type::all) { - asio::dispatch (strand, asio::use_future ([this, type] () { - signal->emit (type); - })) - .wait (); + return asio::dispatch (strand, asio::use_future ([signal_l = signal, type] () { + signal_l->emit (type); + })); } auto slot () @@ -67,9 +66,8 @@ public: nano::async::strand & strand; private: - std::unique_ptr signal; // Wrap the signal in a unique_ptr to enable moving - - bool slotted{ false }; + std::shared_ptr signal; + bool slotted{ false }; // For debugging purposes }; /** @@ -82,7 +80,7 @@ public: // Only thread-like void tasks are supported for now using value_type = void; - task (nano::async::strand & strand) : + explicit task (nano::async::strand & strand) : strand{ strand }, cancellation{ strand } {