Fix some flow control bugs. (#152)
* Release stream capacity back to the connection to avoid capacity leaks. * Actually notify waiting tasks when capacity becomes available.
This commit is contained in:
		| @@ -248,6 +248,8 @@ where | ||||
|     where | ||||
|         R: Resolve<B, P>, | ||||
|     { | ||||
|         trace!("assign_connection_capacity; inc={}", inc); | ||||
|  | ||||
|         self.flow.assign_capacity(inc); | ||||
|  | ||||
|         // Assign newly acquired capacity to streams pending capacity. | ||||
| @@ -315,6 +317,8 @@ where | ||||
|             // TODO: Should prioritization factor into this? | ||||
|             let assign = cmp::min(conn_available, additional); | ||||
|  | ||||
|             trace!("  assigning; num={}", assign); | ||||
|  | ||||
|             // Assign the capacity to the stream | ||||
|             stream.assign_capacity(assign); | ||||
|  | ||||
|   | ||||
| @@ -214,6 +214,7 @@ where | ||||
|         } | ||||
|  | ||||
|         if !stream.send_capacity_inc { | ||||
|             stream.wait_send(); | ||||
|             return Ok(Async::NotReady); | ||||
|         } | ||||
|  | ||||
| @@ -304,13 +305,16 @@ where | ||||
|  | ||||
|                 trace!("decrementing all windows; dec={}", dec); | ||||
|  | ||||
|                 let mut total_reclaimed = 0; | ||||
|                 store.for_each(|mut stream| { | ||||
|                     let stream = &mut *stream; | ||||
|  | ||||
|                     stream.send_flow.dec_window(dec); | ||||
|  | ||||
|                     let available = stream.send_flow.available().as_size(); | ||||
|                     stream.send_flow.claim_capacity(cmp::min(dec, available)); | ||||
|                     let reclaim = cmp::min(dec, available); | ||||
|                     stream.send_flow.claim_capacity(reclaim); | ||||
|                     total_reclaimed += reclaim; | ||||
|  | ||||
|                     trace!( | ||||
|                         "decremented stream window; id={:?}; decr={}; flow={:?}", | ||||
| @@ -319,15 +323,15 @@ where | ||||
|                         stream.send_flow | ||||
|                     ); | ||||
|  | ||||
|                     // TODO: Probably try to assign capacity? | ||||
|  | ||||
|                     // TODO: Handle reclaiming connection level window | ||||
|                     // capacity. | ||||
|  | ||||
|                     // TODO: Should this notify the producer? | ||||
|                     // TODO: Should this notify the producer when the capacity | ||||
|                     // of a stream is reduced? Maybe it should if the capacity | ||||
|                     // is reduced to zero, allowing the producer to stop work. | ||||
|  | ||||
|                     Ok::<_, RecvError>(()) | ||||
|                 })?; | ||||
|  | ||||
|                 self.prioritize | ||||
|                     .assign_connection_capacity(total_reclaimed, store); | ||||
|             } else if val > old_val { | ||||
|                 let inc = val - old_val; | ||||
|  | ||||
|   | ||||
| @@ -229,8 +229,12 @@ where | ||||
|         self.send_capacity_inc = true; | ||||
|         self.send_flow.assign_capacity(capacity); | ||||
|  | ||||
|         trace!("  assigned capacity to stream; available={}; buffered={}; id={:?}", | ||||
|                self.send_flow.available(), self.buffered_send_data, self.id); | ||||
|  | ||||
|         // Only notify if the capacity exceeds the amount of buffered data | ||||
|         if self.send_flow.available() > self.buffered_send_data { | ||||
|             trace!("  notifying task"); | ||||
|             self.notify_send(); | ||||
|         } | ||||
|     } | ||||
| @@ -263,6 +267,10 @@ where | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn wait_send(&mut self) { | ||||
|         self.send_task = Some(task::current()); | ||||
|     } | ||||
|  | ||||
|     pub fn notify_recv(&mut self) { | ||||
|         if let Some(task) = self.recv_task.take() { | ||||
|             task.notify(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user