From 2560860d5f695a4619d097341cc119d7de767b67 Mon Sep 17 00:00:00 2001 From: tottoto Date: Thu, 24 Sep 2026 00:00:00 +0000 Subject: [PATCH] refactor(client): replace SyncWrapper with sync_wrapper crate the `common::sync` module contains a type called `SyncWrapper`, which provides an interface that permits for safely treating a `T` that is not `Sync`, as `Sync`. this exists as a public crate, `sync_wrapper` that we can use instead. this crate is used by `reqwest`, `tower`, `axum`, `tonic`, and other popular crates. Co-authored-by: katelyn martin --- Cargo.toml | 3 +- src/client/legacy/client.rs | 3 +- src/common/mod.rs | 4 --- src/common/sync.rs | 67 ------------------------------------- 4 files changed, 4 insertions(+), 73 deletions(-) delete mode 100644 src/common/sync.rs diff --git a/Cargo.toml b/Cargo.toml index 363ad770..c06db37d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ tracing = { version = "0.1.36", default-features = false, features = ["std"], op tokio = { version = "1.13", optional = true, default-features = false } tower-layer = { version = "0.3", optional = true } tower-service = { version = "0.3", optional = true } +sync_wrapper = { version = "1", optional = true } [dev-dependencies] hyper = { version = "1.4.0", features = ["full"] } @@ -78,7 +79,7 @@ full = [ ] client = ["hyper/client", "dep:tracing", "dep:futures-channel", "dep:tower-service"] -client-legacy = ["client", "tokio/net", "dep:socket2", "tokio/sync", "dep:libc", "dep:futures-util", "dep:httparse"] +client-legacy = ["client", "tokio/net", "dep:socket2", "tokio/sync", "dep:libc", "dep:futures-util", "dep:httparse", "dep:sync_wrapper"] client-pool = ["client", "dep:futures-util", "dep:tower-layer", "tokio/sync"] client-proxy = ["client", "dep:base64", "dep:ipnet", "dep:percent-encoding"] client-proxy-system = ["dep:system-configuration", "dep:windows-registry"] diff --git a/src/client/legacy/client.rs b/src/client/legacy/client.rs index d4f77be4..d6e48955 100644 --- a/src/client/legacy/client.rs +++ b/src/client/legacy/client.rs @@ -17,6 +17,7 @@ use hyper::client::conn::TrySendError as ConnTrySendError; use hyper::header::{HOST, HeaderValue}; use hyper::rt::Timer; use hyper::{Method, Request, Response, Uri, Version, body::Body}; +use sync_wrapper::SyncWrapper; use tracing::{debug, trace, warn}; #[cfg(feature = "tokio")] @@ -25,7 +26,7 @@ use super::connect::capture::CaptureConnectionExtension; use super::connect::{Alpn, Connect, Connected, Connection}; use super::pool::{self, Ver}; -use crate::common::{Exec, Lazy, SyncWrapper, lazy as hyper_lazy, timer}; +use crate::common::{Exec, Lazy, lazy as hyper_lazy, timer}; type BoxSendFuture = Pin + Send>>; diff --git a/src/common/mod.rs b/src/common/mod.rs index bcd7d475..7131c0b9 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -6,8 +6,6 @@ mod lazy; #[cfg(feature = "server")] // #[cfg(feature = "server-auto")] pub(crate) mod rewind; -#[cfg(feature = "client-legacy")] -mod sync; pub(crate) mod timer; #[cfg(feature = "client-legacy")] @@ -15,5 +13,3 @@ pub(crate) use exec::Exec; #[cfg(feature = "client-legacy")] pub(crate) use lazy::{Started as Lazy, lazy}; -#[cfg(feature = "client-legacy")] -pub(crate) use sync::SyncWrapper; diff --git a/src/common/sync.rs b/src/common/sync.rs deleted file mode 100644 index 2755fd05..00000000 --- a/src/common/sync.rs +++ /dev/null @@ -1,67 +0,0 @@ -pub(crate) struct SyncWrapper(T); - -impl SyncWrapper { - /// Creates a new SyncWrapper containing the given value. - /// - /// # Examples - /// - /// ```ignore - /// use hyper::common::sync_wrapper::SyncWrapper; - /// - /// let wrapped = SyncWrapper::new(42); - /// ``` - pub(crate) fn new(value: T) -> Self { - Self(value) - } - - /// Acquires a reference to the protected value. - /// - /// This is safe because it requires an exclusive reference to the wrapper. Therefore this method - /// neither panics nor does it return an error. This is in contrast to [`Mutex::get_mut`] which - /// returns an error if another thread panicked while holding the lock. It is not recommended - /// to send an exclusive reference to a potentially damaged value to another thread for further - /// processing. - /// - /// [`Mutex::get_mut`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.get_mut - /// - /// # Examples - /// - /// ```ignore - /// use hyper::common::sync_wrapper::SyncWrapper; - /// - /// let mut wrapped = SyncWrapper::new(42); - /// let value = wrapped.get_mut(); - /// *value = 0; - /// assert_eq!(*wrapped.get_mut(), 0); - /// ``` - pub(crate) fn get_mut(&mut self) -> &mut T { - &mut self.0 - } - - /// Consumes this wrapper, returning the underlying data. - /// - /// This is safe because it requires ownership of the wrapper, aherefore this method will neither - /// panic nor does it return an error. This is in contrast to [`Mutex::into_inner`] which - /// returns an error if another thread panicked while holding the lock. It is not recommended - /// to send an exclusive reference to a potentially damaged value to another thread for further - /// processing. - /// - /// [`Mutex::into_inner`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.into_inner - /// - /// # Examples - /// - /// ```ignore - /// use hyper::common::sync_wrapper::SyncWrapper; - /// - /// let mut wrapped = SyncWrapper::new(42); - /// assert_eq!(wrapped.into_inner(), 42); - /// ``` - #[allow(dead_code)] - pub(crate) fn into_inner(self) -> T { - self.0 - } -} - -// this is safe because the only operations permitted on this data structure require exclusive -// access or ownership -unsafe impl Sync for SyncWrapper {}