9
9
//! needs to read-after-write from a file, then it would be added to this
10
10
//! abstraction.
11
11
12
+ use std::cmp::max;
12
13
use std::fs;
13
14
use std::io;
14
15
use std::path::{Path, PathBuf};
15
16
use std::string::ToString;
16
17
use std::sync::mpsc::Sender;
18
+ use std::thread::available_parallelism;
19
+ use threadpool::ThreadPool;
17
20
18
21
pub(crate) trait PathError {
19
22
fn new<S, P: AsRef<Path>>(e: S, path: P) -> Self
@@ -24,11 +27,21 @@ pub(crate) trait PathError {
24
27
pub(crate) struct DocFS {
25
28
sync_only: bool,
26
29
errors: Option<Sender<String>>,
30
+ pool: ThreadPool,
27
31
}
28
32
29
33
impl DocFS {
30
34
pub(crate) fn new(errors: Sender<String>) -> DocFS {
31
- DocFS { sync_only: false, errors: Some(errors) }
35
+ const MINIMUM_NB_THREADS: usize = 2;
36
+ DocFS {
37
+ sync_only: false,
38
+ errors: Some(errors),
39
+ pool: ThreadPool::new(
40
+ available_parallelism()
41
+ .map(|nb| max(nb.get(), MINIMUM_NB_THREADS))
42
+ .unwrap_or(MINIMUM_NB_THREADS),
43
+ ),
44
+ }
32
45
}
33
46
34
47
pub(crate) fn set_sync_only(&mut self, sync_only: bool) {
@@ -54,12 +67,11 @@ impl DocFS {
54
67
where
55
68
E: PathError,
56
69
{
57
- #[cfg(windows)]
58
70
if !self.sync_only {
59
71
// A possible future enhancement after more detailed profiling would
60
72
// be to create the file sync so errors are reported eagerly.
61
73
let sender = self.errors.clone().expect("can't write after closing");
62
- rayon::spawn (move || {
74
+ self.pool.execute (move || {
63
75
fs::write(&path, contents).unwrap_or_else(|e| {
64
76
sender.send(format!("\"{}\": {}", path.display(), e)).unwrap_or_else(|_| {
65
77
panic!("failed to send error on \"{}\"", path.display())
@@ -70,9 +82,12 @@ impl DocFS {
70
82
fs::write(&path, contents).map_err(|e| E::new(e, path))?;
71
83
}
72
84
73
- #[cfg(not(windows))]
74
- fs::write(&path, contents).map_err(|e| E::new(e, path))?;
75
-
76
85
Ok(())
77
86
}
78
87
}
88
+
89
+ impl Drop for DocFS {
90
+ fn drop(&mut self) {
91
+ self.pool.join();
92
+ }
93
+ }
0 commit comments