Skip to content

Commit 3a06adb

Browse files
committed
[async-client] Try to bring 'Send' back but…
…it was clear early on that we cannot send readers tied to a lifetime as all safe unblockers will require 'static. It's not a real issue right now but certainly interesting to solve cheaply, potentially diverging the protocol implementaitons for blocking & async. Alternatively there is no other options but to get Arc<Mutex<…>>
1 parent dc742df commit 3a06adb

File tree

14 files changed

+63
-61
lines changed

14 files changed

+63
-61
lines changed

git-packetline/src/read/sidebands/async_io.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ pub struct ReadLineFuture<'a, 'b, T: AsyncRead, F> {
160160

161161
impl<'a, 'b, T, F> Future for ReadLineFuture<'a, 'b, T, F>
162162
where
163-
T: AsyncRead + Unpin,
163+
T: AsyncRead + Unpin + Send,
164164
F: FnMut(bool, &[u8]) + Unpin,
165165
{
166166
type Output = std::io::Result<usize>;

git-packetline/src/write/async_io.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ enum State {
2121
WriteData(usize),
2222
}
2323

24-
impl<T: AsyncWrite + Unpin> Writer<T> {
24+
impl<T: AsyncWrite + Unpin + Send> Writer<T> {
2525
/// Create a new instance from the given `write`
2626
pub fn new(write: T) -> Self {
2727
Writer {
@@ -54,7 +54,7 @@ impl<T> Writer<T> {
5454
}
5555
}
5656

57-
impl<T: AsyncWrite + Unpin> AsyncWrite for Writer<T> {
57+
impl<T: AsyncWrite + Unpin + Send> AsyncWrite for Writer<T> {
5858
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
5959
let mut this = self.project();
6060
loop {

git-protocol/src/fetch/arguments/async_io.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ use futures_lite::io::AsyncWriteExt;
33
use git_transport::{client, client::TransportV2Ext};
44

55
impl Arguments {
6-
pub(crate) async fn send<'a, T: client::Transport + 'a>(
6+
pub(crate) async fn send<'a, T: client::Transport + 'a + Send>(
77
&mut self,
88
transport: &'a mut T,
99
add_done_argument: bool,
10-
) -> Result<Box<dyn client::ExtendedBufRead + Unpin + 'a>, client::Error> {
10+
) -> Result<Box<dyn client::ExtendedBufRead + Unpin + 'a + Send>, client::Error> {
1111
if self.haves.is_empty() {
1212
assert!(add_done_argument, "If there are no haves, is_done must be true.");
1313
}

git-protocol/src/fetch/delegate.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ mod async_io {
127127
/// Everything is tucked away behind type-safety so 'nothing can go wrong'©. Runtime assertions assure invalid
128128
/// features or arguments don't make it to the server in the first place.
129129
/// Please note that this trait mostly corresponds to what V2 would look like, even though V1 is supported as well.
130-
#[async_trait(?Send)]
130+
#[async_trait]
131131
pub trait Delegate: DelegateWithoutIO {
132132
/// Receive a pack provided from the given `input`.
133133
///
@@ -137,7 +137,7 @@ mod async_io {
137137
/// to check additional acks.
138138
async fn receive_pack(
139139
&mut self,
140-
input: impl AsyncBufRead + Unpin + 'async_trait,
140+
input: impl AsyncBufRead + Unpin + 'async_trait + Send,
141141
progress: impl Progress,
142142
refs: &[Ref],
143143
previous: &Response,

git-protocol/src/fetch/function.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::io;
2020
/// _Note_ that depending on the `delegate`, the actual action performed can be `ls-refs`, `clone` or `fetch`.
2121
#[maybe_async]
2222
pub async fn fetch<F>(
23-
mut transport: impl client::Transport,
23+
mut transport: impl client::Transport + Send,
2424
delegate: &mut impl Delegate,
2525
mut authenticate: F,
2626
mut progress: impl Progress,
@@ -172,7 +172,7 @@ where
172172

173173
fn setup_remote_progress(
174174
progress: &mut impl Progress,
175-
reader: &mut Box<dyn git_transport::client::ExtendedBufRead + Unpin + '_>,
175+
reader: &mut Box<dyn git_transport::client::ExtendedBufRead + Unpin + '_ + Send>,
176176
) {
177177
reader.set_progress_handler(Some(Box::new({
178178
let mut remote_progress = progress.add_child("remote");

git-protocol/src/fetch/tests/arguments.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ mod impls {
8888
}
8989
}
9090

91-
#[async_trait(?Send)]
91+
#[async_trait]
9292
impl<T: client::Transport + Send> client::Transport for Transport<T> {
9393
async fn handshake(&mut self, service: Service) -> Result<SetServiceResponse<'_>, Error> {
9494
self.inner.handshake(service).await

git-protocol/tests/fetch/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ mod async_io {
9494
};
9595
use std::io;
9696

97-
#[async_trait(?Send)]
97+
#[async_trait]
9898
impl fetch::Delegate for CloneDelegate {
9999
async fn receive_pack(
100100
&mut self,
101-
mut input: impl AsyncBufRead + Unpin + 'async_trait,
101+
mut input: impl AsyncBufRead + Unpin + 'async_trait + Send,
102102
_progress: impl Progress,
103103
_refs: &[Ref],
104104
_previous: &Response,
@@ -108,11 +108,11 @@ mod async_io {
108108
}
109109
}
110110

111-
#[async_trait(?Send)]
111+
#[async_trait]
112112
impl fetch::Delegate for LsRemoteDelegate {
113113
async fn receive_pack(
114114
&mut self,
115-
_input: impl AsyncBufRead + Unpin + 'async_trait,
115+
_input: impl AsyncBufRead + Unpin + 'async_trait + Send,
116116
_progress: impl Progress,
117117
_refs: &[Ref],
118118
_previous: &Response,

git-transport/src/client/async_io/bufread_ext.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ use std::{
1212
/// A function `f(is_error, text)` receiving progress or error information.
1313
/// As it is not a future itself, it must not block. If IO is performed within the function, be sure to spawn
1414
/// it onto an executor.
15-
pub type HandleProgress = Box<dyn FnMut(bool, &[u8])>;
15+
pub type HandleProgress = Box<dyn FnMut(bool, &[u8]) + Send>;
1616

1717
/// This trait exists to get a version of a `git_packetline::Provider` without type parameters.
1818
/// For the sake of usability, it also implements [`std::io::BufRead`] making it trivial to (eventually)
1919
/// read pack files while keeping the possibility to read individual lines with low overhead.
20-
#[async_trait(?Send)]
20+
#[async_trait]
2121
pub trait ExtendedBufRead: AsyncBufRead {
2222
/// Set the handler to which progress will be delivered.
2323
///
@@ -33,8 +33,8 @@ pub trait ExtendedBufRead: AsyncBufRead {
3333
fn stopped_at(&self) -> Option<MessageKind>;
3434
}
3535

36-
#[async_trait(?Send)]
37-
impl<'a, T: ExtendedBufRead + ?Sized + 'a + Unpin> ExtendedBufRead for Box<T> {
36+
#[async_trait]
37+
impl<'a, T: ExtendedBufRead + ?Sized + 'a + Unpin + Send> ExtendedBufRead for Box<T> {
3838
fn set_progress_handler(&mut self, handle_progress: Option<HandleProgress>) {
3939
self.deref_mut().set_progress_handler(handle_progress)
4040
}
@@ -52,8 +52,8 @@ impl<'a, T: ExtendedBufRead + ?Sized + 'a + Unpin> ExtendedBufRead for Box<T> {
5252
}
5353
}
5454

55-
#[async_trait(?Send)]
56-
impl<'a, T: AsyncRead + Unpin> ExtendedBufRead for git_packetline::read::WithSidebands<'a, T, HandleProgress> {
55+
#[async_trait]
56+
impl<'a, T: AsyncRead + Unpin + Send> ExtendedBufRead for git_packetline::read::WithSidebands<'a, T, HandleProgress> {
5757
fn set_progress_handler(&mut self, handle_progress: Option<HandleProgress>) {
5858
self.set_progress_handler(handle_progress)
5959
}

git-transport/src/client/async_io/request.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ pin_project! {
1414
pub struct RequestWriter<'a> {
1515
on_into_read: MessageKind,
1616
#[pin]
17-
pub(crate) writer: git_packetline::Writer<Box<dyn AsyncWrite + Unpin + 'a>>,
18-
pub(crate) reader: Box<dyn ExtendedBufRead + Unpin + 'a>,
17+
pub(crate) writer: git_packetline::Writer<Box<dyn AsyncWrite + Unpin + 'a + Send>>,
18+
pub(crate) reader: Box<dyn ExtendedBufRead + Unpin + 'a + Send>,
1919
}
2020
}
2121
impl<'a> futures_io::AsyncWrite for RequestWriter<'a> {
@@ -37,13 +37,13 @@ impl<'a> RequestWriter<'a> {
3737
/// Create a new instance from a `writer` (commonly a socket), a `reader` into which to transform once the
3838
/// writes are finished, along with configuration for the `write_mode` and information about which message to write
3939
/// when this instance is converted into a `reader` to read the request's response.
40-
pub fn new_from_bufread<W: AsyncWrite + Unpin + 'a>(
40+
pub fn new_from_bufread<W: AsyncWrite + Unpin + 'a + Send>(
4141
writer: W,
42-
reader: Box<dyn ExtendedBufRead + Unpin + 'a>,
42+
reader: Box<dyn ExtendedBufRead + Unpin + 'a + Send>,
4343
write_mode: WriteMode,
4444
on_into_read: MessageKind,
4545
) -> Self {
46-
let mut writer = git_packetline::Writer::new(Box::new(writer) as Box<dyn AsyncWrite + Unpin>);
46+
let mut writer = git_packetline::Writer::new(Box::new(writer) as Box<dyn AsyncWrite + Unpin + Send>);
4747
match write_mode {
4848
WriteMode::Binary => writer.enable_binary_mode(),
4949
WriteMode::OneLfTerminatedLinePerWriteCall => writer.enable_text_mode(),
@@ -82,7 +82,7 @@ impl<'a> RequestWriter<'a> {
8282
.map(|_| ())
8383
}
8484
/// Discard the ability to write and turn this instance into the reader for obtaining the other side's response.
85-
pub async fn into_read(mut self) -> std::io::Result<Box<dyn ExtendedBufRead + Unpin + 'a>> {
85+
pub async fn into_read(mut self) -> std::io::Result<Box<dyn ExtendedBufRead + Unpin + 'a + Send>> {
8686
self.write_message(self.on_into_read).await?;
8787
Ok(self.reader)
8888
}

git-transport/src/client/async_io/traits.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub struct SetServiceResponse<'a> {
2222
/// It does, however, know just enough to be able to provide a higher-level interface than would otherwise be possible.
2323
/// Thus the consumer of this trait will not have to deal with packet lines at all.
2424
/// **Note that** whenever a `Read` trait or `Write` trait is produced, it must be exhausted.
25-
#[async_trait(?Send)]
25+
#[async_trait]
2626
pub trait Transport: TransportWithoutIO {
2727
/// Initiate connection to the given service.
2828
/// Returns the service capabilities according according to the actual [Protocol] it supports,
@@ -37,8 +37,8 @@ pub trait Transport: TransportWithoutIO {
3737
}
3838

3939
// Would be nice if the box implementation could auto-forward to all implemented traits.
40-
#[async_trait(?Send)]
41-
impl<T: Transport + ?Sized> Transport for Box<T> {
40+
#[async_trait]
41+
impl<T: Transport + ?Sized + Send> Transport for Box<T> {
4242
async fn handshake(&mut self, service: Service) -> Result<SetServiceResponse<'_>, Error> {
4343
self.deref_mut().handshake(service).await
4444
}
@@ -49,27 +49,27 @@ impl<T: Transport + ?Sized> Transport for Box<T> {
4949
}
5050

5151
/// An extension trait to add more methods to everything implementing [`Transport`].
52-
#[async_trait(?Send)]
52+
#[async_trait]
5353
pub trait TransportV2Ext {
5454
/// Invoke a protocol V2 style `command` with given `capabilities` and optional command specific `arguments`.
5555
/// The `capabilities` were communicated during the handshake.
5656
/// _Note:_ panics if [handshake][Transport::handshake()] wasn't performed beforehand.
5757
async fn invoke<'a>(
5858
&mut self,
5959
command: &str,
60-
capabilities: impl Iterator<Item = (&'a str, Option<&'a str>)> + 'a,
61-
arguments: Option<impl Iterator<Item = bstr::BString> + 'a>,
62-
) -> Result<Box<dyn ExtendedBufRead + Unpin + '_>, Error>;
60+
capabilities: impl Iterator<Item = (&'a str, Option<&'a str>)> + 'a + Send,
61+
arguments: Option<impl Iterator<Item = bstr::BString> + 'a + Send>,
62+
) -> Result<Box<dyn ExtendedBufRead + Unpin + '_ + Send>, Error>;
6363
}
6464

65-
#[async_trait(?Send)]
66-
impl<T: Transport> TransportV2Ext for T {
65+
#[async_trait]
66+
impl<T: Transport + Send> TransportV2Ext for T {
6767
async fn invoke<'a>(
6868
&mut self,
6969
command: &str,
70-
capabilities: impl Iterator<Item = (&'a str, Option<&'a str>)> + 'a,
71-
arguments: Option<impl Iterator<Item = BString> + 'a>,
72-
) -> Result<Box<dyn ExtendedBufRead + Unpin + '_>, Error> {
70+
capabilities: impl Iterator<Item = (&'a str, Option<&'a str>)> + 'a + Send,
71+
arguments: Option<impl Iterator<Item = BString> + 'a + Send>,
72+
) -> Result<Box<dyn ExtendedBufRead + Unpin + '_ + Send>, Error> {
7373
let mut writer = self.request(WriteMode::OneLfTerminatedLinePerWriteCall, MessageKind::Flush)?;
7474
writer.write_all(format!("command={}", command).as_bytes()).await?;
7575
for (name, value) in capabilities {

0 commit comments

Comments
 (0)