mirror of
https://github.com/async-rs/async-std.git
synced 2025-01-30 01:05:31 +00:00
Merge branch 'master' into book-release-ready
This commit is contained in:
commit
efd4b7f7ff
15 changed files with 159 additions and 196 deletions
3
CHANGELOG.md
Normal file
3
CHANGELOG.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Version 0.99.3
|
||||
|
||||
- Initial beta release
|
11
Cargo.toml
11
Cargo.toml
|
@ -1,7 +1,10 @@
|
|||
[package]
|
||||
name = "async-std"
|
||||
version = "0.1.0"
|
||||
authors = ["Stjepan Glavina <stjepang@gmail.com>"]
|
||||
version = "0.99.3"
|
||||
authors = [
|
||||
"Stjepan Glavina <stjepang@gmail.com>",
|
||||
"The async-std Project Developers",
|
||||
]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0/MIT"
|
||||
repository = "https://github.com/async-rs/async-std"
|
||||
|
@ -13,13 +16,13 @@ categories = ["asynchronous", "concurrency", "network-programming"]
|
|||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["docs"]
|
||||
rustdoc-args = ["--features docs"]
|
||||
rustdoc-args = ["--cfg", "feature=\"docs\""]
|
||||
|
||||
[features]
|
||||
docs = []
|
||||
|
||||
[dependencies]
|
||||
async-task = { git = "ssh://git@github.com/async-rs/async-task.git" }
|
||||
async-task = "1.0.0"
|
||||
cfg-if = "0.1.9"
|
||||
crossbeam-channel = "0.3.9"
|
||||
futures-preview = "0.3.0-alpha.17"
|
||||
|
|
48
README.md
48
README.md
|
@ -1,13 +1,13 @@
|
|||
# Async version of Rust's standard library
|
||||
|
||||
[![Build Status](https://travis-ci.com/async-rs/async-std.svg?branch=master)](https://travis-ci.org/async-rs/async-std)
|
||||
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](
|
||||
https://github.com/async-rs/async-std)
|
||||
[![Build Status](https://travis-ci.com/async-rs/async-std.svg?branch=master)](https://travis-ci.com/async-rs/async-std)
|
||||
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](https://github.com/async-rs/async-std)
|
||||
[![Cargo](https://img.shields.io/crates/v/async-std.svg)](https://crates.io/crates/async-std)
|
||||
[![Documentation](https://docs.rs/async-std/badge.svg)](https://docs.rs/async-std)
|
||||
[![chat](https://img.shields.io/discord/598880689856970762.svg?logo=discord)](https://discord.gg/JvZeVNe)
|
||||
|
||||
This crate provides an async version of [`std`]. It provides all the interfaces you are used to, but in an async version and ready for Rust's `async/await`-syntax.
|
||||
This crate provides an async version of [`std`]. It provides all the interfaces you
|
||||
are used to, but in an async version and ready for Rust's `async`/`await` syntax.
|
||||
|
||||
[`std`]: https://doc.rust-lang.org/std/index.html
|
||||
|
||||
|
@ -49,15 +49,51 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
## Low-Friction Sockets with Built-In Timeouts
|
||||
|
||||
```rust
|
||||
#![feature(async_await)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use async_std::{
|
||||
prelude::*,
|
||||
task,
|
||||
io,
|
||||
net::TcpStream,
|
||||
};
|
||||
|
||||
async fn get() -> io::Result<Vec<u8>> {
|
||||
let mut stream = TcpStream::connect("example.com:80").await?;
|
||||
stream.write_all(b"GET /index.html HTTP/1.0\r\n\r\n").await?;
|
||||
|
||||
let mut buf = vec![];
|
||||
|
||||
io::timeout(Duration::from_secs(5), async {
|
||||
stream.read_to_end(&mut buf).await?
|
||||
Ok(buf)
|
||||
})
|
||||
}
|
||||
|
||||
fn main() {
|
||||
task::block_on(async {
|
||||
let raw_response = get().await.expect("request");
|
||||
let response = String::from_utf8(raw_response)
|
||||
.expect("utf8 conversion");
|
||||
println!("received: {}", response);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Take a look around
|
||||
|
||||
Clone the repo:
|
||||
|
||||
```
|
||||
git clone git@github.com:stjepang/async-std.git && cd async-std
|
||||
git clone git@github.com:async-rs/async-std.git && cd async-std
|
||||
```
|
||||
|
||||
Read the docs:
|
||||
Generate docs:
|
||||
|
||||
```
|
||||
cargo doc --features docs.rs --open
|
||||
|
|
|
@ -60,21 +60,68 @@ For now, it is enough to know that once you `spawn`ed a task, it will continue r
|
|||
Tasks in `async_std` are one of the core abstractions. Much like Rust’s `thread`s, they provide some practical functionality over the raw concept. `Tasks` have a relationship to the runtime, but they are in themselves separate. `async_std` tasks have a number of desirable properties:
|
||||
|
||||
|
||||
- They are single-allocated
|
||||
- They are allocated in one single allocation
|
||||
- All tasks have a *backchannel*, which allows them to propagate results and errors to the spawning task through the `JoinHandle`
|
||||
- The carry desirable metadata for debugging
|
||||
- They support task local storage
|
||||
|
||||
`async_std` s task api handles setup and teardown of a backing runtime for you and doesn’t rely on a runtime being started.
|
||||
`async_std`s task api handles setup and teardown of a backing runtime for you and doesn’t rely on a runtime being started.
|
||||
|
||||
## Blocking
|
||||
|
||||
TODO: fill me in
|
||||
`Task`s are assumed to run _concurrently_, potentially by sharing a thread of execution. This means that operations blocking an _operating system thread_, such as `std::thread::sleep` or io function from Rusts stdlib will _stop execution of all tasks sharing this thread_. Other libraries (such as database drivers) have similar behaviour. Note that _blocking the current thread_ is not in and by itself bad behaviour, just something that does not mix well with they concurrent execution model of `async-std`. Essentially, never do this:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
task::block_on(async {
|
||||
// this is std::fs, which blocks
|
||||
std::fs::read_to_string("test_file");
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
If you want to mix operation kinds, consider putting such operations on a `thread`.
|
||||
|
||||
## Errors and panics
|
||||
|
||||
TODO: fill me in
|
||||
`Task`s report errors through normal channels: If they are fallible, their `Output` should be of kind `Result<T,E>`.
|
||||
|
||||
In case of `panic`, behaviour differs depending on if there's a reasonable part that addresses the `panic`. If not, the program _aborts_.
|
||||
|
||||
In practice, that means that `block_on` propagates panics to the blocking component:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
task::block_on(async {
|
||||
panic!("test");
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
thread 'async-task-driver' panicked at 'test', examples/panic.rs:8:9
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
|
||||
```
|
||||
|
||||
While panicing a spawned tasks will abort:
|
||||
|
||||
```rust
|
||||
task::spawn(async {
|
||||
panic!("test");
|
||||
});
|
||||
|
||||
task::block_on(async {
|
||||
task::sleep(Duration::from_millis(10000)).await;
|
||||
})
|
||||
```
|
||||
|
||||
```
|
||||
thread 'async-task-driver' panicked at 'test', examples/panic.rs:8:9
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
|
||||
Aborted (core dumped)
|
||||
```
|
||||
|
||||
That might seem odd at first, but the other option would be to silently ignore panics in spawned tasks. The current behaviour can be changed by catching panics in the spawned task and reacting with custom behaviour. This gives users the choice of panic handling strategy.
|
||||
|
||||
## Conclusion
|
||||
|
||||
|
|
|
@ -2,14 +2,12 @@
|
|||
|
||||
Safety is one of the core principles of what we do, and to that end, we would like to ensure that async-std has a secure implementation. Thank you for taking the time to responsibly disclose any issues you find.
|
||||
|
||||
All security bugs in async-std distribution should be reported by email to security@ferrous-systems.com. This list is delivered to a small security team. Your email will be acknowledged within 24 hours, and you’ll receive a more detailed response to your email within 48 hours indicating the next steps in handling your report. If you would like, you can encrypt your report using our public key. This key is also On MIT’s keyserver and reproduced below.
|
||||
All security bugs in async-std distribution should be reported by email to florian.gilcher@ferrous-systems.com. This list is delivered to a small security team. Your email will be acknowledged within 24 hours, and you’ll receive a more detailed response to your email within 48 hours indicating the next steps in handling your report. If you would like, you can encrypt your report using our public key. This key is also On MIT’s keyserver and reproduced below.
|
||||
|
||||
Be sure to use a descriptive subject line to avoid having your report be missed. After the initial reply to your report, the security team will endeavor to keep you informed of the progress being made towards a fix and full announcement. As recommended by [RFPolicy][rf-policy], these updates will be sent at least every five days. In reality, this is more likely to be every 24-48 hours.
|
||||
|
||||
If you have not received a reply to your email within 48 hours, or have not heard from the security team for the past five days, there are a few steps you can take (in order):
|
||||
|
||||
* Contact the current security coordinator TODO directly.
|
||||
* Contact the back-up contact TODO directly.
|
||||
* Post on our Community forums
|
||||
|
||||
Please note that the discussion forums are public areas. When escalating in these venues, please do not discuss your issue. Simply say that you’re trying to get a hold of someone from the security team.
|
||||
|
@ -34,4 +32,35 @@ This policy is adapted from the [Rust project](https://www.rust-lang.org/policie
|
|||
|
||||
## PGP Key
|
||||
|
||||
TODO
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBF1Wu/ABCADJaGt4HwSlqKB9BGHWYKZj/6mTMbmc29vsEOcCSQKo6myCf9zc
|
||||
sasWAttep4FAUDX+MJhVbBTSq9M1YVxp33Qh5AF0t9SnJZnbI+BZuGawcHDL01xE
|
||||
bE+8bcA2+szeTTUZCeWwsaoTd/2qmQKvpUCBQp7uBs/ITO/I2q7+xCGXaOHZwUKc
|
||||
H8SUBLd35nYFtjXAeejoZVkqG2qEjrc9bkZAwxFXi7Fw94QdkNLaCjNfKxZON/qP
|
||||
A3WOpyWPr3ERk5C5prjEAvrW8kdqpTRjdmzQjsr8UEXb5GGEOo93N4OLZVQ2mXt9
|
||||
dfn++GOnOk7sTxvfiDH8Ru5o4zCtKgO+r5/LABEBAAG0UkZsb3JpYW4gR2lsY2hl
|
||||
ciAoU2VjdXJpdHkgY29udGFjdCBhc3luYy1zdGQpIDxmbG9yaWFuLmdpbGNoZXJA
|
||||
ZmVycm91cy1zeXN0ZW1zLmNvbT6JATgEEwECACIFAl1Wu/ACGwMGCwkIBwMCBhUI
|
||||
AgkKCwQWAgMBAh4BAheAAAoJEACXY97PwLtSc0AH/18yvrElVOkG0ADWX7l+JKHH
|
||||
nMQtYj0Auop8d6TuKBbpwtYhwELrQoITDMV7f2XEnchNsvYxAyBZhIISmXeJboE1
|
||||
KzZD1O+4QPXRcXhj+QNsKQ680mrgZXgAI2Y4ptIW9Vyw3jiHu/ZVopvDAt4li+up
|
||||
3fRJGPAvGu+tclpJmA+Xam23cDj89M7/wHHgKIyT59WgFwyCgibL+NHKwg2Unzou
|
||||
9uyZQnq6hf62sQTWEZIAr9BQpKmluplNIJHDeECWzZoE9ucE2ZXsq5pq9qojsAMK
|
||||
yRdaFdpBcD/AxtrTKFeXGS7X7LqaljY/IFBEdJOqVNWpqSLjGWqjSLIEsc1AB0K5
|
||||
AQ0EXVa78AEIAJMxBOEEW+2c3CcjFuUfcRsoBsFH3Vk+GwCbjIpNHq/eAvS1yy2L
|
||||
u10U5CcT5Xb6be3AeCYv00ZHVbEi6VwoauVCSX8qDjhVzQxvNLgQ1SduobjyF6t8
|
||||
3M/wTija6NvMKszyw1l2oHepxSMLej1m49DyCDFNiZm5rjQcYnFT4J71syxViqHF
|
||||
v2fWCheTrHP3wfBAt5zyDet7IZd/EhYAK6xXEwr9nBPjfbaVexm2B8K6hOPNj0Bp
|
||||
OKm4rcOj7JYlcxrwhMvNnwEue7MqH1oXAsoaC1BW+qs4acp/hHpesweL6Rcg1pED
|
||||
OJUQd3UvRsqRK0EsorDu0oj5wt6Qp3ZEbPMAEQEAAYkBHwQYAQIACQUCXVa78AIb
|
||||
DAAKCRAAl2Pez8C7Uv8bB/9scRm2wvzHLbFtcEHaHvlKO1yYfSVqKqJzIKHc7pM2
|
||||
+szM8JVRTxAbzK5Xih9SB5xlekixxO2UCJI5DkJ/ir/RCcg+/CAQ8iLm2UcYAgJD
|
||||
TocKiR5gjNAvUDI4tMrDLLdF+7+RCQGc7HBSxFiNBJVGAztGVh1+cQ0zaCX6Tt33
|
||||
1EQtyRcPID0m6+ip5tCJN0dILC0YcwzXGrSgjB03JqItIyJEucdQz6UB84TIAGku
|
||||
JJl4tktgD9T7Rb5uzRhHCSbLy89DQVvCcKD4B94ffuDW3HO8n8utDusOiZuG4BUf
|
||||
WdFy6/gTLNiFbTzkq1BBJQMN1nBwGs1sn63RRgjumZ1N
|
||||
=dIcF
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
|
@ -8,13 +8,15 @@ use async_std::io;
|
|||
use async_std::task;
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
// This async scope times out after 5 seconds.
|
||||
task::block_on(io::timeout(Duration::from_secs(5), async {
|
||||
let stdin = io::stdin();
|
||||
|
||||
// Read a line from the standard input and display it.
|
||||
let mut line = String::new();
|
||||
stdin.read_line(&mut line).await?;
|
||||
dbg!(line);
|
||||
|
||||
print!("Got line: {}", line);
|
||||
Ok(())
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
/// use std::time::Duration;
|
||||
///
|
||||
/// use async_std::future::pending;
|
||||
/// use async_std::prelude::*;
|
||||
/// use async_std::io;
|
||||
///
|
||||
/// let dur = Duration::from_secs(1);
|
||||
/// assert!(pending::<()>().timeout(dur).await.is_err());
|
||||
/// let fut = pending();
|
||||
///
|
||||
/// let res: io::Result<()> = io::timeout(dur, fut).await;
|
||||
/// assert!(res.is_err());
|
||||
/// #
|
||||
/// # }) }
|
||||
/// ```
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
/// # #![feature(async_await)]
|
||||
/// # fn main() { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use async_std::future::ready;
|
||||
/// use async_std::future;
|
||||
///
|
||||
/// assert_eq!(ready(10).await, 10);
|
||||
/// assert_eq!(future::ready(10).await, 10);
|
||||
/// #
|
||||
/// # }) }
|
||||
/// ```
|
||||
|
|
|
@ -62,7 +62,10 @@ impl AsyncRead for Empty {
|
|||
|
||||
impl AsyncBufRead for Empty {
|
||||
#[inline]
|
||||
fn poll_fill_buf(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
|
||||
fn poll_fill_buf<'a>(
|
||||
self: Pin<&'a mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
) -> Poll<io::Result<&'a [u8]>> {
|
||||
Poll::Ready(Ok(&[]))
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ use crate::task::{Context, Poll};
|
|||
/// let stdin = io::stdin();
|
||||
/// let mut line = String::new();
|
||||
/// let n = stdin.read_line(&mut line).await?;
|
||||
/// Ok(())
|
||||
/// })
|
||||
/// .await?;
|
||||
/// #
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! Async version of the Rust standard library.
|
||||
//!
|
||||
//! This crate is an async version of [`std`].
|
||||
//!
|
||||
//! Higher-level documentation in the form of the book
|
||||
//! ["Async programming in Rust with async-std"][book]
|
||||
//! is available.
|
||||
|
@ -22,6 +23,9 @@
|
|||
//! })
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! See [here](https://github.com/async-rs/async-std/tree/master/examples)
|
||||
//! for more examples.
|
||||
|
||||
#![feature(async_await)]
|
||||
#![cfg_attr(feature = "docs", feature(doc_cfg))]
|
||||
|
@ -39,6 +43,5 @@ pub mod prelude;
|
|||
pub mod stream;
|
||||
pub mod sync;
|
||||
pub mod task;
|
||||
pub mod time;
|
||||
|
||||
pub(crate) mod utils;
|
||||
|
|
|
@ -1,30 +1,6 @@
|
|||
//! The async prelude.
|
||||
//!
|
||||
//! The prelude re-exports the most commonly used traits in async programming.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Import the prelude to use the [`timeout`] combinator:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # #![feature(async_await)]
|
||||
//! # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
//! #
|
||||
//! use std::time::Duration;
|
||||
//!
|
||||
//! use async_std::io;
|
||||
//! use async_std::prelude::*;
|
||||
//!
|
||||
//! let stdin = io::stdin();
|
||||
//! let mut line = String::new();
|
||||
//! let dur = Duration::from_secs(5);
|
||||
//!
|
||||
//! stdin.read_line(&mut line).timeout(dur).await??;
|
||||
//! #
|
||||
//! # Ok(()) }) }
|
||||
//! ```
|
||||
//!
|
||||
//! [`timeout`]: ../time/trait.Timeout.html#method.timeout
|
||||
//! The prelude re-exports the most commonly used traits in this crate.
|
||||
|
||||
#[doc(no_inline)]
|
||||
pub use crate::future::Future;
|
||||
|
@ -40,5 +16,3 @@ pub use crate::io::Write as _;
|
|||
pub use crate::stream::Stream;
|
||||
#[doc(no_inline)]
|
||||
pub use crate::task_local;
|
||||
#[doc(no_inline)]
|
||||
pub use crate::time::Timeout as _;
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use futures::future;
|
||||
|
||||
use crate::time::Timeout;
|
||||
use crate::future;
|
||||
use crate::io;
|
||||
|
||||
/// Sleeps for the specified amount of time.
|
||||
///
|
||||
|
@ -27,5 +26,5 @@ use crate::time::Timeout;
|
|||
/// # }) }
|
||||
/// ```
|
||||
pub async fn sleep(dur: Duration) {
|
||||
let _ = future::pending::<()>().timeout(dur).await;
|
||||
let _: io::Result<()> = io::timeout(dur, future::pending()).await;
|
||||
}
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
//! Timeouts for async operations.
|
||||
//!
|
||||
//! This module is an async extension of [`std::time`].
|
||||
//!
|
||||
//! [`std::time`]: https://doc.rust-lang.org/std/time/index.html
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Read a line from stdin with a timeout of 5 seconds.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # #![feature(async_await)]
|
||||
//! # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
//! #
|
||||
//! use std::time::Duration;
|
||||
//!
|
||||
//! use async_std::io;
|
||||
//! use async_std::prelude::*;
|
||||
//!
|
||||
//! let stdin = io::stdin();
|
||||
//! let mut line = String::new();
|
||||
//!
|
||||
//! let n = stdin
|
||||
//! .read_line(&mut line)
|
||||
//! .timeout(Duration::from_secs(5))
|
||||
//! .await??;
|
||||
//! #
|
||||
//! # Ok(()) }) }
|
||||
//! ```
|
||||
|
||||
pub use timeout::{Timeout, TimeoutError};
|
||||
|
||||
mod timeout;
|
|
@ -1,107 +0,0 @@
|
|||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::pin::Pin;
|
||||
use std::time::Duration;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use futures_timer::Delay;
|
||||
use pin_utils::unsafe_pinned;
|
||||
|
||||
use crate::future::Future;
|
||||
use crate::io;
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "docs")] {
|
||||
#[doc(hidden)]
|
||||
pub struct ImplFuture<T>(std::marker::PhantomData<T>);
|
||||
|
||||
macro_rules! ret {
|
||||
($f:tt, $o:ty) => (ImplFuture<$o>);
|
||||
}
|
||||
} else {
|
||||
macro_rules! ret {
|
||||
($f:tt, $o:ty) => ($f<Self>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An error returned when a future times out.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct TimeoutError;
|
||||
|
||||
impl Error for TimeoutError {}
|
||||
|
||||
impl fmt::Display for TimeoutError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
"future has timed out".fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TimeoutError> for io::Error {
|
||||
fn from(_: TimeoutError) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::TimedOut, "future has timed out")
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension trait that configures timeouts for futures.
|
||||
pub trait Timeout: Future + Sized {
|
||||
/// Awaits a future to completion or times out after a duration of time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #![feature(async_await)]
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// use async_std::io;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let stdin = io::stdin();
|
||||
/// let mut line = String::new();
|
||||
///
|
||||
/// let n = stdin
|
||||
/// .read_line(&mut line)
|
||||
/// .timeout(Duration::from_secs(5))
|
||||
/// .await??;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
fn timeout(self, dur: Duration) -> ret!(TimeoutFuture, Result<Self::Output, TimeoutError>) {
|
||||
TimeoutFuture {
|
||||
future: self,
|
||||
delay: Delay::new(dur),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A future that times out after a duration of time.
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct TimeoutFuture<F> {
|
||||
future: F,
|
||||
delay: Delay,
|
||||
}
|
||||
|
||||
impl<F> TimeoutFuture<F> {
|
||||
unsafe_pinned!(future: F);
|
||||
unsafe_pinned!(delay: Delay);
|
||||
}
|
||||
|
||||
impl<F: Future> Future for TimeoutFuture<F> {
|
||||
type Output = Result<F::Output, TimeoutError>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.as_mut().future().poll(cx) {
|
||||
Poll::Ready(v) => Poll::Ready(Ok(v)),
|
||||
Poll::Pending => match self.delay().poll(cx) {
|
||||
Poll::Ready(_) => Poll::Ready(Err(TimeoutError)),
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Future> Timeout for F {}
|
Loading…
Reference in a new issue