-
Notifications
You must be signed in to change notification settings - Fork 182
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
Implement native unwind behaviour for coroutine cancellation #172
Conversation
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.
This is rad.
include/unifex/task.hpp
Outdated
|
||
coro::coroutine_handle<> continuation_; | ||
done_callback* doneCallback_ = nullptr; |
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.
Did we ever consciously choose camelCase
for variables? My preference is for snake_case
. Obviously not a problem you should be solving here, though.
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 have always been writing camelCase
for non-public variable names.
Public data-members that form part of the interface are still snake_case
.
Although I've noticed others have been using snake_case
variable names, so we're not consistent.
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.
This makes me smile!
@GorNishanov should get a load of this. |
This is beautiful! |
51cd5f7
to
0afc672
Compare
There are a lot of senders in unifex that don't have a |
c793d97
to
8e23a92
Compare
Coroutines now unconditionall unwind themselves if an awaited operation completes with 'done'. This signal will be transported up the stack until it hits a consumer that does handle the 'done' signal. This typically means wrapping the task<T> in a sender-algorithm that translates the done-signal into some other signal that a coroutine can then handle. eg. as an error/exception or as a value. This means we don't have to unwrap std::optional values every time we co_await something. This relies on coroutine promise_types implementing a new 'unhandled_done()' method, similar to 'unhandled_exception()', that handles the 'done' signal for that particular coroutine type. The 'task' type simply forwards the signal on to the awaiting coroutine's promise.unhandled_done() method. This recursion is terminated by the connect_awaitable() implementation which implements unhandled_done() to forward on to the receiver's set_done() implementation.
…meters. The task<T> unhanded_done callbacks are now namespace-scope functions that depend only on the parent promise type, not on T. Eliminate a conditional in unhandled_done() by initialising the doneCallback member with a default callback that terminates.
Implementation now only depends on the essential template arguments. This should reduce code-bloat compared to the lambda approach, which would have been instantiated for each kind of Awaitable the receiver was connected to, even though it didn't depend on the Awaitable.
8e23a92
to
9682a48
Compare
Coroutines now automatically unwind themselves if an awaited
operation completes with 'done'. Note that this 'unwind' process
is not catchable.
This signal will be transported up the stack until it hits a consumer
that does handle the 'done' signal. This typically means wrapping
the
task<T>
in a sender-algorithm that translates the done-signalinto some other signal that a coroutine can then handle.
eg. as an error/exception or as a value.
This means we don't have to unwrap
std::optional
values everytime we
co_await
something.This relies on coroutine promise_types implementing a new
unhandled_done()
method, similar tounhandled_exception()
,that handles the 'done' signal for that particular coroutine type.
The
task
type simply forwards the signal on to the awaitingcoroutine's
promise.unhandled_done()
method. This recursionis terminated by the
connect_awaitable()
implementation whichimplements
unhandled_done()
to forward on to the receiver'sset_done()
implementation.