Skip to content
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

[Channel] improve send cancellation #184

Merged
merged 5 commits into from
Sep 14, 2022

Conversation

twittemb
Copy link
Contributor

This PR aims to:

  • harmonize the cancellation handling for the next() and send() operations. Previously, a send() cancellation was terminating all the pending and awaiting operations, which seemed wrong to me as mentioned here [AsyncChannel] Question: is task cancellation in sending operations too violent? #182.
  • improve the readability of the cancellation in the case it happens before the operation (send/next). Previously, a "cancelled" next was added to the awaiting list, so it can be immediately removed by the operation handling. Although it seemed to work well, it was not obvious when reading the code, and I tried to make it more explicit, so the maintenance is easier.


enum Emission {
case idle
case pending([UnsafeContinuation<UnsafeContinuation<Element?, Never>?, Never>])
case pending(Set<Pending>)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm making this a set becomes non-deterministic on the order of application - which will make it hard to test. Do we need set uniqueness to prevent issues or would just an Array work?

Copy link
Contributor Author

@twittemb twittemb Aug 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we have to be able to uniquely identify the pending operations so we can remove/resume them in case of cancellation thanks to their "id".

Using an array as a FIFO could be nice to guarantee deterministic operations when dequeuing but we cannot rely on the index of a newly added operation to potentially remove it in case of a cancellation because the array could be updated by another concurrent send/next operation in the meantime.

We would have to rely on the id in the Pending/Awaiting structure, and in case of a cancellation we would have to remove the element that matches the id. We loose the O(1) complexity of a Set for an O(n) :-(

I guess we could use something like OrderedSet but it would imply a dependency on swift-collections which we don't want I presume. Do you think we should implement a custom storage that fits our needs here ?

Copy link
Contributor Author

@twittemb twittemb Aug 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@phausler i see in this PR #185 that a dependency on Swift collections is introduced. Is this something we want ? We could leverage OrderedSet if so

Copy link
Contributor Author

@twittemb twittemb Sep 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@phausler did you have the change to think a bit about having an external dep ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OrderedSet is perfectly fine in my book.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, then I’ll update this PR to integrate it.
Thanks for your reply.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@phausler I have successfully introduced OrderedSet in this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@phausler do you think we have a go for this one, now that we use OrderedSet ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea I think we are good to go here


enum Emission {
case idle
case pending([UnsafeContinuation<UnsafeContinuation<Element?, Never>?, Never>])
case pending(Set<Pending>)
case awaiting(Set<Awaiting>)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also the set of awaiting might pose issue too come to think of it... (I should have caught this earlier)

@twittemb twittemb force-pushed the improve/channel_send_cancellation branch from 9495d3f to bde105c Compare August 30, 2022 18:03
@twittemb twittemb force-pushed the improve/channel_send_cancellation branch from bde105c to be52a2d Compare September 7, 2022 07:55
@phausler phausler merged commit 2b5fbf3 into apple:main Sep 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants