Fix flow control bug (#177)
This patch fixes a bug that prevents sent data from being flushed to the socket. When data is sent, the task managing the connection must be notified. A guard exists that prevents unnecessary notification of the connection when the stream does not have any send capacity. However, this guard was buggy. Instead of notifying the connection if *any* data can be sent, it notified the connection only when *all* data could be sent. This patch fixes the check as well as adds some tests that ensure the connection task is notified.
This commit is contained in:
		
							
								
								
									
										55
									
								
								tests/support/notify.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								tests/support/notify.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| use futures::executor::{self, Notify}; | ||||
|  | ||||
| use std::sync::Arc; | ||||
| use std::sync::atomic::AtomicBool; | ||||
| use std::sync::atomic::Ordering::SeqCst; | ||||
|  | ||||
| pub struct MockNotify { | ||||
|     inner: Arc<Inner>, | ||||
| } | ||||
|  | ||||
| struct Inner { | ||||
|     notified: AtomicBool, | ||||
| } | ||||
|  | ||||
| impl MockNotify { | ||||
|     pub fn new() -> Self { | ||||
|         MockNotify { | ||||
|             inner: Arc::new(Inner { | ||||
|                 notified: AtomicBool::new(false), | ||||
|             }), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn with<F: FnOnce() -> R, R>(&self, f: F) -> R { | ||||
|         use futures::Async::Ready; | ||||
|         use futures::future::poll_fn; | ||||
|  | ||||
|         self.clear(); | ||||
|  | ||||
|         let mut f = Some(f); | ||||
|  | ||||
|         let res = executor::spawn(poll_fn(move || { | ||||
|             Ok::<_, ()>(Ready(f.take().unwrap()())) | ||||
|         })).poll_future_notify(&self.inner, 0); | ||||
|  | ||||
|         match res { | ||||
|             Ok(Ready(v)) => v, | ||||
|             _ => unreachable!(), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn clear(&self) { | ||||
|         self.inner.notified.store(false, SeqCst); | ||||
|     } | ||||
|  | ||||
|     pub fn is_notified(&self) -> bool { | ||||
|         self.inner.notified.load(SeqCst) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Notify for Inner { | ||||
|     fn notify(&self, _: usize) { | ||||
|         self.notified.store(true, SeqCst); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user