From 09e0e888b46eb626017ba7c64f636be33acc5cef Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Mon, 14 Oct 2019 15:03:07 +0200 Subject: [PATCH 1/8] add print macros Signed-off-by: Yoshua Wuyts --- src/lib.rs | 1 + src/print.rs | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 src/print.rs diff --git a/src/lib.rs b/src/lib.rs index fb2e6bf..e24bcc5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ mod join; mod join_stream; mod maybe_done; mod poll_fn; +mod print; mod ready; mod select; mod try_join; diff --git a/src/print.rs b/src/print.rs new file mode 100644 index 0000000..98ffdc7 --- /dev/null +++ b/src/print.rs @@ -0,0 +1,179 @@ +/// Prints to the standard output. +/// +/// Equivalent to the [`println!`] macro except that a newline is not printed at +/// the end of the message. +/// +/// Note that stdout is frequently line-buffered by default so it may be +/// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted +/// immediately. +/// +/// Use `print!` only for the primary output of your program. Use +/// [`eprint!`] instead to print error and progress messages. +/// +/// [`println!`]: macro.println.html +/// [flush]: io/trait.Write.html#tymethod.flush +/// [`eprint!`]: macro.eprint.html +/// +/// # Panics +/// +/// Panics if writing to `io::stdout()` fails. +/// +/// # Examples +/// +/// ``` +/// # async_std::task::block_on(async { +/// # +/// use async_std::prelude::*; +/// use async_std::io; +/// use async_std::print; +/// +/// print!("this ").await; +/// print!("will ").await; +/// print!("be ").await; +/// print!("on ").await; +/// print!("the ").await; +/// print!("same ").await; +/// print!("line ").await; +/// +/// io::stdout().flush().await.unwrap(); +/// +/// print!("this string has a newline, why not choose println! instead?\n").await; +/// +/// io::stdout().flush().await.unwrap(); +/// # +/// # }) +/// ``` +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ( + async { + let args = format_args!($($arg)*); + if let Err(e) = stdout().write_fmt(args).await { + panic!("failed printing to stdout: {}", e); + } + } + ); +} + +/// Prints to the standard output, with a newline. +/// +/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone +/// (no additional CARRIAGE RETURN (`\r`/`U+000D`)). +/// +/// Use the [`format!`] syntax to write data to the standard output. +/// See [`std::fmt`] for more information. +/// +/// Use `println!` only for the primary output of your program. Use +/// [`eprintln!`] instead to print error and progress messages. +/// +/// [`format!`]: macro.format.html +/// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html +/// [`eprintln!`]: macro.eprintln.html +/// # Panics +/// +/// Panics if writing to `io::stdout` fails. +/// +/// # Examples +/// +/// ``` +/// # async_std::task::block_on(async { +/// # +/// use async_std::println; +/// +/// println!().await; // prints just a newline +/// println!("hello there!").await; +/// println!("format {} arguments", "some").await; +/// # +/// # }) +/// ``` +#[macro_export] +macro_rules! println { + () => ($crate::print!("\n")); + ($($arg:tt)*) => ( + async { + let args = format_args!($($arg)*); + if let Err(e) = stdout().write_fmt(args).await { + panic!("failed printing to stdout: {}", e); + } + } + ); +} + +/// Prints to the standard error. +/// +/// Equivalent to the [`print!`] macro, except that output goes to +/// [`io::stderr`] instead of `io::stdout`. See [`print!`] for +/// example usage. +/// +/// Use `eprint!` only for error and progress messages. Use `print!` +/// instead for the primary output of your program. +/// +/// [`io::stderr`]: io/struct.Stderr.html +/// [`print!`]: macro.print.html +/// +/// # Panics +/// +/// Panics if writing to `io::stderr` fails. +/// +/// # Examples +/// +/// ``` +/// # async_std::task::block_on(async { +/// # +/// use async_std::eprint; +/// +/// eprint!("Error: Could not complete task").await; +/// # +/// # }) +/// ``` +#[macro_export] +macro_rules! eprint { + ($($arg:tt)*) => ( + async { + let args = format_args!($($arg)*); + if let Err(e) = stderr().write_fmt(args).await { + panic!("failed printing to stderr: {}", e); + } + } + ); +} + +/// Prints to the standard error, with a newline. +/// +/// Equivalent to the [`println!`] macro, except that output goes to +/// [`io::stderr`] instead of `io::stdout`. See [`println!`] for +/// example usage. +/// +/// Use `eprintln!` only for error and progress messages. Use `println!` +/// instead for the primary output of your program. +/// +/// [`io::stderr`]: io/struct.Stderr.html +/// [`println!`]: macro.println.html +/// +/// # Panics +/// +/// Panics if writing to `io::stderr` fails. +/// +/// # Examples +/// +/// ``` +/// # async_std::task::block_on(async { +/// # +/// use async_std::eprintln; +/// +/// eprintln!("Error: Could not complete task").await; +/// # +/// # }) +/// ``` +#[macro_export] +macro_rules! eprintln { + () => ($crate::eprint!("\n")); + ($($arg:tt)*) => ( + async { + let args = format_args!($($arg)*); + if let Err(e) = stderr().write_fmt(args).await { + panic!("failed printing to stderr: {}", e); + } + } + ); +} From 41f4d0748c7e1a1cd4372c2add314e20ceb0c80d Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Mon, 14 Oct 2019 17:13:12 +0200 Subject: [PATCH 2/8] fix macros Signed-off-by: Yoshua Wuyts --- src/lib.rs | 3 +++ src/print.rs | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e24bcc5..e78a8e4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,9 +31,12 @@ mod try_select; pub use join_stream::JoinStream; pub use maybe_done::MaybeDone; +pub use std::{write, writeln}; /// Helper re-exports for use in macros. pub mod utils { pub use super::poll_fn::poll_fn; pub use core::{future, pin, result, task}; + pub use std::format_args; + pub use std::panic; } diff --git a/src/print.rs b/src/print.rs index 98ffdc7..a1a3b1e 100644 --- a/src/print.rs +++ b/src/print.rs @@ -47,9 +47,9 @@ macro_rules! print { ($($arg:tt)*) => ( async { - let args = format_args!($($arg)*); - if let Err(e) = stdout().write_fmt(args).await { - panic!("failed printing to stdout: {}", e); + let args = $crate::utils::format_args!($($arg)*); + if let Err(e) = ::async_std::io::stdout().write_fmt(args).await { + $crate::utils::panic!("failed printing to stdout: {}", e); } } ); @@ -91,9 +91,9 @@ macro_rules! println { () => ($crate::print!("\n")); ($($arg:tt)*) => ( async { - let args = format_args!($($arg)*); - if let Err(e) = stdout().write_fmt(args).await { - panic!("failed printing to stdout: {}", e); + let args = $crate::utils::format_args!($($arg)*); + if let Err(e) = ::async_std::io::stdout().write_fmt(args).await { + $crate::utils::panic!("failed printing to stdout: {}", e); } } ); @@ -130,9 +130,9 @@ macro_rules! println { macro_rules! eprint { ($($arg:tt)*) => ( async { - let args = format_args!($($arg)*); - if let Err(e) = stderr().write_fmt(args).await { - panic!("failed printing to stderr: {}", e); + let args = $crate::utils::format_args!($($arg)*); + if let Err(e) = ::async_std::io::stderr().write_fmt(args).await { + $crate::panic!("failed printing to stderr: {}", e); } } ); @@ -170,9 +170,9 @@ macro_rules! eprintln { () => ($crate::eprint!("\n")); ($($arg:tt)*) => ( async { - let args = format_args!($($arg)*); - if let Err(e) = stderr().write_fmt(args).await { - panic!("failed printing to stderr: {}", e); + let args = $crate::utils::format_args!($($arg)*); + if let Err(e) = ::async_std::io::stderr().write_fmt(args).await { + $crate::panic!("failed printing to stderr: {}", e); } } ); From 1130ff256cf3e01c3b0d5028dbdfbfb91a393617 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Mon, 14 Oct 2019 17:50:17 +0200 Subject: [PATCH 3/8] fix newline logging Signed-off-by: Yoshua Wuyts --- src/print.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/print.rs b/src/print.rs index a1a3b1e..92949ce 100644 --- a/src/print.rs +++ b/src/print.rs @@ -47,6 +47,7 @@ macro_rules! print { ($($arg:tt)*) => ( async { + use ::async_std::prelude::*; let args = $crate::utils::format_args!($($arg)*); if let Err(e) = ::async_std::io::stdout().write_fmt(args).await { $crate::utils::panic!("failed printing to stdout: {}", e); @@ -91,10 +92,12 @@ macro_rules! println { () => ($crate::print!("\n")); ($($arg:tt)*) => ( async { + use ::async_std::prelude::*; let args = $crate::utils::format_args!($($arg)*); if let Err(e) = ::async_std::io::stdout().write_fmt(args).await { $crate::utils::panic!("failed printing to stdout: {}", e); } + $crate::utils::print!("\n").await; } ); } @@ -130,9 +133,10 @@ macro_rules! println { macro_rules! eprint { ($($arg:tt)*) => ( async { + use ::async_std::prelude::*; let args = $crate::utils::format_args!($($arg)*); if let Err(e) = ::async_std::io::stderr().write_fmt(args).await { - $crate::panic!("failed printing to stderr: {}", e); + $crate::utils::panic!("failed printing to stderr: {}", e); } } ); @@ -170,10 +174,12 @@ macro_rules! eprintln { () => ($crate::eprint!("\n")); ($($arg:tt)*) => ( async { + use ::async_std::prelude::*; let args = $crate::utils::format_args!($($arg)*); if let Err(e) = ::async_std::io::stderr().write_fmt(args).await { - $crate::panic!("failed printing to stderr: {}", e); + $crate::utils::panic!("failed printing to stderr: {}", e); } + $crate::eprint!("\n").await; } ); } From 6b0cc79c0e8d2cd36863e102ef1a31d093786b50 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Mon, 14 Oct 2019 18:04:43 +0200 Subject: [PATCH 4/8] also export task_local Signed-off-by: Yoshua Wuyts --- src/lib.rs | 1 + src/print.rs | 8 ++++---- src/task_local.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 src/task_local.rs diff --git a/src/lib.rs b/src/lib.rs index e78a8e4..2e1d170 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,7 @@ mod ready; mod select; mod try_join; mod try_select; +mod task_local; pub use join_stream::JoinStream; pub use maybe_done::MaybeDone; diff --git a/src/print.rs b/src/print.rs index 92949ce..2da8e1b 100644 --- a/src/print.rs +++ b/src/print.rs @@ -20,7 +20,7 @@ /// /// # Examples /// -/// ``` +/// ```ignore /// # async_std::task::block_on(async { /// # /// use async_std::prelude::*; @@ -76,7 +76,7 @@ macro_rules! print { /// /// # Examples /// -/// ``` +/// ```ignore /// # async_std::task::block_on(async { /// # /// use async_std::println; @@ -120,7 +120,7 @@ macro_rules! println { /// /// # Examples /// -/// ``` +/// ```ignore /// # async_std::task::block_on(async { /// # /// use async_std::eprint; @@ -160,7 +160,7 @@ macro_rules! eprint { /// /// # Examples /// -/// ``` +/// ```ignore /// # async_std::task::block_on(async { /// # /// use async_std::eprintln; diff --git a/src/task_local.rs b/src/task_local.rs new file mode 100644 index 0000000..14bb27b --- /dev/null +++ b/src/task_local.rs @@ -0,0 +1,50 @@ +/// Declares task-local values. +/// +/// The macro wraps any number of static declarations and makes them task-local. Attributes and +/// visibility modifiers are allowed. +/// +/// Each declared value is of the accessor type [`LocalKey`]. +/// +/// [`LocalKey`]: task/struct.LocalKey.html +/// +/// # Examples +/// +/// ``` +/// # +/// use std::cell::Cell; +/// +/// use async_std::task; +/// use async_std::prelude::*; +/// +/// task_local! { +/// static VAL: Cell = Cell::new(5); +/// } +/// +/// task::block_on(async { +/// let v = VAL.with(|c| c.get()); +/// assert_eq!(v, 5); +/// }); +/// ``` +#[macro_export] +macro_rules! task_local { + () => (); + + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => ( + $(#[$attr])* $vis static $name: ::async_std::task::LocalKey<$t> = { + #[inline] + fn __init() -> $t { + $init + } + + ::async_std::task::LocalKey { + __init, + __key: ::std::sync::atomic::AtomicUsize::new(0), + } + }; + ); + + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( + $crate::task_local!($(#[$attr])* $vis static $name: $t = $init); + $crate::task_local!($($rest)*); + ); +} From 181913470c51e64fc88d2f2be9bcaeb3eba67180 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Mon, 14 Oct 2019 18:15:22 +0200 Subject: [PATCH 5/8] cargo fmt Signed-off-by: Yoshua Wuyts --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2e1d170..2e36f4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,9 +26,9 @@ mod poll_fn; mod print; mod ready; mod select; +mod task_local; mod try_join; mod try_select; -mod task_local; pub use join_stream::JoinStream; pub use maybe_done::MaybeDone; From ecf5312ec12a237351e5dab42e9b1f64d0ca442d Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Mon, 14 Oct 2019 18:21:50 +0200 Subject: [PATCH 6/8] skip task_local macros Signed-off-by: Yoshua Wuyts --- src/task_local.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/task_local.rs b/src/task_local.rs index 14bb27b..1664f89 100644 --- a/src/task_local.rs +++ b/src/task_local.rs @@ -9,7 +9,7 @@ /// /// # Examples /// -/// ``` +/// ```ignore /// # /// use std::cell::Cell; /// From 08342286118893e06b863bbffd356d7c766f285e Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Mon, 14 Oct 2019 18:37:23 +0200 Subject: [PATCH 7/8] fix printing Signed-off-by: Yoshua Wuyts --- src/print.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/print.rs b/src/print.rs index 2da8e1b..f39e6e3 100644 --- a/src/print.rs +++ b/src/print.rs @@ -97,7 +97,7 @@ macro_rules! println { if let Err(e) = ::async_std::io::stdout().write_fmt(args).await { $crate::utils::panic!("failed printing to stdout: {}", e); } - $crate::utils::print!("\n").await; + $crate::print!("\n").await; } ); } From fcaa53238fdfee22427ea5f780e22e764e2181ca Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Mon, 14 Oct 2019 18:47:04 +0200 Subject: [PATCH 8/8] expand args outside async block Signed-off-by: Yoshua Wuyts --- src/print.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/print.rs b/src/print.rs index f39e6e3..71300bb 100644 --- a/src/print.rs +++ b/src/print.rs @@ -45,15 +45,15 @@ /// ``` #[macro_export] macro_rules! print { - ($($arg:tt)*) => ( - async { + ($($arg:tt)*) => ({ + let args = $crate::utils::format_args!($($arg)*); + async move { use ::async_std::prelude::*; - let args = $crate::utils::format_args!($($arg)*); if let Err(e) = ::async_std::io::stdout().write_fmt(args).await { $crate::utils::panic!("failed printing to stdout: {}", e); } } - ); + }); } /// Prints to the standard output, with a newline. @@ -90,16 +90,16 @@ macro_rules! print { #[macro_export] macro_rules! println { () => ($crate::print!("\n")); - ($($arg:tt)*) => ( - async { + ($($arg:tt)*) => ({ + let args = $crate::utils::format_args!($($arg)*); + async move { use ::async_std::prelude::*; - let args = $crate::utils::format_args!($($arg)*); if let Err(e) = ::async_std::io::stdout().write_fmt(args).await { $crate::utils::panic!("failed printing to stdout: {}", e); } $crate::print!("\n").await; } - ); + }); } /// Prints to the standard error. @@ -131,15 +131,15 @@ macro_rules! println { /// ``` #[macro_export] macro_rules! eprint { - ($($arg:tt)*) => ( - async { + ($($arg:tt)*) => ({ + let args = $crate::utils::format_args!($($arg)*); + async move { use ::async_std::prelude::*; - let args = $crate::utils::format_args!($($arg)*); if let Err(e) = ::async_std::io::stderr().write_fmt(args).await { $crate::utils::panic!("failed printing to stderr: {}", e); } } - ); + }); } /// Prints to the standard error, with a newline. @@ -172,14 +172,14 @@ macro_rules! eprint { #[macro_export] macro_rules! eprintln { () => ($crate::eprint!("\n")); - ($($arg:tt)*) => ( - async { + ($($arg:tt)*) => ({ + let args = $crate::utils::format_args!($($arg)*); + async move { use ::async_std::prelude::*; - let args = $crate::utils::format_args!($($arg)*); if let Err(e) = ::async_std::io::stderr().write_fmt(args).await { $crate::utils::panic!("failed printing to stderr: {}", e); } $crate::eprint!("\n").await; } - ); + }); }