-
Notifications
You must be signed in to change notification settings - Fork 8
[dcl.fct.def.coroutine] p9 Whether a coroutine is suspended before a resumption should be in terms of happens-before #870
Description
Full name of submitter (unless configured in github; will be published with the issue): Jim X
[dcl.fct.def.coroutine] p9 says:
Invoking a resumption member function for a coroutine that is not suspended results in undefined behavior.
However, in a concurrent context, whether a coroutine is suspended before a resumption is hard to determine according to the current wording. Consider this example:
#include <coroutine>
#include <exception>
#include <iostream>
#include <thread>
struct Task {
struct promise_type {
Task get_return_object() {
return {std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};
std::coroutine_handle<promise_type> handle;
Task(std::coroutine_handle<promise_type> h) : handle(h) {}
};
struct SuspendOnce {
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle<> h) {}
void await_resume() {}
};
Task my_coroutine() {
co_await SuspendOnce{};
co_await SuspendOnce{};
}
int main() {
auto task = my_coroutine();
auto& h = task.handle;
auto t1 = std::thread([&]() {
h.resume(); // #1
});
auto t2 = std::thread([&]() {
h.resume(); // #2
});
t1.join();
t2.join();
}The signature of the member function resume implies the action is read-only, as per [coroutine.handle.resumption]
void resume() const;
So, the concurrent invocation of the member function does not constitute a data race because there are no conflicting actions. Similarly, there are also no conflicting actions in the body of the coroutine. This example doesn't itself have a data race.
However, it's hard to say whether the coroutine is suspended relative to the invocation of the resumption member function when there is another such concurrent invocation.
Suggested Resolution:
We may need to use happens-before to define whether a coroutine is suspended relative to a resumption(i.e., including resumption by returning false from await-suspend, see #865).
The suggested wording might be:
Resuming a coroutine shall happen after the coroutine is suspended and before any other resumption.