From 09e99843e448de0860e1fe6d40d0d32958835073 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 15 Jan 2021 09:05:21 -0800 Subject: [PATCH] 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`. --- src/fs/file.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/fs/file.rs b/src/fs/file.rs index 56d292b9..e8cad7ad 100644 --- a/src/fs/file.rs +++ b/src/fs/file.rs @@ -58,6 +58,7 @@ use crate::utils::Context as _; /// # /// # Ok(()) }) } /// ``` +#[derive(Clone)] pub struct File { /// A reference to the inner file. file: Arc, @@ -470,6 +471,13 @@ struct Lock(Arc>); unsafe impl Send for Lock {} unsafe impl Sync for Lock {} +impl Clone for Lock { + #[inline] + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } +} + /// The state of a lock. struct LockState { /// 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()); + }); + } }