fix(http1): force always-ready connections to yield after a few spins
This commit is contained in:
@@ -4,8 +4,10 @@ pub(crate) mod exec;
|
||||
pub(crate) mod io;
|
||||
mod lazy;
|
||||
mod never;
|
||||
pub(crate) mod task;
|
||||
|
||||
pub(crate) use self::buf::StaticBuf;
|
||||
pub(crate) use self::exec::Exec;
|
||||
pub(crate) use self::lazy::{lazy, Started as Lazy};
|
||||
pub use self::never::Never;
|
||||
pub(crate) use self::task::YieldNow;
|
||||
|
||||
40
src/common/task.rs
Normal file
40
src/common/task.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use futures::{Async, Poll, task::Task};
|
||||
|
||||
use super::Never;
|
||||
|
||||
/// A type to help "yield" a future, such that it is re-scheduled immediately.
|
||||
///
|
||||
/// Useful for spin counts, so a future doesn't hog too much time.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct YieldNow {
|
||||
cached_task: Option<Task>,
|
||||
}
|
||||
|
||||
impl YieldNow {
|
||||
pub(crate) fn new() -> YieldNow {
|
||||
YieldNow {
|
||||
cached_task: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Ok(Async::NotReady)` always, while also notifying the
|
||||
/// current task so that it is rescheduled immediately.
|
||||
///
|
||||
/// Since it never returns `Async::Ready` or `Err`, those types are
|
||||
/// set to `Never`.
|
||||
pub(crate) fn poll_yield(&mut self) -> Poll<Never, Never> {
|
||||
// Check for a cached `Task` first...
|
||||
if let Some(ref t) = self.cached_task {
|
||||
if t.will_notify_current() {
|
||||
t.notify();
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
}
|
||||
|
||||
// No cached task, or not current, so get a new one...
|
||||
let t = ::futures::task::current();
|
||||
t.notify();
|
||||
self.cached_task = Some(t);
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user