1 | #![cfg (not(loom))] |
2 | |
3 | //! Asynchronous file and standard stream adaptation. |
4 | //! |
5 | //! This module contains utility methods and adapter types for input/output to |
6 | //! files or standard streams (`Stdin`, `Stdout`, `Stderr`), and |
7 | //! filesystem manipulation, for use within (and only within) a Tokio runtime. |
8 | //! |
9 | //! Tasks run by *worker* threads should not block, as this could delay |
10 | //! servicing reactor events. Portable filesystem operations are blocking, |
11 | //! however. This module offers adapters which use a `blocking` annotation |
12 | //! to inform the runtime that a blocking operation is required. When |
13 | //! necessary, this allows the runtime to convert the current thread from a |
14 | //! *worker* to a *backup* thread, where blocking is acceptable. |
15 | //! |
16 | //! ## Usage |
17 | //! |
18 | //! Where possible, users should prefer the provided asynchronous-specific |
19 | //! traits such as [`AsyncRead`], or methods returning a `Future` or `Poll` |
20 | //! type. Adaptions also extend to traits like `std::io::Read` where methods |
21 | //! return `std::io::Result`. Be warned that these adapted methods may return |
22 | //! `std::io::ErrorKind::WouldBlock` if a *worker* thread can not be converted |
23 | //! to a *backup* thread immediately. |
24 | //! |
25 | //! **Warning**: These adapters may create a large number of temporary tasks, |
26 | //! especially when reading large files. When performing a lot of operations |
27 | //! in one batch, it may be significantly faster to use [`spawn_blocking`] |
28 | //! directly: |
29 | //! |
30 | //! ``` |
31 | //! use tokio::fs::File; |
32 | //! use std::io::{BufReader, BufRead}; |
33 | //! async fn count_lines(file: File) -> Result<usize, std::io::Error> { |
34 | //! let file = file.into_std().await; |
35 | //! tokio::task::spawn_blocking(move || { |
36 | //! let line_count = BufReader::new(file).lines().count(); |
37 | //! Ok(line_count) |
38 | //! }).await? |
39 | //! } |
40 | //! ``` |
41 | //! |
42 | //! [`spawn_blocking`]: fn@crate::task::spawn_blocking |
43 | //! [`AsyncRead`]: trait@crate::io::AsyncRead |
44 | |
45 | mod canonicalize; |
46 | pub use self::canonicalize::canonicalize; |
47 | |
48 | mod create_dir; |
49 | pub use self::create_dir::create_dir; |
50 | |
51 | mod create_dir_all; |
52 | pub use self::create_dir_all::create_dir_all; |
53 | |
54 | mod dir_builder; |
55 | pub use self::dir_builder::DirBuilder; |
56 | |
57 | mod file; |
58 | pub use self::file::File; |
59 | |
60 | mod hard_link; |
61 | pub use self::hard_link::hard_link; |
62 | |
63 | mod metadata; |
64 | pub use self::metadata::metadata; |
65 | |
66 | mod open_options; |
67 | pub use self::open_options::OpenOptions; |
68 | |
69 | mod read; |
70 | pub use self::read::read; |
71 | |
72 | mod read_dir; |
73 | pub use self::read_dir::{read_dir, DirEntry, ReadDir}; |
74 | |
75 | mod read_link; |
76 | pub use self::read_link::read_link; |
77 | |
78 | mod read_to_string; |
79 | pub use self::read_to_string::read_to_string; |
80 | |
81 | mod remove_dir; |
82 | pub use self::remove_dir::remove_dir; |
83 | |
84 | mod remove_dir_all; |
85 | pub use self::remove_dir_all::remove_dir_all; |
86 | |
87 | mod remove_file; |
88 | pub use self::remove_file::remove_file; |
89 | |
90 | mod rename; |
91 | pub use self::rename::rename; |
92 | |
93 | mod set_permissions; |
94 | pub use self::set_permissions::set_permissions; |
95 | |
96 | mod symlink_metadata; |
97 | pub use self::symlink_metadata::symlink_metadata; |
98 | |
99 | mod write; |
100 | pub use self::write::write; |
101 | |
102 | mod copy; |
103 | pub use self::copy::copy; |
104 | |
105 | mod try_exists; |
106 | pub use self::try_exists::try_exists; |
107 | |
108 | #[cfg (test)] |
109 | mod mocks; |
110 | |
111 | feature! { |
112 | #![unix] |
113 | |
114 | mod symlink; |
115 | pub use self::symlink::symlink; |
116 | } |
117 | |
118 | cfg_windows! { |
119 | mod symlink_dir; |
120 | pub use self::symlink_dir::symlink_dir; |
121 | |
122 | mod symlink_file; |
123 | pub use self::symlink_file::symlink_file; |
124 | } |
125 | |
126 | use std::io; |
127 | |
128 | #[cfg (not(test))] |
129 | use crate::blocking::spawn_blocking; |
130 | #[cfg (test)] |
131 | use mocks::spawn_blocking; |
132 | |
133 | pub(crate) async fn asyncify<F, T>(f: F) -> io::Result<T> |
134 | where |
135 | F: FnOnce() -> io::Result<T> + Send + 'static, |
136 | T: Send + 'static, |
137 | { |
138 | match spawn_blocking(func:f).await { |
139 | Ok(res: Result) => res, |
140 | Err(_) => Err(io::Error::new( |
141 | kind:io::ErrorKind::Other, |
142 | error:"background task failed" , |
143 | )), |
144 | } |
145 | } |
146 | |