#![cfg(not(loom))] //! Asynchronous file and standard stream adaptation. //! //! This module contains utility methods and adapter types for input/output to //! files or standard streams (`Stdin`, `Stdout`, `Stderr`), and //! filesystem manipulation, for use within (and only within) a Tokio runtime. //! //! Tasks run by *worker* threads should not block, as this could delay //! servicing reactor events. Portable filesystem operations are blocking, //! however. This module offers adapters which use a `blocking` annotation //! to inform the runtime that a blocking operation is required. When //! necessary, this allows the runtime to convert the current thread from a //! *worker* to a *backup* thread, where blocking is acceptable. //! //! ## Usage //! //! Where possible, users should prefer the provided asynchronous-specific //! traits such as [`AsyncRead`], or methods returning a `Future` or `Poll` //! type. Adaptions also extend to traits like `std::io::Read` where methods //! return `std::io::Result`. Be warned that these adapted methods may return //! `std::io::ErrorKind::WouldBlock` if a *worker* thread can not be converted //! to a *backup* thread immediately. //! //! **Warning**: These adapters may create a large number of temporary tasks, //! especially when reading large files. When performing a lot of operations //! in one batch, it may be significantly faster to use [`spawn_blocking`] //! directly: //! //! ``` //! use tokio::fs::File; //! use std::io::{BufReader, BufRead}; //! async fn count_lines(file: File) -> Result { //! let file = file.into_std().await; //! tokio::task::spawn_blocking(move || { //! let line_count = BufReader::new(file).lines().count(); //! Ok(line_count) //! }).await? //! } //! ``` //! //! [`spawn_blocking`]: fn@crate::task::spawn_blocking //! [`AsyncRead`]: trait@crate::io::AsyncRead mod canonicalize; pub use self::canonicalize::canonicalize; mod create_dir; pub use self::create_dir::create_dir; mod create_dir_all; pub use self::create_dir_all::create_dir_all; mod dir_builder; pub use self::dir_builder::DirBuilder; mod file; pub use self::file::File; mod hard_link; pub use self::hard_link::hard_link; mod metadata; pub use self::metadata::metadata; mod open_options; pub use self::open_options::OpenOptions; mod read; pub use self::read::read; mod read_dir; pub use self::read_dir::{read_dir, DirEntry, ReadDir}; mod read_link; pub use self::read_link::read_link; mod read_to_string; pub use self::read_to_string::read_to_string; mod remove_dir; pub use self::remove_dir::remove_dir; mod remove_dir_all; pub use self::remove_dir_all::remove_dir_all; mod remove_file; pub use self::remove_file::remove_file; mod rename; pub use self::rename::rename; mod set_permissions; pub use self::set_permissions::set_permissions; mod symlink_metadata; pub use self::symlink_metadata::symlink_metadata; mod write; pub use self::write::write; mod copy; pub use self::copy::copy; mod try_exists; pub use self::try_exists::try_exists; #[cfg(test)] mod mocks; feature! { #![unix] mod symlink; pub use self::symlink::symlink; } cfg_windows! { mod symlink_dir; pub use self::symlink_dir::symlink_dir; mod symlink_file; pub use self::symlink_file::symlink_file; } use std::io; #[cfg(not(test))] use crate::blocking::spawn_blocking; #[cfg(test)] use mocks::spawn_blocking; pub(crate) async fn asyncify(f: F) -> io::Result where F: FnOnce() -> io::Result + Send + 'static, T: Send + 'static, { match spawn_blocking(f).await { Ok(res) => res, Err(_) => Err(io::Error::new( io::ErrorKind::Other, "background task failed", )), } }