diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs index be066bdafa14a..630158359d3ee 100644 --- a/src/librustdoc/docfs.rs +++ b/src/librustdoc/docfs.rs @@ -9,11 +9,21 @@ //! needs to read-after-write from a file, then it would be added to this //! abstraction. +#[cfg(windows)] +use std::cell::RefCell; use std::fs; use std::io; use std::path::{Path, PathBuf}; use std::string::ToString; +#[cfg(windows)] +use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::Sender; +#[cfg(windows)] +use std::sync::Arc; +#[cfg(windows)] +use std::thread::sleep; +#[cfg(windows)] +use std::time::Duration; pub(crate) trait PathError { fn new>(e: S, path: P) -> Self @@ -24,11 +34,22 @@ pub(crate) trait PathError { pub(crate) struct DocFS { sync_only: bool, errors: Option>, + #[cfg(windows)] + written_files: Arc, + #[cfg(windows)] + total_files: RefCell, } impl DocFS { pub(crate) fn new(errors: Sender) -> DocFS { - DocFS { sync_only: false, errors: Some(errors) } + DocFS { + sync_only: false, + errors: Some(errors), + #[cfg(windows)] + written_files: Arc::new(AtomicUsize::new(0)), + #[cfg(windows)] + total_files: RefCell::new(0), + } } pub(crate) fn set_sync_only(&mut self, sync_only: bool) { @@ -56,23 +77,34 @@ impl DocFS { { #[cfg(windows)] if !self.sync_only { + *self.total_files.borrow_mut() += 1; // A possible future enhancement after more detailed profiling would // be to create the file sync so errors are reported eagerly. let sender = self.errors.clone().expect("can't write after closing"); + let written_files = Arc::clone(&self.written_files); rayon::spawn(move || { fs::write(&path, contents).unwrap_or_else(|e| { sender.send(format!("\"{}\": {}", path.display(), e)).unwrap_or_else(|_| { + written_files.fetch_add(1, Ordering::Relaxed); panic!("failed to send error on \"{}\"", path.display()) }) }); + written_files.fetch_add(1, Ordering::Relaxed); }); - } else { - fs::write(&path, contents).map_err(|e| E::new(e, path))?; + return; } - #[cfg(not(windows))] fs::write(&path, contents).map_err(|e| E::new(e, path))?; - Ok(()) } } + +#[cfg(windows)] +impl Drop for DocFS { + fn drop(&mut self) { + let total_files = *self.total_files.borrow(); + while self.written_files.load(Ordering::Relaxed) < total_files { + sleep(Duration::from_millis(1)); + } + } +}