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:
Carl Lerche
2017-10-13 14:15:20 -07:00
committed by GitHub
parent 5c1bde7d62
commit 7c287af0d0
6 changed files with 196 additions and 9 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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();