Skip to content

Add alternative design with just 2 operations on async_scope#16

Open
lucteo wants to merge 1 commit into
kirkshoop:mainfrom
lucteo:alternative_design
Open

Add alternative design with just 2 operations on async_scope#16
lucteo wants to merge 1 commit into
kirkshoop:mainfrom
lucteo:alternative_design

Conversation

@lucteo

@lucteo lucteo commented Sep 28, 2022

Copy link
Copy Markdown
Collaborator

Put the new alternative is a separate part of the document, making it easier to read and compare with the base proposal.

Put the new alternative is a separate part of the document, making it
easier to read and compare with the base proposal.
@lucteo

lucteo commented Sep 28, 2022

Copy link
Copy Markdown
Collaborator Author

This is just the first draft; I didn't go over it to check for errors. Please excuse me for this.

Comment thread asyncscope.md

If `scope` is an object of type `async_scope`, then `scope.spawn(snd)` is equivalent with:
```c++
start_detached(scope.nest(snd));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can't say I'm a fan of this. For this particular case, those things may well be equivalent, but anywhere that I see a start_detached, alarm bells will ring. Whereas when I see a spawn on an async scope, alarm bells won't ring, that's the bread-and-butter operation and I know that it's likely going to be correct.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Yes, I think this bothers me as well. Suggesting that we use start_detached to achieve this implies that start_detached is itself a good algorithm. Yet if it is used for anything that doesn't hand ownership anywhere (like chaining anything after that nest call) it probably isn't. So we end up in a situation where we recommend to not use start_detached except where its input is a nest-sender. In which case it's an async_scope algorithm and it might as well be explicitly tied to the async_scope.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It makes a lot of sense. I would also want us to ensure that we don't use start_detached without some clear lifetime safety nets.

I see two good ways out of this:

  1. completely remove start_detached
  2. make start_detached work by default only with async_scope senders; i.e., disallow general senders, unless somebody makes an explicit specialization

The alternative of keeping start_detached and saying that it should never be used, seems less ideal.

I feel this is the main question we need to answer before choosing how asnyc_scope should be used.

Do you think it's worth writing a quick paper on this, to get a general direction from LEWG? Or should we just put this question in this paper?

Comment thread asyncscope.md
However, this can be added on top.
If `scope` is an object of type `async_scope`, and `stoken` is a stop token, then we can build cancellation in with the following:
```c++
scope.nest(stop_when(snd, stoken))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we would want to see the cancellation path here too.

If we are going to wait for the scope to complete we need to decide what happens - do we stop accepting work (which cancellation tied to the scope can allow) and cancel in-flight work so we can guarantee safe shutdown?

Kirk's recent work on a phased async_scope makes this a bit more explicit.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

In this alternative, you loose the ability co cancel any future work (unless everything is spawn using the construct above). This may be an inconvenience, but not all flows might have cases in which work is spawned when we are trying to end the scope. It provides a bit more granular access to the user to decide whether global cancellation is needed, or not.

If global cancellation is needed, then the user can always make a small abstraction on top of async_scope that always packs the stop token with the work needing to be spawned.

I guess, in an ideal world, we would propose two abstractions:

  • a low level abstraction, similar to the one in this alternative
  • a friendlier version of async_scope, as described by the main paper

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.

3 participants