Skip to content

Commit 8ac2b79

Browse files
authored
Fix cancellation propagation by moving responsability to awaiter (#1246)
1 parent 69f9d8c commit 8ac2b79

File tree

4 files changed

+272
-224
lines changed

4 files changed

+272
-224
lines changed

strings/base_coroutine_foundation.h

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ namespace winrt::impl
142142

143143
#ifdef WINRT_IMPL_COROUTINES
144144
template <typename Async>
145-
struct await_adapter : enable_await_cancellation
145+
struct await_adapter : cancellable_awaiter<await_adapter<Async>>
146146
{
147147
await_adapter(Async const& async) : async(async) { }
148148

@@ -164,7 +164,22 @@ namespace winrt::impl
164164
return false;
165165
}
166166

167-
auto await_suspend(coroutine_handle<> handle)
167+
template <typename T>
168+
auto await_suspend(coroutine_handle<T> handle)
169+
{
170+
this->set_cancellable_promise_from_handle(handle);
171+
return register_completed_callback(handle);
172+
}
173+
174+
auto await_resume() const
175+
{
176+
check_hresult(failure);
177+
check_status_canceled(status);
178+
return async.GetResults();
179+
}
180+
181+
private:
182+
auto register_completed_callback(coroutine_handle<> handle)
168183
{
169184
auto extend_lifetime = async;
170185
async.Completed(disconnect_aware_handler(this, handle));
@@ -178,14 +193,6 @@ namespace winrt::impl
178193
#endif
179194
}
180195

181-
auto await_resume() const
182-
{
183-
check_hresult(failure);
184-
check_status_canceled(status);
185-
return async.GetResults();
186-
}
187-
188-
private:
189196
static fire_and_forget cancel_asynchronously(Async async)
190197
{
191198
co_await winrt::resume_background();
@@ -373,7 +380,7 @@ namespace winrt::impl
373380
};
374381

375382
template <typename Derived, typename AsyncInterface, typename TProgress = void>
376-
struct promise_base : implements<Derived, AsyncInterface, Windows::Foundation::IAsyncInfo>
383+
struct promise_base : implements<Derived, AsyncInterface, Windows::Foundation::IAsyncInfo>, cancellable_promise
377384
{
378385
using AsyncStatus = Windows::Foundation::AsyncStatus;
379386

@@ -471,7 +478,7 @@ namespace winrt::impl
471478
cancel();
472479
}
473480

474-
m_cancellable.cancel();
481+
cancellable_promise::cancel();
475482
}
476483

477484
void Close() const noexcept
@@ -608,15 +615,6 @@ namespace winrt::impl
608615
throw winrt::hresult_canceled();
609616
}
610617

611-
if constexpr (std::is_convertible_v<std::remove_reference_t<decltype(expression)>&, enable_await_cancellation&>)
612-
{
613-
if (m_propagate_cancellation)
614-
{
615-
static_cast<enable_await_cancellation&>(expression).set_cancellable_promise(&m_cancellable);
616-
expression.enable_cancellation(&m_cancellable);
617-
}
618-
}
619-
620618
return std::forward<Expression>(expression);
621619
}
622620

@@ -648,11 +646,6 @@ namespace winrt::impl
648646
}
649647
}
650648

651-
bool enable_cancellation_propagation(bool value) noexcept
652-
{
653-
return std::exchange(m_propagate_cancellation, value);
654-
}
655-
656649
#if defined(_DEBUG) && !defined(WINRT_NO_MAKE_DETECTION)
657650
void use_make_function_to_create_this_object() final
658651
{
@@ -673,10 +666,8 @@ namespace winrt::impl
673666
slim_mutex m_lock;
674667
async_completed_handler_t<AsyncInterface> m_completed;
675668
winrt::delegate<> m_cancel;
676-
cancellable_promise m_cancellable;
677669
std::atomic<AsyncStatus> m_status;
678670
bool m_completed_assigned{ false };
679-
bool m_propagate_cancellation{ false };
680671
};
681672
}
682673

0 commit comments

Comments
 (0)