fix(client): make ResponseFuture implement Sync

This commit is contained in:
Alice Ryhl
2021-09-19 18:08:30 +02:00
committed by Sean McArthur
parent d0c6aaa59d
commit bd6c35b98f
2 changed files with 24 additions and 10 deletions

View File

@@ -18,7 +18,7 @@ use super::pool::{
#[cfg(feature = "tcp")] #[cfg(feature = "tcp")]
use super::HttpConnector; use super::HttpConnector;
use crate::body::{Body, HttpBody}; use crate::body::{Body, HttpBody};
use crate::common::{exec::BoxSendFuture, lazy as hyper_lazy, task, Future, Lazy, Pin, Poll}; use crate::common::{exec::BoxSendFuture, sync_wrapper::SyncWrapper, lazy as hyper_lazy, task, Future, Lazy, Pin, Poll};
use crate::rt::Executor; use crate::rt::Executor;
/// A Client to make outgoing HTTP requests. /// A Client to make outgoing HTTP requests.
@@ -45,7 +45,7 @@ struct Config {
/// This is returned by `Client::request` (and `Client::get`). /// This is returned by `Client::request` (and `Client::get`).
#[must_use = "futures do nothing unless polled"] #[must_use = "futures do nothing unless polled"]
pub struct ResponseFuture { pub struct ResponseFuture {
inner: Pin<Box<dyn Future<Output = crate::Result<Response<Body>>> + Send>>, inner: SyncWrapper<Pin<Box<dyn Future<Output = crate::Result<Response<Body>>> + Send>>>,
} }
// ===== impl Client ===== // ===== impl Client =====
@@ -168,9 +168,9 @@ where
Version::HTTP_10 => { Version::HTTP_10 => {
if is_http_connect { if is_http_connect {
warn!("CONNECT is not allowed for HTTP/1.0"); warn!("CONNECT is not allowed for HTTP/1.0");
return ResponseFuture::new(Box::pin(future::err( return ResponseFuture::new(future::err(
crate::Error::new_user_unsupported_request_method(), crate::Error::new_user_unsupported_request_method(),
))); ));
} }
} }
Version::HTTP_2 => (), Version::HTTP_2 => (),
@@ -181,11 +181,11 @@ where
let pool_key = match extract_domain(req.uri_mut(), is_http_connect) { let pool_key = match extract_domain(req.uri_mut(), is_http_connect) {
Ok(s) => s, Ok(s) => s,
Err(err) => { Err(err) => {
return ResponseFuture::new(Box::pin(future::err(err))); return ResponseFuture::new(future::err(err));
} }
}; };
ResponseFuture::new(Box::pin(self.clone().retryably_send_request(req, pool_key))) ResponseFuture::new(self.clone().retryably_send_request(req, pool_key))
} }
async fn retryably_send_request( async fn retryably_send_request(
@@ -580,8 +580,13 @@ impl<C, B> fmt::Debug for Client<C, B> {
// ===== impl ResponseFuture ===== // ===== impl ResponseFuture =====
impl ResponseFuture { impl ResponseFuture {
fn new(fut: Pin<Box<dyn Future<Output = crate::Result<Response<Body>>> + Send>>) -> Self { fn new<F>(value: F) -> Self
Self { inner: fut } where
F: Future<Output = crate::Result<Response<Body>>> + Send + 'static,
{
Self {
inner: SyncWrapper::new(Box::pin(value))
}
} }
fn error_version(ver: Version) -> Self { fn error_version(ver: Version) -> Self {
@@ -602,7 +607,7 @@ impl Future for ResponseFuture {
type Output = crate::Result<Response<Body>>; type Output = crate::Result<Response<Body>>;
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut self.inner).poll(cx) self.inner.get_mut().as_mut().poll(cx)
} }
} }
@@ -1276,6 +1281,12 @@ impl fmt::Debug for Builder {
mod unit_tests { mod unit_tests {
use super::*; use super::*;
#[test]
fn response_future_is_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<ResponseFuture>();
}
#[test] #[test]
fn set_relative_uri_with_implicit_path() { fn set_relative_uri_with_implicit_path() {
let mut uri = "http://hyper.rs".parse().unwrap(); let mut uri = "http://hyper.rs".parse().unwrap();

View File

@@ -18,7 +18,10 @@ pub(crate) mod io;
#[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))] #[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]
mod lazy; mod lazy;
mod never; mod never;
#[cfg(feature = "stream")] #[cfg(any(
feature = "stream",
all(feature = "client", any(feature = "http1", feature = "http2"))
))]
pub(crate) mod sync_wrapper; pub(crate) mod sync_wrapper;
pub(crate) mod task; pub(crate) mod task;
pub(crate) mod watch; pub(crate) mod watch;