Add support for pause & resume of thread-bound items in coroutines#621
Add support for pause & resume of thread-bound items in coroutines#621jonwis wants to merge 8 commits intomicrosoft:masterfrom
Conversation
|
So I'm on these: Installed just today. I can undo the change to the cmake file - I can't reproduce it building from a vs x64 build window with the scripts or with manual "cmake --preset clang ; cmake --build --preset clang-debug" ... |
| // Priority tags for SFINAE-based overload resolution | ||
| struct get_awaiter_priority_fallback | ||
| { | ||
| }; | ||
| struct get_awaiter_priority_free_op : get_awaiter_priority_fallback | ||
| { | ||
| }; | ||
| struct get_awaiter_priority_member_op : get_awaiter_priority_free_op | ||
| { | ||
| }; |
There was a problem hiding this comment.
There's a wil::details::priority_tag<N> I added (moved) somewhat recently. May be better to just re-use it? Higher N gets higher priority.
There was a problem hiding this comment.
Wait, oops, it's not in the details namespace
There was a problem hiding this comment.
@copilot please fix and use the standard priority_tag<> type instead
|
|
||
| template <typename T> | ||
| auto await_suspend(T&& handle) noexcept( | ||
| noexcept(std::declval<TChildAwaitable>().await_suspend(std::forward<T>(handle))) && noexcept(pausable.suspend())) |
There was a problem hiding this comment.
I thought that
| noexcept(std::declval<TChildAwaitable>().await_suspend(std::forward<T>(handle))) && noexcept(pausable.suspend())) | |
| noexcept(child_awaitable.await_suspend(std::forward<T>(handle))) && noexcept(pausable.suspend())) |
should work... did that give you issues?
There was a problem hiding this comment.
Really wish noexcept(auto) was a thing 😭
| return child_awaitable.await_suspend(std::forward<T>(handle)); | ||
| } | ||
|
|
||
| auto await_resume() noexcept(noexcept(std::declval<TChildAwaitable>().await_resume())) |
There was a problem hiding this comment.
You check noexcept(pausable.suspend()) above, but not noexcept(pausable.resume()) here?
| auto with_watcher(TWatcher& watcher, TAwaitable&& awaitable) | ||
| { | ||
| using awaiter_t = std::decay_t<decltype(details::coro::get_awaiter(std::forward<TAwaitable>(awaitable)))>; | ||
| return details::coro::coroutine_withsuspend_awaiter<TWatcher, awaiter_t>{watcher, std::forward<TAwaitable>(awaitable)}; |
There was a problem hiding this comment.
Doesn't this need to call get_awaiter on the awaitable?
|
|
||
| void resume() WI_NOEXCEPT | ||
| { | ||
| if (!IsWatching()) |
There was a problem hiding this comment.
Strictly for my own curiosity (the code as-is is probably fine to be safe) - is there a valid scenario where we end up calling resume() when IsWatching() is true? Seems like if that's the case, there was a mis-match with suspend()
We saw heap & stack corruptions with code like:
This type and types that use it are inherently thread-bound, and there's no guarantee that the continuation happens on the same thread.
Instead, this new helper lets you say:
... and the awaitable will unhook the watcher on the source thread during suspend and reattach it on the continuation thread before processing exception propagation, etc.