Implement Client::poll_ready (#21)
Client::poll_ready ensures that the connection is ale to to initiate a new request stream to the remote server. When the server is at capacity, a task is stored to be notified when capacity is available.
This commit is contained in:
committed by
Carl Lerche
parent
150c3160be
commit
e015d7bfba
@@ -27,19 +27,17 @@ pub(super) struct Send<B> {
|
||||
/// List of streams waiting for outbound connection capacity
|
||||
pending_capacity: store::List<B>,
|
||||
|
||||
/// Task awaiting notification to open a new stream.
|
||||
blocked_open: Option<task::Task>,
|
||||
|
||||
/// Prioritization layer
|
||||
prioritize: Prioritize<B>,
|
||||
}
|
||||
|
||||
impl<B> Send<B> where B: Buf {
|
||||
|
||||
/// Create a new `Send`
|
||||
pub fn new<P: Peer>(config: &Config) -> Self {
|
||||
let next_stream_id = if P::is_server() {
|
||||
2
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let next_stream_id = if P::is_server() { 2 } else { 1 };
|
||||
|
||||
Send {
|
||||
max_streams: config.max_local_initiated,
|
||||
@@ -47,10 +45,24 @@ impl<B> Send<B> where B: Buf {
|
||||
next_stream_id: next_stream_id.into(),
|
||||
init_window_sz: config.init_local_window_sz,
|
||||
pending_capacity: store::List::new(),
|
||||
blocked_open: None,
|
||||
prioritize: Prioritize::new(config),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poll_open_ready<P: Peer>(&mut self) -> Poll<(), ConnectionError> {
|
||||
try!(self.ensure_can_open::<P>());
|
||||
|
||||
if let Some(max) = self.max_streams {
|
||||
if max <= self.num_streams {
|
||||
self.blocked_open = Some(task::current());
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(Async::Ready(()));
|
||||
}
|
||||
|
||||
/// Update state reflecting a new, locally opened stream
|
||||
///
|
||||
/// Returns the stream state if successful. `None` if refused
|
||||
@@ -129,9 +141,9 @@ impl<B> Send<B> where B: Buf {
|
||||
}
|
||||
|
||||
if stream.state.is_closed() {
|
||||
return Err(InactiveStreamId.into())
|
||||
return Err(InactiveStreamId.into());
|
||||
} else {
|
||||
return Err(UnexpectedFrameType.into())
|
||||
return Err(UnexpectedFrameType.into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +287,8 @@ impl<B> Send<B> where B: Buf {
|
||||
|
||||
pub fn apply_remote_settings(&mut self,
|
||||
settings: &frame::Settings,
|
||||
store: &mut Store<B>) {
|
||||
store: &mut Store<B>)
|
||||
{
|
||||
if let Some(val) = settings.max_concurrent_streams() {
|
||||
self.max_streams = Some(val as usize);
|
||||
}
|
||||
@@ -342,6 +355,12 @@ impl<B> Send<B> where B: Buf {
|
||||
|
||||
pub fn dec_num_streams(&mut self) {
|
||||
self.num_streams -= 1;
|
||||
|
||||
if self.num_streams < self.max_streams.unwrap_or(::std::usize::MAX) {
|
||||
if let Some(task) = self.blocked_open.take() {
|
||||
task.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the local actor can initiate a stream with the given ID.
|
||||
|
||||
Reference in New Issue
Block a user