split Client into (Client, Connection) (#107)
The Connection type is a `Future` that drives all of the IO of the client connection. The Client type is separate, and is used to send requests into the connection.
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
use super::*;
|
||||
use client;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::usize;
|
||||
@@ -10,20 +9,17 @@ where
|
||||
P: Peer,
|
||||
{
|
||||
/// Maximum number of locally initiated streams
|
||||
max_send_streams: Option<usize>,
|
||||
max_send_streams: usize,
|
||||
|
||||
/// Current number of remote initiated streams
|
||||
num_send_streams: usize,
|
||||
|
||||
/// Maximum number of remote initiated streams
|
||||
max_recv_streams: Option<usize>,
|
||||
max_recv_streams: usize,
|
||||
|
||||
/// Current number of locally initiated streams
|
||||
num_recv_streams: usize,
|
||||
|
||||
/// Task awaiting notification to open a new stream.
|
||||
blocked_open: Option<task::Task>,
|
||||
|
||||
_p: PhantomData<P>,
|
||||
}
|
||||
|
||||
@@ -34,22 +30,17 @@ where
|
||||
/// Create a new `Counts` using the provided configuration values.
|
||||
pub fn new(config: &Config) -> Self {
|
||||
Counts {
|
||||
max_send_streams: config.local_max_initiated,
|
||||
max_send_streams: config.local_max_initiated.unwrap_or(usize::MAX),
|
||||
num_send_streams: 0,
|
||||
max_recv_streams: config.remote_max_initiated,
|
||||
max_recv_streams: config.remote_max_initiated.unwrap_or(usize::MAX),
|
||||
num_recv_streams: 0,
|
||||
blocked_open: None,
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the receive stream concurrency can be incremented
|
||||
pub fn can_inc_num_recv_streams(&self) -> bool {
|
||||
if let Some(max) = self.max_recv_streams {
|
||||
max > self.num_recv_streams
|
||||
} else {
|
||||
true
|
||||
}
|
||||
self.max_recv_streams > self.num_recv_streams
|
||||
}
|
||||
|
||||
/// Increments the number of concurrent receive streams.
|
||||
@@ -66,11 +57,7 @@ where
|
||||
|
||||
/// Returns true if the send stream concurrency can be incremented
|
||||
pub fn can_inc_num_send_streams(&self) -> bool {
|
||||
if let Some(max) = self.max_send_streams {
|
||||
max > self.num_send_streams
|
||||
} else {
|
||||
true
|
||||
}
|
||||
self.max_send_streams > self.num_send_streams
|
||||
}
|
||||
|
||||
/// Increments the number of concurrent send streams.
|
||||
@@ -87,7 +74,7 @@ where
|
||||
|
||||
pub fn apply_remote_settings(&mut self, settings: &frame::Settings) {
|
||||
if let Some(val) = settings.max_concurrent_streams() {
|
||||
self.max_send_streams = Some(val as usize);
|
||||
self.max_send_streams = val as usize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +86,7 @@ where
|
||||
where
|
||||
F: FnOnce(&mut Self, &mut store::Ptr<B, P>) -> U,
|
||||
{
|
||||
let is_counted = stream.state.is_counted();
|
||||
let is_counted = stream.is_counted();
|
||||
|
||||
// Run the action
|
||||
let ret = f(self, &mut stream);
|
||||
@@ -127,29 +114,10 @@ where
|
||||
}
|
||||
|
||||
fn dec_num_streams(&mut self, id: StreamId) {
|
||||
use std::usize;
|
||||
|
||||
if P::is_local_init(id) {
|
||||
self.num_send_streams -= 1;
|
||||
|
||||
if self.num_send_streams < self.max_send_streams.unwrap_or(usize::MAX) {
|
||||
if let Some(task) = self.blocked_open.take() {
|
||||
task.notify();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.num_recv_streams -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Counts<client::Peer> {
|
||||
pub fn poll_open_ready(&mut self) -> Async<()> {
|
||||
if !self.can_inc_num_send_streams() {
|
||||
self.blocked_open = Some(task::current());
|
||||
return Async::NotReady;
|
||||
}
|
||||
|
||||
return Async::Ready(());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ mod stream;
|
||||
mod streams;
|
||||
|
||||
pub(crate) use self::prioritize::Prioritized;
|
||||
pub(crate) use self::store::Key;
|
||||
pub(crate) use self::streams::{StreamRef, Streams};
|
||||
|
||||
use self::buffer::Buffer;
|
||||
|
||||
@@ -22,6 +22,9 @@ where
|
||||
/// Queue of streams waiting for window capacity to produce data.
|
||||
pending_capacity: store::Queue<B, stream::NextSendCapacity, P>,
|
||||
|
||||
/// Streams waiting for capacity due to max concurrency
|
||||
pending_open: store::Queue<B, stream::NextOpen, P>,
|
||||
|
||||
/// Connection level flow control governing sent data
|
||||
flow: FlowControl,
|
||||
|
||||
@@ -60,6 +63,7 @@ where
|
||||
Prioritize {
|
||||
pending_send: store::Queue::new(),
|
||||
pending_capacity: store::Queue::new(),
|
||||
pending_open: store::Queue::new(),
|
||||
flow: flow,
|
||||
buffer: Buffer::new(),
|
||||
}
|
||||
@@ -75,15 +79,22 @@ where
|
||||
// Queue the frame in the buffer
|
||||
stream.pending_send.push_back(&mut self.buffer, frame);
|
||||
|
||||
// Queue the stream
|
||||
self.pending_send.push(stream);
|
||||
// If the stream is waiting to be opened, nothing more to do.
|
||||
if !stream.is_pending_open {
|
||||
// Queue the stream
|
||||
self.pending_send.push(stream);
|
||||
|
||||
// Notify the connection.
|
||||
if let Some(task) = task.take() {
|
||||
task.notify();
|
||||
// Notify the connection.
|
||||
if let Some(task) = task.take() {
|
||||
task.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn queue_open(&mut self, stream: &mut store::Ptr<B, P>) {
|
||||
self.pending_open.push(stream);
|
||||
}
|
||||
|
||||
/// Send a data frame
|
||||
pub fn send_data(
|
||||
&mut self,
|
||||
@@ -371,6 +382,7 @@ where
|
||||
trace!("poll_complete");
|
||||
|
||||
loop {
|
||||
self.schedule_pending_open(store, counts);
|
||||
match self.pop_frame(store, max_frame_len, counts) {
|
||||
Some(frame) => {
|
||||
trace!("writing frame={:?}", frame);
|
||||
@@ -482,7 +494,7 @@ where
|
||||
trace!("pop_frame; stream={:?}", stream.id);
|
||||
debug_assert!(!stream.pending_send.is_empty());
|
||||
|
||||
let is_counted = stream.state.is_counted();
|
||||
let is_counted = stream.is_counted();
|
||||
|
||||
let frame = match stream.pending_send.pop_front(&mut self.buffer).unwrap() {
|
||||
Frame::Data(mut frame) => {
|
||||
@@ -594,6 +606,23 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn schedule_pending_open(&mut self, store: &mut Store<B, P>, counts: &mut Counts<P>) {
|
||||
trace!("schedule_pending_open");
|
||||
// check for any pending open streams
|
||||
while counts.can_inc_num_send_streams() {
|
||||
if let Some(mut stream) = self.pending_open.pop(store) {
|
||||
trace!("schedule_pending_open; stream={:?}", stream.id);
|
||||
counts.inc_num_send_streams();
|
||||
self.pending_send.push(&mut stream);
|
||||
if let Some(task) = stream.open_task.take() {
|
||||
task.notify();
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Prioritized =====
|
||||
|
||||
@@ -43,20 +43,9 @@ where
|
||||
self.init_window_sz
|
||||
}
|
||||
|
||||
/// Update state reflecting a new, locally opened stream
|
||||
///
|
||||
/// Returns the stream state if successful. `None` if refused
|
||||
pub fn open(&mut self, counts: &mut Counts<P>) -> Result<StreamId, UserError> {
|
||||
if !counts.can_inc_num_send_streams() {
|
||||
return Err(Rejected.into());
|
||||
}
|
||||
|
||||
pub fn open(&mut self) -> Result<StreamId, UserError> {
|
||||
let stream_id = self.try_open()?;
|
||||
|
||||
// Increment the number of locally initiated streams
|
||||
counts.inc_num_send_streams();
|
||||
self.next_stream_id = stream_id.next_id();
|
||||
|
||||
Ok(stream_id)
|
||||
}
|
||||
|
||||
@@ -64,6 +53,7 @@ where
|
||||
&mut self,
|
||||
frame: frame::Headers,
|
||||
stream: &mut store::Ptr<B, P>,
|
||||
counts: &mut Counts<P>,
|
||||
task: &mut Option<Task>,
|
||||
) -> Result<(), UserError> {
|
||||
trace!(
|
||||
@@ -77,6 +67,14 @@ where
|
||||
// Update the state
|
||||
stream.state.send_open(end_stream)?;
|
||||
|
||||
if P::is_local_init(frame.stream_id()) {
|
||||
if counts.can_inc_num_send_streams() {
|
||||
counts.inc_num_send_streams();
|
||||
} else {
|
||||
self.prioritize.queue_open(stream);
|
||||
}
|
||||
}
|
||||
|
||||
// Queue the frame for sending
|
||||
self.prioritize.queue_frame(frame.into(), stream, task);
|
||||
|
||||
|
||||
@@ -251,9 +251,8 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if a stream with the current state counts against the
|
||||
/// concurrency limit.
|
||||
pub fn is_counted(&self) -> bool {
|
||||
/// Returns true if a stream is open or half-closed.
|
||||
pub fn is_at_least_half_open(&self) -> bool {
|
||||
match self.inner {
|
||||
Open {
|
||||
..
|
||||
|
||||
@@ -13,8 +13,9 @@ pub(super) struct Store<B, P>
|
||||
where
|
||||
P: Peer,
|
||||
{
|
||||
slab: slab::Slab<Stream<B, P>>,
|
||||
ids: OrderMap<StreamId, usize>,
|
||||
slab: slab::Slab<(StoreId, Stream<B, P>)>,
|
||||
ids: OrderMap<StreamId, (usize, StoreId)>,
|
||||
counter: StoreId,
|
||||
}
|
||||
|
||||
/// "Pointer" to an entry in the store
|
||||
@@ -28,7 +29,12 @@ where
|
||||
|
||||
/// References an entry in the store.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(super) struct Key(usize);
|
||||
pub(crate) struct Key {
|
||||
index: usize,
|
||||
store_id: StoreId,
|
||||
}
|
||||
|
||||
type StoreId = usize;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct Queue<B, N, P>
|
||||
@@ -64,15 +70,16 @@ pub(super) enum Entry<'a, B: 'a, P: Peer + 'a> {
|
||||
}
|
||||
|
||||
pub(super) struct OccupiedEntry<'a> {
|
||||
ids: ordermap::OccupiedEntry<'a, StreamId, usize>,
|
||||
ids: ordermap::OccupiedEntry<'a, StreamId, (usize, StoreId)>,
|
||||
}
|
||||
|
||||
pub(super) struct VacantEntry<'a, B: 'a, P>
|
||||
where
|
||||
P: Peer + 'a,
|
||||
{
|
||||
ids: ordermap::VacantEntry<'a, StreamId, usize>,
|
||||
slab: &'a mut slab::Slab<Stream<B, P>>,
|
||||
ids: ordermap::VacantEntry<'a, StreamId, (usize, StoreId)>,
|
||||
slab: &'a mut slab::Slab<(StoreId, Stream<B, P>)>,
|
||||
counter: &'a mut usize,
|
||||
}
|
||||
|
||||
pub(super) trait Resolve<B, P>
|
||||
@@ -92,6 +99,7 @@ where
|
||||
Store {
|
||||
slab: slab::Slab::new(),
|
||||
ids: OrderMap::new(),
|
||||
counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,17 +114,25 @@ where
|
||||
};
|
||||
|
||||
Some(Ptr {
|
||||
key: Key(key),
|
||||
key: Key {
|
||||
index: key.0,
|
||||
store_id: key.1,
|
||||
},
|
||||
store: self,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, id: StreamId, val: Stream<B, P>) -> Ptr<B, P> {
|
||||
let key = self.slab.insert(val);
|
||||
assert!(self.ids.insert(id, key).is_none());
|
||||
let store_id = self.counter;
|
||||
self.counter = self.counter.wrapping_add(1);
|
||||
let key = self.slab.insert((store_id, val));
|
||||
assert!(self.ids.insert(id, (key, store_id)).is_none());
|
||||
|
||||
Ptr {
|
||||
key: Key(key),
|
||||
key: Key {
|
||||
index: key,
|
||||
store_id,
|
||||
},
|
||||
store: self,
|
||||
}
|
||||
}
|
||||
@@ -131,6 +147,7 @@ where
|
||||
Vacant(e) => Entry::Vacant(VacantEntry {
|
||||
ids: e,
|
||||
slab: &mut self.slab,
|
||||
counter: &mut self.counter,
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -147,7 +164,10 @@ where
|
||||
let key = *self.ids.get_index(i).unwrap().1;
|
||||
|
||||
f(Ptr {
|
||||
key: Key(key),
|
||||
key: Key {
|
||||
index: key.0,
|
||||
store_id: key.1,
|
||||
},
|
||||
store: self,
|
||||
})?;
|
||||
|
||||
@@ -185,7 +205,9 @@ where
|
||||
type Output = Stream<B, P>;
|
||||
|
||||
fn index(&self, key: Key) -> &Self::Output {
|
||||
self.slab.index(key.0)
|
||||
let slot = self.slab.index(key.index);
|
||||
assert_eq!(slot.0, key.store_id);
|
||||
&slot.1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +216,9 @@ where
|
||||
P: Peer,
|
||||
{
|
||||
fn index_mut(&mut self, key: Key) -> &mut Self::Output {
|
||||
self.slab.index_mut(key.0)
|
||||
let slot = self.slab.index_mut(key.index);
|
||||
assert_eq!(slot.0, key.store_id);
|
||||
&mut slot.1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,7 +343,7 @@ where
|
||||
debug_assert!(!self.store.ids.contains_key(&self.id));
|
||||
|
||||
// Remove the stream state
|
||||
self.store.slab.remove(self.key.0).id
|
||||
self.store.slab.remove(self.key.index).1.id
|
||||
}
|
||||
|
||||
/// Remove the StreamId -> stream state association.
|
||||
@@ -351,7 +375,7 @@ where
|
||||
type Target = Stream<B, P>;
|
||||
|
||||
fn deref(&self) -> &Stream<B, P> {
|
||||
&self.store.slab[self.key.0]
|
||||
&self.store.slab[self.key.index].1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +384,7 @@ where
|
||||
P: Peer,
|
||||
{
|
||||
fn deref_mut(&mut self) -> &mut Stream<B, P> {
|
||||
&mut self.store.slab[self.key.0]
|
||||
&mut self.store.slab[self.key.index].1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,7 +392,11 @@ where
|
||||
|
||||
impl<'a> OccupiedEntry<'a> {
|
||||
pub fn key(&self) -> Key {
|
||||
Key(*self.ids.get())
|
||||
let tup = self.ids.get();
|
||||
Key {
|
||||
index: tup.0,
|
||||
store_id: tup.1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,11 +408,16 @@ where
|
||||
{
|
||||
pub fn insert(self, value: Stream<B, P>) -> Key {
|
||||
// Insert the value in the slab
|
||||
let key = self.slab.insert(value);
|
||||
let store_id = *self.counter;
|
||||
*self.counter = store_id.wrapping_add(1);
|
||||
let index = self.slab.insert((store_id, value));
|
||||
|
||||
// Insert the handle in the ID map
|
||||
self.ids.insert(key);
|
||||
self.ids.insert((index, store_id));
|
||||
|
||||
Key(key)
|
||||
Key {
|
||||
index,
|
||||
store_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,15 @@ where
|
||||
/// Set to true when the send capacity has been incremented
|
||||
pub send_capacity_inc: bool,
|
||||
|
||||
/// Next node in the open linked list
|
||||
pub next_open: Option<store::Key>,
|
||||
|
||||
/// Set to true when the stream is pending to be opened
|
||||
pub is_pending_open: bool,
|
||||
|
||||
/// Task tracking when stream can be "opened", or initially sent to socket.
|
||||
pub open_task: Option<task::Task>,
|
||||
|
||||
// ===== Fields related to receiving =====
|
||||
/// Next node in the accept linked list
|
||||
pub next_pending_accept: Option<store::Key>,
|
||||
@@ -111,6 +120,9 @@ pub(super) struct NextSendCapacity;
|
||||
#[derive(Debug)]
|
||||
pub(super) struct NextWindowUpdate;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct NextOpen;
|
||||
|
||||
impl<B, P> Stream<B, P>
|
||||
where
|
||||
P: Peer,
|
||||
@@ -150,6 +162,9 @@ where
|
||||
is_pending_send_capacity: false,
|
||||
next_pending_send_capacity: None,
|
||||
send_capacity_inc: false,
|
||||
is_pending_open: false,
|
||||
next_open: None,
|
||||
open_task: None,
|
||||
|
||||
// ===== Fields related to receiving =====
|
||||
next_pending_accept: None,
|
||||
@@ -177,6 +192,12 @@ where
|
||||
self.ref_count -= 1;
|
||||
}
|
||||
|
||||
/// Returns true if a stream with the current state counts against the
|
||||
/// concurrency limit.
|
||||
pub fn is_counted(&self) -> bool {
|
||||
!self.is_pending_open && self.state.is_at_least_half_open()
|
||||
}
|
||||
|
||||
/// Returns true if the stream is closed
|
||||
pub fn is_closed(&self) -> bool {
|
||||
// The state has fully transitioned to closed.
|
||||
@@ -337,6 +358,28 @@ impl store::Next for NextWindowUpdate {
|
||||
}
|
||||
}
|
||||
|
||||
impl store::Next for NextOpen {
|
||||
fn next<B, P: Peer>(stream: &Stream<B, P>) -> Option<store::Key> {
|
||||
stream.next_open
|
||||
}
|
||||
|
||||
fn set_next<B, P: Peer>(stream: &mut Stream<B, P>, key: Option<store::Key>) {
|
||||
stream.next_open = key;
|
||||
}
|
||||
|
||||
fn take_next<B, P: Peer>(stream: &mut Stream<B, P>) -> Option<store::Key> {
|
||||
stream.next_open.take()
|
||||
}
|
||||
|
||||
fn is_queued<B, P: Peer>(stream: &Stream<B, P>) -> bool {
|
||||
stream.is_pending_open
|
||||
}
|
||||
|
||||
fn set_queued<B, P: Peer>(stream: &mut Stream<B, P>, val: bool) {
|
||||
stream.is_pending_open = val;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl ContentLength =====
|
||||
|
||||
impl ContentLength {
|
||||
|
||||
@@ -323,6 +323,7 @@ where
|
||||
&mut self,
|
||||
request: Request<()>,
|
||||
end_of_stream: bool,
|
||||
pending: Option<&store::Key>,
|
||||
) -> Result<StreamRef<B, P>, SendError> {
|
||||
use super::stream::ContentLength;
|
||||
use http::Method;
|
||||
@@ -336,8 +337,21 @@ where
|
||||
let mut me = self.inner.lock().unwrap();
|
||||
let me = &mut *me;
|
||||
|
||||
// Initialize a new stream. This fails if the connection is at capacity.
|
||||
let stream_id = me.actions.send.open(&mut me.counts)?;
|
||||
me.actions.send.ensure_next_stream_id()?;
|
||||
|
||||
// The `pending` argument is provided by the `Client`, and holds
|
||||
// a store `Key` of a `Stream` that may have been not been opened
|
||||
// yet.
|
||||
//
|
||||
// If that stream is still pending, the Client isn't allowed to
|
||||
// queue up another pending stream. They should use `poll_ready`.
|
||||
if let Some(key) = pending {
|
||||
if me.store.resolve(*key).is_pending_open {
|
||||
return Err(UserError::Rejected.into());
|
||||
}
|
||||
}
|
||||
|
||||
let stream_id = me.actions.send.open()?;
|
||||
|
||||
let mut stream = Stream::new(
|
||||
stream_id,
|
||||
@@ -354,9 +368,12 @@ where
|
||||
|
||||
let mut stream = me.store.insert(stream.id, stream);
|
||||
|
||||
me.actions
|
||||
.send
|
||||
.send_headers(headers, &mut stream, &mut me.actions.task)?;
|
||||
me.actions.send.send_headers(
|
||||
headers,
|
||||
&mut stream,
|
||||
&mut me.counts,
|
||||
&mut me.actions.task,
|
||||
)?;
|
||||
|
||||
// Given that the stream has been initialized, it should not be in the
|
||||
// closed state.
|
||||
@@ -403,13 +420,21 @@ impl<B> Streams<B, client::Peer>
|
||||
where
|
||||
B: Buf,
|
||||
{
|
||||
pub fn poll_send_request_ready(&mut self) -> Poll<(), ::Error> {
|
||||
pub fn poll_pending_open(&mut self, key: Option<&store::Key>) -> Poll<(), ::Error> {
|
||||
let mut me = self.inner.lock().unwrap();
|
||||
let me = &mut *me;
|
||||
|
||||
me.actions.send.ensure_next_stream_id()?;
|
||||
|
||||
Ok(me.counts.poll_open_ready())
|
||||
if let Some(key) = key {
|
||||
let mut stream = me.store.resolve(*key);
|
||||
trace!("poll_pending_open; stream = {:?}", stream.is_pending_open);
|
||||
if stream.is_pending_open {
|
||||
stream.send_task = Some(task::current());
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
}
|
||||
Ok(().into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,6 +455,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// no derive because we don't need B and P to be Clone.
|
||||
impl<B, P> Clone for Streams<B, P>
|
||||
where
|
||||
B: Buf,
|
||||
P: Peer,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Streams {
|
||||
inner: self.inner.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl StreamRef =====
|
||||
|
||||
impl<B, P> StreamRef<B, P>
|
||||
@@ -493,10 +531,12 @@ where
|
||||
let stream = me.store.resolve(self.key);
|
||||
let actions = &mut me.actions;
|
||||
|
||||
me.counts.transition(stream, |_, stream| {
|
||||
me.counts.transition(stream, |counts, stream| {
|
||||
let frame = server::Peer::convert_send_message(stream.id, response, end_of_stream);
|
||||
|
||||
actions.send.send_headers(frame, stream, &mut actions.task)
|
||||
actions
|
||||
.send
|
||||
.send_headers(frame, stream, counts, &mut actions.task)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -569,6 +609,10 @@ where
|
||||
|
||||
me.actions.send.poll_capacity(&mut stream)
|
||||
}
|
||||
|
||||
pub(crate) fn key(&self) -> store::Key {
|
||||
self.key
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> StreamRef<B, server::Peer>
|
||||
@@ -603,6 +647,12 @@ where
|
||||
|
||||
me.actions.recv.poll_response(&mut stream)
|
||||
}
|
||||
|
||||
|
||||
pub fn is_pending_open(&self) -> bool {
|
||||
let mut me = self.inner.lock().unwrap();
|
||||
me.store.resolve(self.key).is_pending_open
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, P> Clone for StreamRef<B, P>
|
||||
@@ -625,7 +675,15 @@ where
|
||||
P: Peer,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
let mut me = self.inner.lock().unwrap();
|
||||
let mut me = match self.inner.lock() {
|
||||
Ok(inner) => inner,
|
||||
Err(_) => if ::std::thread::panicking() {
|
||||
trace!("StreamRef::drop; mutex poisoned");
|
||||
return;
|
||||
} else {
|
||||
panic!("StreamRef::drop; mutex poisoned");
|
||||
},
|
||||
};
|
||||
|
||||
let me = &mut *me;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user