2
0
Fork 1
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:
Florian Gilcher 2019-08-16 17:46:22 +02:00 committed by GitHub
commit efd4b7f7ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 159 additions and 196 deletions

3
CHANGELOG.md Normal file
View file

@ -0,0 +1,3 @@
# Version 0.99.3
- Initial beta release

View file

@ -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"

View file

@ -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

View file

@ -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 Rusts `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 doesnt rely on a runtime being started.
`async_std`s task api handles setup and teardown of a backing runtime for you and doesnt 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

View file

@ -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 youll 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 MITs 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 youll 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 MITs 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 youre 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-----
```

View file

@ -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(())
}))
}

View file

@ -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());
/// #
/// # }) }
/// ```

View file

@ -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);
/// #
/// # }) }
/// ```

View file

@ -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(&[]))
}

View file

@ -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?;
/// #

View file

@ -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;

View file

@ -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 _;

View file

@ -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;
}

View file

@ -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;

View file

@ -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 {}