Skip to content

Commit 951d353

Browse files
authored
Support shared futures on no_std (#2868)
1 parent bbaa0e3 commit 951d353

File tree

5 files changed

+39
-16
lines changed

5 files changed

+39
-16
lines changed

futures-util/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ Common utilities and extension traits for the futures-rs library.
1212

1313
[features]
1414
default = ["std", "async-await", "async-await-macro"]
15-
std = ["alloc", "futures-core/std", "futures-task/std", "slab"]
16-
alloc = ["futures-core/alloc", "futures-task/alloc"]
15+
std = ["alloc", "futures-core/std", "futures-task/std", "slab/std"]
16+
alloc = ["futures-core/alloc", "futures-task/alloc", "slab"]
1717
async-await = []
1818
async-await-macro = ["async-await", "futures-macro"]
1919
compat = ["std", "futures_01"]
@@ -37,12 +37,13 @@ futures-channel = { path = "../futures-channel", version = "=0.4.0-alpha.0", def
3737
futures-io = { path = "../futures-io", version = "0.3.31", default-features = false, features = ["std"], optional = true }
3838
futures-sink = { path = "../futures-sink", version = "=0.4.0-alpha.0", default-features = false, optional = true }
3939
futures-macro = { path = "../futures-macro", version = "=0.4.0-alpha.0", default-features = false, optional = true }
40-
slab = { version = "0.4.2", optional = true }
40+
slab = { version = "0.4.2", default-features = false, optional = true }
4141
memchr = { version = "2.2", optional = true }
4242
futures_01 = { version = "0.1.25", optional = true, package = "futures" }
4343
tokio-io = { version = "0.1.9", optional = true }
4444
pin-utils = "0.1.0"
4545
pin-project-lite = "0.2.6"
46+
spin = { version = "0.9.8", optional = true }
4647

4748
[dev-dependencies]
4849
futures = { path = "../futures", features = ["async-await", "thread-pool"] }

futures-util/src/future/future/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ mod remote_handle;
107107
#[cfg(feature = "std")]
108108
pub use self::remote_handle::{Remote, RemoteHandle};
109109

110-
#[cfg(feature = "std")]
110+
#[cfg(any(feature = "std", all(feature = "alloc", feature = "spin")))]
111111
mod shared;
112-
#[cfg(feature = "std")]
112+
#[cfg(any(feature = "std", all(feature = "alloc", feature = "spin")))]
113113
pub use self::shared::{Shared, WeakShared};
114114

115115
impl<T: ?Sized> FutureExt for T where T: Future {}
@@ -440,7 +440,7 @@ pub trait FutureExt: Future {
440440
/// into a cloneable future. It enables a future to be polled by multiple
441441
/// threads.
442442
///
443-
/// This method is only available when the `std` feature of this
443+
/// This method is only available when the `std` or 'spin' feature of this
444444
/// library is activated, and it is activated by default.
445445
///
446446
/// # Examples
@@ -474,7 +474,7 @@ pub trait FutureExt: Future {
474474
/// join_handle.join().unwrap();
475475
/// # });
476476
/// ```
477-
#[cfg(feature = "std")]
477+
#[cfg(any(feature = "std", all(feature = "alloc", feature = "spin")))]
478478
fn shared(self) -> Shared<Self>
479479
where
480480
Self: Sized,

futures-util/src/future/future/shared.rs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
use crate::task::{waker_ref, ArcWake};
2+
use alloc::sync::{Arc, Weak};
3+
use core::cell::UnsafeCell;
4+
use core::fmt;
5+
use core::hash::Hasher;
6+
use core::pin::Pin;
7+
use core::ptr;
8+
use core::sync::atomic::AtomicUsize;
9+
use core::sync::atomic::Ordering::{Acquire, SeqCst};
210
use futures_core::future::{FusedFuture, Future};
311
use futures_core::task::{Context, Poll, Waker};
412
use slab::Slab;
5-
use std::cell::UnsafeCell;
6-
use std::fmt;
7-
use std::hash::Hasher;
8-
use std::pin::Pin;
9-
use std::ptr;
10-
use std::sync::atomic::AtomicUsize;
11-
use std::sync::atomic::Ordering::{Acquire, SeqCst};
12-
use std::sync::{Arc, Mutex, Weak};
13+
14+
#[cfg(feature = "std")]
15+
type Mutex<T> = std::sync::Mutex<T>;
16+
#[cfg(not(feature = "std"))]
17+
type Mutex<T> = spin::Mutex<T>;
1318

1419
/// Future for the [`shared`](super::FutureExt::shared) method.
1520
#[must_use = "futures do nothing unless you `.await` or poll them"]
@@ -204,7 +209,10 @@ where
204209
{
205210
/// Registers the current task to receive a wakeup when we are awoken.
206211
fn record_waker(&self, waker_key: &mut usize, cx: &mut Context<'_>) {
212+
#[cfg(feature = "std")]
207213
let mut wakers_guard = self.notifier.wakers.lock().unwrap();
214+
#[cfg(not(feature = "std"))]
215+
let mut wakers_guard = self.notifier.wakers.lock();
208216

209217
let wakers_mut = wakers_guard.as_mut();
210218

@@ -345,7 +353,11 @@ where
345353
inner.notifier.state.store(COMPLETE, SeqCst);
346354

347355
// Wake all tasks and drop the slab
356+
#[cfg(feature = "std")]
348357
let mut wakers_guard = inner.notifier.wakers.lock().unwrap();
358+
#[cfg(not(feature = "std"))]
359+
let mut wakers_guard = inner.notifier.wakers.lock();
360+
349361
let mut wakers = wakers_guard.take().unwrap();
350362
for waker in wakers.drain().flatten() {
351363
waker.wake();
@@ -375,19 +387,28 @@ where
375387
fn drop(&mut self) {
376388
if self.waker_key != NULL_WAKER_KEY {
377389
if let Some(ref inner) = self.inner {
390+
#[cfg(feature = "std")]
378391
if let Ok(mut wakers) = inner.notifier.wakers.lock() {
379392
if let Some(wakers) = wakers.as_mut() {
380393
wakers.remove(self.waker_key);
381394
}
382395
}
396+
#[cfg(not(feature = "std"))]
397+
if let Some(wakers) = inner.notifier.wakers.lock().as_mut() {
398+
wakers.remove(self.waker_key);
399+
}
383400
}
384401
}
385402
}
386403
}
387404

388405
impl ArcWake for Notifier {
389406
fn wake_by_ref(arc_self: &Arc<Self>) {
407+
#[cfg(feature = "std")]
390408
let wakers = &mut *arc_self.wakers.lock().unwrap();
409+
#[cfg(not(feature = "std"))]
410+
let wakers = &mut *arc_self.wakers.lock();
411+
391412
if let Some(wakers) = wakers.as_mut() {
392413
for (_key, opt_waker) in wakers {
393414
if let Some(waker) = opt_waker.take() {

futures-util/src/future/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub use self::future::CatchUnwind;
3535
#[cfg(feature = "std")]
3636
pub use self::future::{Remote, RemoteHandle};
3737

38-
#[cfg(feature = "std")]
38+
#[cfg(any(feature = "std", all(feature = "alloc", feature = "spin")))]
3939
pub use self::future::{Shared, WeakShared};
4040

4141
mod try_future;

futures/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ compat = ["std", "futures-util/compat"]
4040
io-compat = ["compat", "futures-util/io-compat"]
4141
executor = ["std", "futures-executor/std"]
4242
thread-pool = ["executor", "futures-executor/thread-pool"]
43+
spin = ["futures-util/spin"]
4344

4445
# Unstable features
4546
# These features are outside of the normal semver guarantees and require the

0 commit comments

Comments
 (0)