diff --git a/futures-util/Cargo.toml b/futures-util/Cargo.toml index 68dbd86b7..f4d5466f1 100644 --- a/futures-util/Cargo.toml +++ b/futures-util/Cargo.toml @@ -12,8 +12,8 @@ Common utilities and extension traits for the futures-rs library. [features] default = ["std", "async-await", "async-await-macro"] -std = ["alloc", "futures-core/std", "futures-task/std", "slab"] -alloc = ["futures-core/alloc", "futures-task/alloc"] +std = ["alloc", "futures-core/std", "futures-task/std", "slab/std"] +alloc = ["futures-core/alloc", "futures-task/alloc", "slab"] async-await = [] async-await-macro = ["async-await", "futures-macro"] compat = ["std", "futures_01"] @@ -37,13 +37,16 @@ futures-channel = { path = "../futures-channel", version = "=0.4.0-alpha.0", def futures-io = { path = "../futures-io", version = "0.3.30", default-features = false, features = ["std"], optional = true } futures-sink = { path = "../futures-sink", version = "=0.4.0-alpha.0", default-features = false, optional = true } futures-macro = { path = "../futures-macro", version = "=0.4.0-alpha.0", default-features = false, optional = true } -slab = { version = "0.4.2", optional = true } +slab = { version = "0.4.2", default-features = false, optional = true } memchr = { version = "2.2", optional = true } futures_01 = { version = "0.1.25", optional = true, package = "futures" } tokio-io = { version = "0.1.9", optional = true } pin-utils = "0.1.0" pin-project-lite = "0.2.6" +[target.'cfg(target_has_atomic = "8")'.dependencies] +spin = "0.9.8" + [dev-dependencies] futures = { path = "../futures", features = ["async-await", "thread-pool"] } futures-test = { path = "../futures-test" } diff --git a/futures-util/src/future/future/mod.rs b/futures-util/src/future/future/mod.rs index cf6bd8680..ee757eb0a 100644 --- a/futures-util/src/future/future/mod.rs +++ b/futures-util/src/future/future/mod.rs @@ -107,9 +107,9 @@ mod remote_handle; #[cfg(feature = "std")] pub use self::remote_handle::{Remote, RemoteHandle}; -#[cfg(feature = "std")] +#[cfg(all(feature = "alloc", target_has_atomic = "8"))] mod shared; -#[cfg(feature = "std")] +#[cfg(all(feature = "alloc", target_has_atomic = "8"))] pub use self::shared::{Shared, WeakShared}; impl FutureExt for T where T: Future {} @@ -474,7 +474,7 @@ pub trait FutureExt: Future { /// join_handle.join().unwrap(); /// # }); /// ``` - #[cfg(feature = "std")] + #[cfg(all(feature = "alloc", target_has_atomic = "8"))] fn shared(self) -> Shared where Self: Sized, diff --git a/futures-util/src/future/future/shared.rs b/futures-util/src/future/future/shared.rs index b4d9bff89..f26b20d92 100644 --- a/futures-util/src/future/future/shared.rs +++ b/futures-util/src/future/future/shared.rs @@ -1,15 +1,20 @@ use crate::task::{waker_ref, ArcWake}; +use alloc::sync::{Arc, Weak}; +use core::cell::UnsafeCell; +use core::fmt; +use core::hash::Hasher; +use core::pin::Pin; +use core::ptr; +use core::sync::atomic::AtomicUsize; +use core::sync::atomic::Ordering::{Acquire, SeqCst}; use futures_core::future::{FusedFuture, Future}; use futures_core::task::{Context, Poll, Waker}; use slab::Slab; -use std::cell::UnsafeCell; -use std::fmt; -use std::hash::Hasher; -use std::pin::Pin; -use std::ptr; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering::{Acquire, SeqCst}; -use std::sync::{Arc, Mutex, Weak}; + +#[cfg(feature = "std")] +type Mutex = std::sync::Mutex; +#[cfg(not(feature = "std"))] +type Mutex = spin::Mutex; /// Future for the [`shared`](super::FutureExt::shared) method. #[must_use = "futures do nothing unless you `.await` or poll them"] @@ -204,7 +209,10 @@ where { /// Registers the current task to receive a wakeup when we are awoken. fn record_waker(&self, waker_key: &mut usize, cx: &mut Context<'_>) { + #[cfg(feature = "std")] let mut wakers_guard = self.notifier.wakers.lock().unwrap(); + #[cfg(not(feature = "std"))] + let mut wakers_guard = self.notifier.wakers.lock(); let wakers_mut = wakers_guard.as_mut(); @@ -345,7 +353,11 @@ where inner.notifier.state.store(COMPLETE, SeqCst); // Wake all tasks and drop the slab + #[cfg(feature = "std")] let mut wakers_guard = inner.notifier.wakers.lock().unwrap(); + #[cfg(not(feature = "std"))] + let mut wakers_guard = inner.notifier.wakers.lock(); + let mut wakers = wakers_guard.take().unwrap(); for waker in wakers.drain().flatten() { waker.wake(); @@ -375,11 +387,16 @@ where fn drop(&mut self) { if self.waker_key != NULL_WAKER_KEY { if let Some(ref inner) = self.inner { + #[cfg(feature = "std")] if let Ok(mut wakers) = inner.notifier.wakers.lock() { if let Some(wakers) = wakers.as_mut() { wakers.remove(self.waker_key); } } + #[cfg(not(feature = "std"))] + if let Some(wakers) = inner.notifier.wakers.lock().as_mut() { + wakers.remove(self.waker_key); + } } } } @@ -387,7 +404,11 @@ where impl ArcWake for Notifier { fn wake_by_ref(arc_self: &Arc) { + #[cfg(feature = "std")] let wakers = &mut *arc_self.wakers.lock().unwrap(); + #[cfg(not(feature = "std"))] + let wakers = &mut *arc_self.wakers.lock(); + if let Some(wakers) = wakers.as_mut() { for (_key, opt_waker) in wakers { if let Some(waker) = opt_waker.take() { diff --git a/futures-util/src/future/mod.rs b/futures-util/src/future/mod.rs index 1280ce986..e3ca85f6f 100644 --- a/futures-util/src/future/mod.rs +++ b/futures-util/src/future/mod.rs @@ -35,7 +35,7 @@ pub use self::future::CatchUnwind; #[cfg(feature = "std")] pub use self::future::{Remote, RemoteHandle}; -#[cfg(feature = "std")] +#[cfg(all(feature = "alloc", target_has_atomic = "8"))] pub use self::future::{Shared, WeakShared}; mod try_future;