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)?; | ||||
|  | ||||
|         // TODO: If there is available connection capacity, release pending | ||||
|         // streams. | ||||
|         // | ||||
|         // Get the current connection capacity | ||||
|         let connection = self.prioritize.available_window(); | ||||
|  | ||||
|         // Walk each stream pending capacity and see if this change to the | ||||
|         // 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!(); | ||||
|         // Ok(()) | ||||
|                 // Get the current unadvertised window | ||||
|                 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, | ||||
|   | ||||
| @@ -32,9 +32,9 @@ pub(super) struct List<B> { | ||||
| pub(super) trait Next { | ||||
|     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 | ||||
| @@ -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<B> List<B> { | ||||
| @@ -157,7 +171,7 @@ impl<B> List<B> { | ||||
|             Some(ref mut idxs) => { | ||||
|                 // Update the current tail node to point to `stream` | ||||
|                 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 | ||||
|                 idxs.tail = stream.key(); | ||||
| @@ -181,7 +195,7 @@ impl<B> List<B> { | ||||
|                 assert!(N::next(&*stream).is_none()); | ||||
|                 self.indices = None; | ||||
|             } else { | ||||
|                 idxs.head = N::take_next(&mut *stream); | ||||
|                 idxs.head = N::take_next(&mut *stream).unwrap(); | ||||
|                 self.indices = Some(idxs); | ||||
|             } | ||||
|  | ||||
| @@ -190,6 +204,53 @@ impl<B> List<B> { | ||||
|  | ||||
|         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 ===== | ||||
|   | ||||
| @@ -97,13 +97,12 @@ impl store::Next for Next { | ||||
|         stream.next | ||||
|     } | ||||
|  | ||||
|     fn set_next<B>(stream: &mut Stream<B>, key: store::Key) { | ||||
|         debug_assert!(stream.next.is_none()); | ||||
|         stream.next = Some(key); | ||||
|     fn set_next<B>(stream: &mut Stream<B>, key: Option<store::Key>) { | ||||
|         stream.next = key; | ||||
|     } | ||||
|  | ||||
|     fn take_next<B>(stream: &mut Stream<B>) -> store::Key { | ||||
|         stream.next.take().unwrap() | ||||
|     fn take_next<B>(stream: &mut Stream<B>) -> Option<store::Key> { | ||||
|         stream.next.take() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -112,12 +111,11 @@ impl store::Next for NextCapacity { | ||||
|         stream.next_capacity | ||||
|     } | ||||
|  | ||||
|     fn set_next<B>(stream: &mut Stream<B>, key: store::Key) { | ||||
|         debug_assert!(stream.next_capacity.is_none()); | ||||
|         stream.next_capacity = Some(key); | ||||
|     fn set_next<B>(stream: &mut Stream<B>, key: Option<store::Key>) { | ||||
|         stream.next_capacity = key; | ||||
|     } | ||||
|  | ||||
|     fn take_next<B>(stream: &mut Stream<B>) -> store::Key { | ||||
|         stream.next_capacity.take().unwrap() | ||||
|     fn take_next<B>(stream: &mut Stream<B>) -> Option<store::Key> { | ||||
|         stream.next_capacity.take() | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user