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

[FEATURE REQUEST] Add yield_now future or equivelant #1215

Open
alatiera opened this issue Oct 30, 2023 · 4 comments
Open

[FEATURE REQUEST] Add yield_now future or equivelant #1215

alatiera opened this issue Oct 30, 2023 · 4 comments
Labels
enhancement New feature or request

Comments

@alatiera
Copy link
Contributor

alatiera commented Oct 30, 2023

Both tokio and async-std have a yield_now future, which is a manual hand-off back to executor to allow to schedule other things. Similar to G_SOURCE_CONTINUE/glib::ControlFlow::Continue.

An example is when you are manually looping over sync code you can await after a long running task.

async move {
    while let Some(item) = data.next() {
        let thing = heavey_operation(item);
        tokio::task::yield_now().await;
    }
}

For another example see:

Example code for a yield future, though should ideally be ported to impl Future

let mut once = false;
futures::future::poll_fn(|ctx| {
    if once {
        Poll::Ready(())
    } else {
        once = true;
        let waker = ctx.waker().clone();
        glib::idle_add(move || {
            waker.wake();
            glib::Continue::Break
        });
        Poll::Pending
    }
}).await;

cc @sdroege

@alatiera alatiera added the enhancement New feature or request label Oct 30, 2023
@sdroege
Copy link
Member

sdroege commented Oct 30, 2023

Some thoughts:

  • I think there should also be a yield_now_with_priority() which schedules the wake up with a different priority
  • The idle_add() should go via the idle GSource and use the thread default main context
  • The whole thing can be a bit more lightweight (for the compiler!) with a impl Future around a simple struct with a bool
  • If the same priority is used it might be possible to go without the separate idle_add() by poking at the currently active GSource, to be confirmed
  • Maybe the above needs to be limited to be run from inside a glib main context

@alatiera Do you want to make a PR for this?

@alatiera
Copy link
Contributor Author

Thanks for the comment and the implementation details!

Maybe the above needs to be limited to be run from inside a glib main context

given that the other executors have their own versions, I think this would be fine

@alatiera Do you want to make a PR for this?

Yea I'd like to give a go at some point, but not high priority for now.

@SeaDve
Copy link
Contributor

SeaDve commented Nov 3, 2023

Somewhat unrelated, and more like a clarification:

async move {
while let Some(item) = data.next() {
let thing = heavey_operation(item);
sender.send(thing).await.unwrap();
tokio::task::yield_now().await;
}
}

Isn't here sender.send(thing).await.unwrap(); is already doing the yielding, thus tokio::task::yield_now().await; won't be necessary?

@alatiera
Copy link
Contributor Author

alatiera commented Nov 3, 2023

Isn't here sender.send(thing).await.unwrap(); is already doing the yielding, thus tokio::task::yield_now().await; won't be necessary?

Yes, bad example code and wasn't even needed anyway. Removed it from the example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants