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