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

Reimplement scheduler affinity #527

Merged
merged 2 commits into from
Jun 1, 2023
Merged

Conversation

ispeters
Copy link
Contributor

@ispeters ispeters commented May 24, 2023

This diff changes how unifex::task<> implements Scheduler affinity to work more like folly::coro::Task<>. What Folly calls co_viaIfAsync, this diff calls with_scheduler_affinity, which is a new CPO.

with_scheduler_affinity is a Sender algorithm that maps the given Sender to another Sender that must meet new postconditions if the Receiver that it's connected to meets certain preconditions. The new preconditions are:

  • the eventual Receiver must provide a "current Scheduler";
  • the result of with_scheduler_affinity must be started on the Receiver's current Scheduler; and
  • stop requests delivered to the new Sender must be delivered on the Receiver's current Scheduler.

The Sender returned from with_scheduler_affinity must complete on its Receiver's current Scheduler (i.e. must complete where it was started) so long as all the above preconditions are met.

with_scheduler_affinity has two default implementations for a Sender type S:

  • if sender_traits<S>::is_always_scheduler_affine is true, the default is the identity;
  • if sender_traits<S>::is_always_scheduler_affine is false, the default is, essentially, a typed_via back to the correct scheduler.

Any Sender can customize with_scheduler_affinity, regardless of its is_always_scheduler_affine property.

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label May 24, 2023
@ispeters
Copy link
Contributor Author

This depends on #526.

@ispeters ispeters force-pushed the reimplement_scheduler_affinity branch 2 times, most recently from 23d1445 to 7bd7d60 Compare May 24, 2023 06:28
@ispeters
Copy link
Contributor Author

To make this really work well, I'll need to follow up with customizations of with_scheduler_affinity for the algorithms that need it, which is probably all algorithms that have a computed is_always_scheduler_affine property.

include/unifex/task.hpp Outdated Show resolved Hide resolved
Comment on lines +321 to +322
// TODO: verify that `at_coroutine_exit()` can't be used to break scheduler
// affinity by running an async task that reschedules
Copy link
Contributor Author

Choose a reason for hiding this comment

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

at_coroutine_exit can already break Scheduler affinity so this is a TODO, which I've captured in #535.

This diff changes how `unifex::task<>` implements *Scheduler* affinity to work
more like `folly::coro::Task<>`.  What Folly calls `co_viaIfAsync`, this diff
calls `with_scheduler_affinity`, which is a new CPO.

`with_scheduler_affinity` is a *Sender* algorithm that maps the given *Sender*
to another *Sender* that must meet new postconditions if the *Receiver* that
it's connected to meets certain preconditions.  The new preconditions are:
 - the eventual *Receiver* must provide a "current *Scheduler*";
 - the result of `with_scheduler_affinity` must be started on the *Receiver's*
   current *Scheduler*; and
 - stop requests delivered to the new *Sender* must be delivered on the
   *Receiver's* current *Scheduler*.

The *Sender* returned from `with_scheduler_affinity` must complete on its
*Receiver's* current *Scheduler* (i.e. must complete where it was started) so
long as all the above preconditions are met.

Any *Sender* type, `S`, that has `sender_traits<S>::is_always_scheduler_affine`
set to `true` will be returned unmodified from `with_scheduler_affinity`.  For
*Senders* that are not always *Scheduler*-affine and that do not customize
`with_scheduler_affinity`, the default implementation is:
```
template <typename Sender, typename Scheduler>
auto with_scheduler_affinity(Sender&& s, Scheduler&& sched) {
  return finally(
      std::forward<Sender>(s),
      unstoppable(schedule(std::forward<Scheduler>(sched))));
}
```
* nested stop source on the correct scheduler; and
* - ensure that, if the async stop request is ever started, we wait for
* *both* the async stop request *and* the nested operation to complete
* before continuating our continuation.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

lol, "continuating"

include/unifex/task.hpp Outdated Show resolved Hide resolved
This diff address the review comments I left myself, other than the ones
I punted to issues.

I also realized I could use a `manual_lifetime<>` instead of a
`std::optional<>` for the `_sr_thunk_task`'s stop callback, which saves
a little overhead.
@ispeters ispeters force-pushed the reimplement_scheduler_affinity branch from 25aea72 to e002af2 Compare May 31, 2023 21:30

template <typename Sender, typename Scheduler>
using wsa_sender_wrapper =
typename _wsa_sender_wrapper<Sender, Scheduler>::type;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: just _wsa_sender?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe next time I'm in here; I'd like to get this merged so we can sync it internally.

@ispeters ispeters merged commit 1067303 into main Jun 1, 2023
@ispeters ispeters deleted the reimplement_scheduler_affinity branch June 1, 2023 00:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants