-
Notifications
You must be signed in to change notification settings - Fork 638
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
Add macro yield_now
for futures_util::async_await
#1430
Conversation
Can you say more about your usecase? How do you intend to wake up this task when it should be polled again? |
I'm writing a static file server for And hyper requires that I use poll_ready to check if I can send it, each time I send data through the sender. Which means, my code like this: fn work(self, mut sender: hyper::body::Sender, mut file: File) -> FutureObj<'static, Result<(), ()>> {
let mut chunk:Option<Chunk> = None;
FutureObj::new(Box::new(async move {
loop {
// read 4K data from file to 'chunk', if it is 'None'
match sender.poll_ready() {
Err(_) => {
// Some code
}
Ok(x) => {
if x.is_not_ready() {
yield_now!();
continue;
}
}
}
// send data and clean 'chunk'
}
}))
} Without |
Is there a reason you're not using the |
Document of In fact, I don't want to look at the specific scene. The point is, there is currently no simple way to polling(not I believe that most of the time there will be more efficient implementations(implement |
I think |
maybe one usecase is doing some cpu-intensive work gradually in single thread executor : async {
for i in 0..N {
// do some cpu-intensive work...
if i % 1000 == 0 {
yield_now!();
}
}
} |
@laizy That would be incorrect, since nothing would cause that task to resume. That's why I'm trying to clarify here, as this is the wrong function for most purposes I can think of. |
@DCjanus That |
I found that my implementation doesn't always work, I will close this pull request. Maybe, |
@DCjanus I don't think you want to delay for some arbitrary time period-- that |
@cramertj You are right, I am not trying to delay, but i can replace 'yield_now!()' with 'await(Delay::new( now() ))' |
@cramertj Does't the inner let mut pool = executor::LocalPool::new();
let mut spawner = pool.spawner();
let a = async {
for i in 0..10u32 {
println!("task a: {}", i);
if i % 4 == 3 {
println!("task a begin yield at {}", i);
yield_now!();
println!("task a end yield at {}", i);
}
}
};
let b = async {
for i in 0..10u32 {
println!("task b: {}", i);
if i % 4 == 3 {
println!("task b begin yield at {}", i);
yield_now!();
println!("task b end yield at {}", i);
}
}
};
spawner.spawn(a);
spawner.spawn(b);
pool.run(); output:
|
@laizy Immediately waking will just result in spin-looping. |
@cramertj em,I agree this macro is not suitable for @DCjanus 's usecase. But for cpu-intensive task, one option is setup an dedicated cpu-pool. but if i want run it in the current executor, periodically calling |
@laizy Yeah, that could be true depending on the scheduling model of the executor. |
@cramertj I see what you mean now, thanks. |
A useful 'helper macro', the asynchronous version of
std::thread::yield_now()
.Reference: https://users.rust-lang.org/t/what-is-the-asynchronous-version-of-yield-now/24367/2
PS: Thanks for being patient with this. I'm not a native speaker, my English is very bad. If there is something wrong, whether it is code or grammar, feel free to point it out.