From a195a4e0f7015d3c263a04bbd503585b9e1c5b0f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 19 Aug 2016 18:12:19 -0700 Subject: [PATCH] Add an on-by-default use_std feature to `futures` This commit adds a new Cargo feature to the `futures` crate, `use_std`, which is enabled by default. The `futures` crate is now tagged as `#![no_std]` with extra support like tasks, oneshot, and channels coming in through the `use_std` feature. Most crates will likely depend on the `use_std` version, but that shouldn't preclude those that don't want to! Closes #60 --- .travis.yml | 2 + Cargo.toml | 8 +++- appveyor.yml | 2 + src/chain.rs | 2 +- src/collect.rs | 2 + src/empty.rs | 2 +- src/executor.rs | 1 + src/failed.rs | 2 +- src/finished.rs | 2 +- src/forget.rs | 2 + src/impls.rs | 19 --------- src/join.rs | 2 +- src/lazy.rs | 2 +- src/lib.rs | 92 +++++++++++++++++++++++++++++------------- src/lock.rs | 8 ++-- src/select_all.rs | 1 + src/slot.rs | 1 + src/stream/buffered.rs | 2 + src/stream/collect.rs | 2 + src/stream/fold.rs | 2 +- src/stream/impls.rs | 20 --------- src/stream/mod.rs | 47 +++++++++++++++------ src/task.rs | 2 + 23 files changed, 132 insertions(+), 93 deletions(-) delete mode 100644 src/impls.rs delete mode 100644 src/stream/impls.rs diff --git a/.travis.yml b/.travis.yml index 28283fb87a1..e12427c4e56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,8 @@ sudo: false before_script: - pip install git+https://github.com/euclio/travis-cargo@kcov --user && export PATH=$HOME/.local/bin:$PATH script: + - cargo build + - cargo build --no-default-features - cargo test - cargo test --manifest-path futures-io/Cargo.toml - cargo test --manifest-path futures-iobuf/Cargo.toml diff --git a/Cargo.toml b/Cargo.toml index c3a20022b70..75be9665098 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,5 +30,9 @@ members = [ ] [dependencies] -log = "0.3" -scoped-tls = "0.1" +log = { version = "0.3", default-features = true } +scoped-tls = { version = "0.1", optional = true } + +[features] +use_std = ["scoped-tls"] +default = ["use_std"] diff --git a/appveyor.yml b/appveyor.yml index 0e0e085da87..7c3c72b1136 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,6 +11,8 @@ install: build: false test_script: + - cargo build + - cargo build --no-default-features - cargo test - cargo test --manifest-path futures-io/Cargo.toml - cargo test --manifest-path futures-iobuf/Cargo.toml diff --git a/src/chain.rs b/src/chain.rs index aa47e4567f0..6e685b2210e 100644 --- a/src/chain.rs +++ b/src/chain.rs @@ -1,4 +1,4 @@ -use std::mem; +use core::mem; use {Future, Poll}; diff --git a/src/collect.rs b/src/collect.rs index c1f82bc6265..4eb8984d1e3 100644 --- a/src/collect.rs +++ b/src/collect.rs @@ -1,3 +1,5 @@ +use std::prelude::v1::*; + use std::mem; use {Future, IntoFuture, Poll}; diff --git a/src/empty.rs b/src/empty.rs index da77bad4eef..3a420945885 100644 --- a/src/empty.rs +++ b/src/empty.rs @@ -1,4 +1,4 @@ -use std::marker; +use core::marker; use {Future, Poll}; diff --git a/src/executor.rs b/src/executor.rs index 945a78b6de8..b47919f1bb0 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -4,6 +4,7 @@ //! is not currently used much by futures beyond `DEFAULT`. use std::cell::{Cell, RefCell}; +use std::prelude::v1::*; use std::sync::Arc; /// Encapsulation of a value which has the ability to execute arbitrary code. diff --git a/src/failed.rs b/src/failed.rs index 3df08cd1a9d..e17541f961e 100644 --- a/src/failed.rs +++ b/src/failed.rs @@ -1,4 +1,4 @@ -use std::marker; +use core::marker; use {Future, Poll}; diff --git a/src/finished.rs b/src/finished.rs index 2fd79de6319..13c58d1efe3 100644 --- a/src/finished.rs +++ b/src/finished.rs @@ -1,4 +1,4 @@ -use std::marker; +use core::marker; use {Future, Poll}; diff --git a/src/forget.rs b/src/forget.rs index 792b7695a4d..248f6a7629d 100644 --- a/src/forget.rs +++ b/src/forget.rs @@ -1,3 +1,5 @@ +use std::prelude::v1::*; + use {Future, Poll}; use task::Task; diff --git a/src/impls.rs b/src/impls.rs deleted file mode 100644 index b1f5b5f6ec0..00000000000 --- a/src/impls.rs +++ /dev/null @@ -1,19 +0,0 @@ -use {Future, Poll}; - -impl Future for Box { - type Item = F::Item; - type Error = F::Error; - - fn poll(&mut self) -> Poll { - (**self).poll() - } -} - -impl<'a, F: ?Sized + Future> Future for &'a mut F { - type Item = F::Item; - type Error = F::Error; - - fn poll(&mut self) -> Poll { - (**self).poll() - } -} diff --git a/src/join.rs b/src/join.rs index d816824a718..811465e0043 100644 --- a/src/join.rs +++ b/src/join.rs @@ -1,6 +1,6 @@ #![allow(non_snake_case)] -use std::mem; +use core::mem; use {Future, Poll, IntoFuture}; diff --git a/src/lazy.rs b/src/lazy.rs index 388e149bb0f..1d7319d7eec 100644 --- a/src/lazy.rs +++ b/src/lazy.rs @@ -1,4 +1,4 @@ -use std::mem; +use core::mem; use {Future, IntoFuture, Poll}; diff --git a/src/lib.rs b/src/lib.rs index a9e4ec38175..8bf045155e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -149,42 +149,41 @@ //! //! [README]: https://github.com/alexcrichton/futures-rs#futures-rs +#![no_std] #![deny(missing_docs)] -use std::thread; - #[macro_use] -extern crate log; +#[cfg(feature = "use_std")] +extern crate scoped_tls; +#[macro_use] +#[cfg(feature = "use_std")] +extern crate std; #[macro_use] -extern crate scoped_tls; +extern crate log; -// internal utilities -mod lock; -mod slot; +macro_rules! if_std { + ($($i:item)*) => ($( + #[cfg(feature = "use_std")] + $i + )*) +} #[macro_use] mod poll; pub use poll::Poll; -pub mod task; -pub mod executor; - // Primitive futures -mod collect; mod done; mod empty; mod failed; mod finished; mod lazy; -mod oneshot; -pub use collect::{collect, Collect}; pub use done::{done, Done}; pub use empty::{empty, Empty}; pub use failed::{failed, Failed}; pub use finished::{finished, Finished}; pub use lazy::{lazy, Lazy}; -pub use oneshot::{oneshot, Oneshot, Complete, Canceled}; // combinators mod and_then; @@ -195,7 +194,6 @@ mod map; mod map_err; mod or_else; mod select; -mod select_all; mod then; pub use and_then::AndThen; pub use flatten::Flatten; @@ -205,16 +203,49 @@ pub use map::Map; pub use map_err::MapErr; pub use or_else::OrElse; pub use select::{Select, SelectNext}; -pub use select_all::{SelectAll, SelectAllNext, select_all}; pub use then::Then; +if_std! { + mod lock; + mod slot; + pub mod task; + pub mod executor; + + mod collect; + mod oneshot; + mod select_all; + pub use collect::{collect, Collect}; + pub use oneshot::{oneshot, Oneshot, Complete, Canceled}; + pub use select_all::{SelectAll, SelectAllNext, select_all}; + + mod forget; + + struct ThreadNotify(std::thread::Thread); + + impl task::Notify for ThreadNotify { + fn notify(&self) { + self.0.unpark(); + } + } + + /// A type alias for `Box` + pub type BoxFuture = std::boxed::Box + Send>; + + impl Future for std::boxed::Box { + type Item = F::Item; + type Error = F::Error; + + fn poll(&mut self) -> Poll { + (**self).poll() + } + } +} + // streams pub mod stream; // impl details mod chain; -mod impls; -mod forget; /// Trait for types which are a placeholder of a value that will become /// available at possible some later point in time. @@ -351,9 +382,12 @@ pub trait Future { /// /// This function does not attempt to catch panics. If the `poll` function /// panics, panics will be propagated to the caller. + #[cfg(feature = "use_std")] fn await(mut self) -> Result where Self: Sized { + use std::thread; + let notify = ThreadNotify(thread::current()); let mut task = task::Task::new_notify(notify); loop { @@ -380,10 +414,11 @@ pub trait Future { /// /// let a: BoxFuture = done(Ok(1)).boxed(); /// ``` + #[cfg(feature = "use_std")] fn boxed(self) -> BoxFuture where Self: Sized + Send + 'static { - Box::new(self) + ::std::boxed::Box::new(self) } /// Map this future's result to a different type, returning a new future of @@ -782,13 +817,20 @@ pub trait Future { /// `futures-mio` crate provides a `Loop::run` method which pins the future /// to the stack frame of that functionc all, allowing it to have a /// non-`'static` lifetime. + #[cfg(feature = "use_std")] fn forget(self) where Self: Sized + Send + 'static { forget::forget(self); } } -/// A type alias for `Box` -pub type BoxFuture = Box + Send>; +impl<'a, F: ?Sized + Future> Future for &'a mut F { + type Item = F::Item; + type Error = F::Error; + + fn poll(&mut self) -> Poll { + (**self).poll() + } +} // Just a helper function to ensure the futures we're returning all have the // right implementations. @@ -834,11 +876,3 @@ impl IntoFuture for Result { done(self) } } - -struct ThreadNotify(thread::Thread); - -impl task::Notify for ThreadNotify { - fn notify(&self) { - self.0.unpark(); - } -} diff --git a/src/lock.rs b/src/lock.rs index 7ab746f558b..f9bcfc40895 100644 --- a/src/lock.rs +++ b/src/lock.rs @@ -4,10 +4,10 @@ //! thing that ever blocks, so this is assisted with a fast user-space //! implementation of a lock that can only have a `try_lock` operation. -use std::cell::UnsafeCell; -use std::ops::{Deref, DerefMut}; -use std::sync::atomic::Ordering::{Acquire, Release}; -use std::sync::atomic::AtomicBool; +use core::cell::UnsafeCell; +use core::ops::{Deref, DerefMut}; +use core::sync::atomic::Ordering::{Acquire, Release}; +use core::sync::atomic::AtomicBool; /// A "mutex" around a value, similar to `std::sync::Mutex`. /// diff --git a/src/select_all.rs b/src/select_all.rs index 83d70167792..03fe074a4b4 100644 --- a/src/select_all.rs +++ b/src/select_all.rs @@ -1,4 +1,5 @@ use std::mem; +use std::prelude::v1::*; use {Future, IntoFuture, Poll}; diff --git a/src/slot.rs b/src/slot.rs index e3203bb40cd..d802c98764a 100644 --- a/src/slot.rs +++ b/src/slot.rs @@ -7,6 +7,7 @@ #![allow(dead_code)] // imported in a few places +use std::prelude::v1::*; use std::sync::atomic::{AtomicUsize, Ordering}; use lock::Lock; diff --git a/src/stream/buffered.rs b/src/stream/buffered.rs index 6aa1ab72770..571e1f46d10 100644 --- a/src/stream/buffered.rs +++ b/src/stream/buffered.rs @@ -1,3 +1,5 @@ +use std::prelude::v1::*; + use std::mem; use {IntoFuture, Poll, Future}; diff --git a/src/stream/collect.rs b/src/stream/collect.rs index 7e7396bfcac..550caca3af2 100644 --- a/src/stream/collect.rs +++ b/src/stream/collect.rs @@ -1,3 +1,5 @@ +use std::prelude::v1::*; + use std::mem; use {Future, Poll}; diff --git a/src/stream/fold.rs b/src/stream/fold.rs index ddcd9ad6ade..899a001e93b 100644 --- a/src/stream/fold.rs +++ b/src/stream/fold.rs @@ -1,4 +1,4 @@ -use std::mem; +use core::mem; use {Future, Poll, IntoFuture}; use stream::Stream; diff --git a/src/stream/impls.rs b/src/stream/impls.rs deleted file mode 100644 index d061707bf44..00000000000 --- a/src/stream/impls.rs +++ /dev/null @@ -1,20 +0,0 @@ -use Poll; -use stream::Stream; - -impl Stream for Box { - type Item = S::Item; - type Error = S::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - (**self).poll() - } -} - -impl<'a, S: ?Sized + Stream> Stream for &'a mut S { - type Item = S::Item; - type Error = S::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - (**self).poll() - } -} diff --git a/src/stream/mod.rs b/src/stream/mod.rs index aab460a30ce..0946254d241 100755 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -13,15 +13,10 @@ use {IntoFuture, Poll}; -mod channel; mod iter; -pub use self::channel::{channel, Sender, Receiver}; pub use self::iter::{iter, IterStream}; mod and_then; -mod await; -mod buffered; -mod collect; mod filter; mod filter_map; mod flatten; @@ -40,9 +35,6 @@ mod take; mod then; mod zip; pub use self::and_then::AndThen; -pub use self::await::Await; -pub use self::buffered::Buffered; -pub use self::collect::Collect; pub use self::filter::Filter; pub use self::filter_map::FilterMap; pub use self::flatten::Flatten; @@ -61,7 +53,28 @@ pub use self::then::Then; pub use self::zip::Zip; pub use self::peek::Peekable; -mod impls; +if_std! { + mod await; + mod buffered; + mod channel; + mod collect; + pub use self::await::Await; + pub use self::buffered::Buffered; + pub use self::channel::{channel, Sender, Receiver}; + pub use self::collect::Collect; + + /// A type alias for `Box` + pub type BoxStream = ::std::boxed::Box + Send>; + + impl Stream for ::std::boxed::Box { + type Item = S::Item; + type Error = S::Error; + + fn poll(&mut self) -> Poll, Self::Error> { + (**self).poll() + } + } +} /// A stream of values, not all of which have been produced yet. /// @@ -144,6 +157,7 @@ pub trait Stream { /// /// The returned iterator does not attempt to catch panics. If the `poll` /// function panics, panics will be propagated to the caller of `next`. + #[cfg(feature = "use_std")] fn await(self) -> Await where Self: Sized { @@ -166,10 +180,11 @@ pub trait Stream { /// let (_tx, rx) = channel(); /// let a: BoxStream = rx.boxed(); /// ``` + #[cfg(feature = "use_std")] fn boxed(self) -> BoxStream where Self: Sized + Send + 'static, { - Box::new(self) + ::std::boxed::Box::new(self) } /// Converts this stream into a `Future`. @@ -458,6 +473,7 @@ pub trait Stream { /// let mut result = rx.collect(); /// assert_eq!(result.poll(), Poll::Ok(vec![5, 4, 3, 2, 1])); /// ``` + #[cfg(feature = "use_std")] fn collect(self) -> Collect where Self: Sized { @@ -621,6 +637,7 @@ pub trait Stream { /// /// The returned stream will be a stream of each future's result, with /// errors passed through whenever they occur. + #[cfg(feature = "use_std")] fn buffered(self, amt: usize) -> Buffered where Self::Item: IntoFuture::Error>, Self: Sized @@ -662,5 +679,11 @@ pub trait Stream { } } -/// A type alias for `Box` -pub type BoxStream = Box + Send>; +impl<'a, S: ?Sized + Stream> Stream for &'a mut S { + type Item = S::Item; + type Error = S::Error; + + fn poll(&mut self) -> Poll, Self::Error> { + (**self).poll() + } +} diff --git a/src/task.rs b/src/task.rs index 8d7d8664ffb..be0d9d9e385 100644 --- a/src/task.rs +++ b/src/task.rs @@ -28,6 +28,8 @@ //! care because if used improperly it can easily cause a panic. For more //! information, see the documentation on the function itself. +use std::prelude::v1::*; + use std::cell::{UnsafeCell, Cell, RefCell}; use std::marker; use std::panic;