More work on window updates
This commit is contained in:
@@ -159,14 +159,56 @@ impl<B> Send<B> where B: Buf {
|
|||||||
{
|
{
|
||||||
self.prioritize.recv_window_update(frame)?;
|
self.prioritize.recv_window_update(frame)?;
|
||||||
|
|
||||||
// TODO: If there is available connection capacity, release pending
|
// Get the current connection capacity
|
||||||
// streams.
|
let connection = self.prioritize.available_window();
|
||||||
//
|
|
||||||
// Walk each stream pending capacity and see if this change to the
|
// Walk each stream pending capacity and see if this change to the
|
||||||
// connection window can increase the advertised capacity of the stream.
|
// connection window can increase the advertised capacity of the stream.
|
||||||
|
//
|
||||||
|
// TODO: This is not a hugely efficient operation. It could be better to
|
||||||
|
// change the pending_capacity structure to a red-black tree.
|
||||||
|
//
|
||||||
|
self.pending_capacity.retain::<stream::NextCapacity, _>(
|
||||||
|
store,
|
||||||
|
|stream| {
|
||||||
|
// Make sure that the stream is flagged as queued
|
||||||
|
debug_assert!(stream.is_pending_send_capacity);
|
||||||
|
|
||||||
unimplemented!();
|
// Get the current unadvertised window
|
||||||
// Ok(())
|
let unadvertised = stream.unadvertised_send_window;
|
||||||
|
|
||||||
|
if unadvertised == 0 {
|
||||||
|
stream.is_pending_send_capacity = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let effective_window_size = match stream.state.send_flow_control() {
|
||||||
|
Some(flow) => flow.effective_window_size(),
|
||||||
|
None => {
|
||||||
|
// The state transitioned and this stream is no longer
|
||||||
|
// waiting for updates
|
||||||
|
stream.is_pending_send_capacity = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if connection <= effective_window_size - unadvertised {
|
||||||
|
// The window is not increased, but we remain interested in
|
||||||
|
// updates in the future.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if connection >= effective_window_size {
|
||||||
|
stream.unadvertised_send_window = 0;
|
||||||
|
} else {
|
||||||
|
stream.unadvertised_send_window = effective_window_size - connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.notify_send();
|
||||||
|
true
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_stream_window_update(&mut self,
|
pub fn recv_stream_window_update(&mut self,
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ pub(super) struct List<B> {
|
|||||||
pub(super) trait Next {
|
pub(super) trait Next {
|
||||||
fn next<B>(stream: &Stream<B>) -> Option<Key>;
|
fn next<B>(stream: &Stream<B>) -> Option<Key>;
|
||||||
|
|
||||||
fn set_next<B>(stream: &mut Stream<B>, key: Key);
|
fn set_next<B>(stream: &mut Stream<B>, key: Option<Key>);
|
||||||
|
|
||||||
fn take_next<B>(stream: &mut Stream<B>) -> Key;
|
fn take_next<B>(stream: &mut Stream<B>) -> Option<Key>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A linked list
|
/// A linked list
|
||||||
@@ -125,6 +125,20 @@ impl<B> Store<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<B> ops::Index<Key> for Store<B> {
|
||||||
|
type Output = Stream<B>;
|
||||||
|
|
||||||
|
fn index(&self, key: Key) -> &Self::Output {
|
||||||
|
self.slab.index(key.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B> ops::IndexMut<Key> for Store<B> {
|
||||||
|
fn index_mut(&mut self, key: Key) -> &mut Self::Output {
|
||||||
|
self.slab.index_mut(key.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ===== impl List =====
|
// ===== impl List =====
|
||||||
|
|
||||||
impl<B> List<B> {
|
impl<B> List<B> {
|
||||||
@@ -157,7 +171,7 @@ impl<B> List<B> {
|
|||||||
Some(ref mut idxs) => {
|
Some(ref mut idxs) => {
|
||||||
// Update the current tail node to point to `stream`
|
// Update the current tail node to point to `stream`
|
||||||
let key = stream.key();
|
let key = stream.key();
|
||||||
N::set_next(&mut stream.resolve(idxs.tail), key);
|
N::set_next(&mut stream.resolve(idxs.tail), Some(key));
|
||||||
|
|
||||||
// Update the tail pointer
|
// Update the tail pointer
|
||||||
idxs.tail = stream.key();
|
idxs.tail = stream.key();
|
||||||
@@ -181,7 +195,7 @@ impl<B> List<B> {
|
|||||||
assert!(N::next(&*stream).is_none());
|
assert!(N::next(&*stream).is_none());
|
||||||
self.indices = None;
|
self.indices = None;
|
||||||
} else {
|
} else {
|
||||||
idxs.head = N::take_next(&mut *stream);
|
idxs.head = N::take_next(&mut *stream).unwrap();
|
||||||
self.indices = Some(idxs);
|
self.indices = Some(idxs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +204,53 @@ impl<B> List<B> {
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn retain<N, F>(&mut self, store: &mut Store<B>, mut f: F)
|
||||||
|
where N: Next,
|
||||||
|
F: FnMut(&mut Stream<B>) -> bool,
|
||||||
|
{
|
||||||
|
if let Some(mut idxs) = self.indices {
|
||||||
|
let mut prev = None;
|
||||||
|
let mut curr = idxs.head;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if f(&mut store[curr]) {
|
||||||
|
// Element is retained, walk to the next
|
||||||
|
if let Some(next) = N::next(&mut store[curr]) {
|
||||||
|
prev = Some(curr);
|
||||||
|
curr = next;
|
||||||
|
} else {
|
||||||
|
// Tail
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Element is dropped
|
||||||
|
if let Some(prev) = prev {
|
||||||
|
let next = N::take_next(&mut store[curr]);
|
||||||
|
N::set_next(&mut store[prev], next);
|
||||||
|
|
||||||
|
// current is last element, but guaranteed to not be the
|
||||||
|
// only one
|
||||||
|
if next.is_none() {
|
||||||
|
idxs.tail = prev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(next) = N::take_next(&mut store[curr]) {
|
||||||
|
curr = next;
|
||||||
|
idxs.head = next;
|
||||||
|
} else {
|
||||||
|
// Only element
|
||||||
|
self.indices = None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.indices = Some(idxs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== impl Ptr =====
|
// ===== impl Ptr =====
|
||||||
|
|||||||
@@ -97,13 +97,12 @@ impl store::Next for Next {
|
|||||||
stream.next
|
stream.next
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_next<B>(stream: &mut Stream<B>, key: store::Key) {
|
fn set_next<B>(stream: &mut Stream<B>, key: Option<store::Key>) {
|
||||||
debug_assert!(stream.next.is_none());
|
stream.next = key;
|
||||||
stream.next = Some(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take_next<B>(stream: &mut Stream<B>) -> store::Key {
|
fn take_next<B>(stream: &mut Stream<B>) -> Option<store::Key> {
|
||||||
stream.next.take().unwrap()
|
stream.next.take()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,12 +111,11 @@ impl store::Next for NextCapacity {
|
|||||||
stream.next_capacity
|
stream.next_capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_next<B>(stream: &mut Stream<B>, key: store::Key) {
|
fn set_next<B>(stream: &mut Stream<B>, key: Option<store::Key>) {
|
||||||
debug_assert!(stream.next_capacity.is_none());
|
stream.next_capacity = key;
|
||||||
stream.next_capacity = Some(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take_next<B>(stream: &mut Stream<B>) -> store::Key {
|
fn take_next<B>(stream: &mut Stream<B>) -> Option<store::Key> {
|
||||||
stream.next_capacity.take().unwrap()
|
stream.next_capacity.take()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user