Implement Clone for File.

Implement `Clone` for `File` so that `File`s can be passed into closures
for use in `spawn_blocking`. `File`'s contents are already wrapped in
`Arc`s, so the implementation of `clone` is straightforward.

This also aligns with `TcpStream` which already implements `Clone` using
its internal `Arc`.
pull/937/head
Dan Gohman 4 years ago
parent b210ee3628
commit 09e99843e4

@ -58,6 +58,7 @@ use crate::utils::Context as _;
/// #
/// # Ok(()) }) }
/// ```
#[derive(Clone)]
pub struct File {
/// A reference to the inner file.
file: Arc<std::fs::File>,
@ -470,6 +471,13 @@ struct Lock<T>(Arc<LockState<T>>);
unsafe impl<T: Send> Send for Lock<T> {}
unsafe impl<T: Send> Sync for Lock<T> {}
impl<T> Clone for Lock<T> {
#[inline]
fn clone(&self) -> Self {
Self(Arc::clone(&self.0))
}
}
/// The state of a lock.
struct LockState<T> {
/// Set to `true` when locked.
@ -878,4 +886,21 @@ mod tests {
File::open(file!()).await.unwrap();
});
}
#[test]
fn async_file_clone() {
crate::task::block_on(async move {
let file = File::open(file!()).await.unwrap();
let mut clone = file.clone();
let len = crate::task::spawn_blocking(move || {
let mut buf = Vec::new();
crate::task::block_on(async move {
clone.read_to_end(&mut buf).await.unwrap();
drop(clone);
buf.len()
})
}).await;
assert_eq!(len as u64, file.metadata().await.unwrap().len());
});
}
}

Loading…
Cancel
Save