-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix coroutine continuation cleanup #181
Fix coroutine continuation cleanup #181
Conversation
Thank you for this contribution. Regarding your questions:
|
5793459
to
ee2bcb1
Compare
Thanks for the feedback. I've replaced |
support-lib/cpp/Future.hpp
Outdated
constexpr bool await_ready() const noexcept { | ||
return false; | ||
} | ||
bool await_suspend(std::coroutine_handle<ConcretePromise> finished) const noexcept { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use the alias detail::CoroutineHandle
for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done 👍
@@ -16,6 +16,8 @@ | |||
|
|||
#pragma once | |||
|
|||
#include "expected.hpp" | |||
|
|||
#include <atomic> | |||
#include <functional> | |||
#include <memory> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find I have to change the feature detection to the following to make it work in c++17 + -fcoroutine-ts
#if defined(__cpp_coroutines) && __has_include(<experimental/coroutine>)
#include <experimental/coroutine>
namespace djinni::detail {
template <typename Promise = void> using CoroutineHandle = std::experimental::coroutine_handle<Promise>;
using SuspendNever = std::experimental::suspend_never;
}
#define DJINNI_FUTURE_HAS_COROUTINE_SUPPORT 1
#elif defined(__cpp_impl_coroutine) && __has_include(<coroutine>)
#include <coroutine>
namespace djinni::detail {
template <typename Promise = void> using CoroutineHandle = std::coroutine_handle<Promise>;
using SuspendNever = std::suspend_never;
}
#define DJINNI_FUTURE_HAS_COROUTINE_SUPPORT 1
#endif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like with these settings the <coroutine>
header is available but not functional. Your suggestion fixes that nicely, but I found another issue: with clang 16 and -std=c++20 -stdlib=libc++
, it chooses the experimental
implementation even though the proper one is available.
I've done some experiments:
__cpp_coroutines
is available for both C++20 and C++17 +-fcoroutines-ts
until clang 17 when the macro and-fcoroutines-ts
were completely removed__cpp_impl_coroutine
and__cpp_lib_coroutine
are only available in proper C++20 mode when we have<coroutine>
I've just pushed another suggestion based on these findings. Here's what I used to test it with a few compilers/settings: https://godbolt.org/z/rj737E5eq
Caveat: I've tested only with clang. For iOS and Android that seems to be the relevant compiler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! this works really well.
C++ coroutines clean up their local variables after invoking
return_value
,return_void
orunhandled_exception
. This means that executing a continuation in one of these methods basically inverts the cleanup order. Example:Before this PR, the above code produced:
Which is inverted (caller gets cleaned up before callee). This can even lead to crashes etc, if a reference to a local variable from
bar
is used during cleanup infoo
- because that local variable inbar
was already cleaned up!After this PR the code produces:
As it should.
Merge considerations
requires
, which is a C++20 feature. I decided that this is acceptable, since coroutines themselves are also a C++20 feature. If this is not okay, let me know and I'll change it to a more compatible SFINAE approach.