Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Spawn/AtomicWaker/ArcWake/FutureObj to futures-task #1925

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -7,6 +7,7 @@ members = [
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"futures-util",
"futures-test",
]
3 changes: 0 additions & 3 deletions futures-core/src/future/mod.rs → futures-core/src/future.rs
Expand Up @@ -6,9 +6,6 @@ use core::task::{Context, Poll};

pub use core::future::Future;

mod future_obj;
pub use self::future_obj::{FutureObj, LocalFutureObj, UnsafeFutureObj};

/// An owned dynamically typed [`Future`] for use in cases where you can't
/// statically type your result or need to add some indirection.
#[cfg(feature = "alloc")]
Expand Down
4 changes: 2 additions & 2 deletions futures-core/src/task/__internal/atomic_waker.rs
@@ -1,8 +1,8 @@
use core::fmt;
use core::cell::UnsafeCell;
use core::fmt;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering::{Acquire, Release, AcqRel};
use crate::task::Waker;
use core::task::Waker;

/// A synchronization primitive for task wakeup.
///
Expand Down
3 changes: 0 additions & 3 deletions futures-core/src/task/mod.rs
Expand Up @@ -3,9 +3,6 @@
#[macro_use]
mod poll;

mod spawn;
pub use self::spawn::{Spawn, LocalSpawn, SpawnError};

#[doc(hidden)]
pub mod __internal;

Expand Down
3 changes: 2 additions & 1 deletion futures-executor/Cargo.toml
Expand Up @@ -16,11 +16,12 @@ name = "futures_executor"

[features]
default = ["std"]
std = ["futures-core-preview/std", "futures-util-preview/std"]
std = ["futures-core-preview/std", "futures-task-preview/std", "futures-util-preview/std"]
thread-pool = ["std", "num_cpus"]

[dependencies]
futures-core-preview = { path = "../futures-core", version = "=0.3.0-alpha.19", default-features = false }
futures-task-preview = { path = "../futures-task", version = "=0.3.0-alpha.19", default-features = false }
futures-util-preview = { path = "../futures-util", version = "=0.3.0-alpha.19", default-features = false }
num_cpus = { version = "1.8.0", optional = true }

Expand Down
15 changes: 8 additions & 7 deletions futures-executor/src/local_pool.rs
@@ -1,8 +1,9 @@
use crate::enter;
use futures_core::future::{Future, FutureObj, LocalFutureObj};
use futures_core::stream::{Stream};
use futures_core::task::{Context, Poll, Spawn, LocalSpawn, SpawnError};
use futures_util::task::{waker_ref, ArcWake};
use futures_core::future::Future;
use futures_core::stream::Stream;
use futures_core::task::{Context, Poll};
use futures_task::{FutureObj, LocalFutureObj, Spawn, LocalSpawn, SpawnError};
use futures_task::{waker_ref, ArcWake};
use futures_util::stream::FuturesUnordered;
use futures_util::stream::StreamExt;
use futures_util::pin_mut;
Expand All @@ -19,18 +20,18 @@ use std::thread::{self, Thread};
/// little work in between I/O actions.
///
/// To get a handle to the pool that implements
/// [`Spawn`](futures_core::task::Spawn), use the
/// [`Spawn`](futures_task::Spawn), use the
/// [`spawner()`](LocalPool::spawner) method. Because the executor is
/// single-threaded, it supports a special form of task spawning for non-`Send`
/// futures, via [`spawn_local_obj`](futures_core::task::LocalSpawn::spawn_local_obj).
/// futures, via [`spawn_local_obj`](futures_task::LocalSpawn::spawn_local_obj).
#[derive(Debug)]
pub struct LocalPool {
pool: FuturesUnordered<LocalFutureObj<'static, ()>>,
incoming: Rc<Incoming>,
}

/// A handle to a [`LocalPool`](LocalPool) that implements
/// [`Spawn`](futures_core::task::Spawn).
/// [`Spawn`](futures_task::Spawn).
#[derive(Clone, Debug)]
pub struct LocalSpawner {
incoming: Weak<Incoming>,
Expand Down
7 changes: 4 additions & 3 deletions futures-executor/src/thread_pool.rs
@@ -1,9 +1,10 @@
use crate::enter;
use crate::unpark_mutex::UnparkMutex;
use futures_core::future::{Future, FutureObj};
use futures_core::task::{Context, Poll, Spawn, SpawnError};
use futures_core::future::Future;
use futures_core::task::{Context, Poll};
use futures_task::{FutureObj, Spawn, SpawnError};
use futures_task::{ArcWake, waker_ref};
use futures_util::future::FutureExt;
use futures_util::task::{ArcWake, waker_ref};
use std::cmp;
use std::fmt;
use std::io;
Expand Down
31 changes: 31 additions & 0 deletions futures-task/Cargo.toml
@@ -0,0 +1,31 @@
[package]
name = "futures-task-preview"
edition = "2018"
version = "0.3.0-alpha.19"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang-nursery/futures-rs"
homepage = "https://rust-lang-nursery.github.io/futures-rs"
documentation = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.18/futures_core"
description = """
Tools for working with tasks.
"""

[lib]
name = "futures_task"

[features]
default = ["std"]
std = ["alloc"]
alloc = []

# Unstable features
# These features are outside of the normal semver guarantees and require the
# `unstable` feature as an explicit opt-in to unstable API.
unstable = []
cfg-target-has-atomic = []

[dependencies]

[dev-dependencies]
futures-preview = { path = "../futures", version = "=0.3.0-alpha.19" }
Expand Up @@ -9,12 +9,12 @@ use alloc::sync::Arc;
///
/// Currently, there are two ways to convert `ArcWake` into [`Waker`]:
///
/// * [`waker`](crate::task::waker()) converts `Arc<impl ArcWake>` into [`Waker`].
/// * [`waker_ref`](crate::task::waker_ref()) converts `&Arc<impl ArcWake>` into [`WakerRef`] that
/// * [`waker`](super::waker()) converts `Arc<impl ArcWake>` into [`Waker`].
/// * [`waker_ref`](super::waker_ref()) converts `&Arc<impl ArcWake>` into [`WakerRef`] that
/// provides access to a [`&Waker`][`Waker`].
///
/// [`Waker`]: std::task::Waker
/// [`WakerRef`]: crate::task::WakerRef
/// [`WakerRef`]: super::WakerRef
// Note: Send + Sync required because `Arc<T>` doesn't automatically imply
// those bounds, but `Waker` implements them.
pub trait ArcWake: Send + Sync {
Expand Down
Expand Up @@ -104,8 +104,7 @@ impl<T> Drop for LocalFutureObj<'_, T> {
/// contexts.
///
/// You should generally not need to use this type outside of `no_std` or when
/// implementing `Spawn`, consider using [`BoxFuture`](crate::future::BoxFuture)
/// instead.
/// implementing `Spawn`, consider using `BoxFuture` instead.
pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>);

impl<T> Unpin for FutureObj<'_, T> {}
Expand Down
57 changes: 57 additions & 0 deletions futures-task/src/lib.rs
@@ -0,0 +1,57 @@
//! Tools for working with tasks.

#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))]

#![cfg_attr(not(feature = "std"), no_std)]

#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
// It cannot be included in the published code because this lints have false positives in the minimum required version.
#![cfg_attr(test, warn(single_use_lifetimes))]
#![warn(clippy::all)]

#![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))]

#![doc(html_root_url = "https://docs.rs/futures-task-preview/0.3.0-alpha.19")]

#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "unstable")))]
compile_error!("The `cfg-target-has-atomic` feature requires the `unstable` feature as an explicit opt-in to unstable features");

#[cfg(feature = "alloc")]
extern crate alloc;

macro_rules! cfg_target_has_atomic {
($($item:item)*) => {$(
#[cfg_attr(feature = "cfg-target-has-atomic", cfg(target_has_atomic = "ptr"))]
$item
)*};
}

mod spawn;
pub use crate::spawn::{Spawn, SpawnError, LocalSpawn};

cfg_target_has_atomic! {
#[cfg(feature = "alloc")]
mod arc_wake;
#[cfg(feature = "alloc")]
pub use crate::arc_wake::ArcWake;

#[cfg(feature = "alloc")]
mod waker;
#[cfg(feature = "alloc")]
pub use crate::waker::waker;

#[cfg(feature = "alloc")]
mod waker_ref;
#[cfg(feature = "alloc")]
pub use crate::waker_ref::{waker_ref, WakerRef};
}

mod future_obj;
pub use crate::future_obj::{FutureObj, LocalFutureObj, UnsafeFutureObj};

mod noop_waker;
pub use crate::noop_waker::noop_waker;
#[cfg(feature = "std")]
pub use crate::noop_waker::noop_waker_ref;

pub use core::task::{Context, Poll, Waker, RawWaker, RawWakerVTable};
@@ -1,5 +1,6 @@
//! Utilities for creating zero-cost wakers that don't do anything.
use futures_core::task::{RawWaker, RawWakerVTable, Waker};

use core::task::{RawWaker, RawWakerVTable, Waker};
use core::ptr::null;
#[cfg(feature = "std")]
use core::cell::UnsafeCell;
Expand Down
26 changes: 9 additions & 17 deletions futures-core/src/task/spawn.rs → futures-task/src/spawn.rs
@@ -1,4 +1,4 @@
use crate::future::{FutureObj, LocalFutureObj};
use crate::{FutureObj, LocalFutureObj};
use core::fmt;

/// The `Spawn` trait allows for pushing futures onto an executor that will
Expand All @@ -12,8 +12,7 @@ pub trait Spawn {
/// represent relatively rare scenarios, such as the executor
/// having been shut down so that it is no longer able to accept
/// tasks.
fn spawn_obj(&mut self, future: FutureObj<'static, ()>)
-> Result<(), SpawnError>;
fn spawn_obj(&mut self, future: FutureObj<'static, ()>) -> Result<(), SpawnError>;

/// Determines whether the executor is able to spawn new tasks.
///
Expand All @@ -38,8 +37,7 @@ pub trait LocalSpawn {
/// represent relatively rare scenarios, such as the executor
/// having been shut down so that it is no longer able to accept
/// tasks.
fn spawn_local_obj(&mut self, future: LocalFutureObj<'static, ()>)
-> Result<(), SpawnError>;
fn spawn_local_obj(&mut self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError>;

/// Determines whether the executor is able to spawn new tasks.
///
Expand All @@ -60,9 +58,7 @@ pub struct SpawnError {

impl fmt::Debug for SpawnError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("SpawnError")
.field(&"shutdown")
.finish()
f.debug_tuple("SpawnError").field(&"shutdown").finish()
}
}

Expand All @@ -88,8 +84,7 @@ impl SpawnError {
}

impl<Sp: ?Sized + Spawn> Spawn for &mut Sp {
fn spawn_obj(&mut self, future: FutureObj<'static, ()>)
-> Result<(), SpawnError> {
fn spawn_obj(&mut self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> {
Sp::spawn_obj(self, future)
}

Expand All @@ -99,8 +94,7 @@ impl<Sp: ?Sized + Spawn> Spawn for &mut Sp {
}

impl<Sp: ?Sized + LocalSpawn> LocalSpawn for &mut Sp {
fn spawn_local_obj(&mut self, future: LocalFutureObj<'static, ()>)
-> Result<(), SpawnError> {
fn spawn_local_obj(&mut self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> {
Sp::spawn_local_obj(self, future)
}

Expand All @@ -111,12 +105,11 @@ impl<Sp: ?Sized + LocalSpawn> LocalSpawn for &mut Sp {

#[cfg(feature = "alloc")]
mod if_alloc {
use alloc::boxed::Box;
use super::*;
use alloc::boxed::Box;

impl<Sp: ?Sized + Spawn> Spawn for Box<Sp> {
fn spawn_obj(&mut self, future: FutureObj<'static, ()>)
-> Result<(), SpawnError> {
fn spawn_obj(&mut self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> {
(**self).spawn_obj(future)
}

Expand All @@ -126,8 +119,7 @@ mod if_alloc {
}

impl<Sp: ?Sized + LocalSpawn> LocalSpawn for Box<Sp> {
fn spawn_local_obj(&mut self, future: LocalFutureObj<'static, ()>)
-> Result<(), SpawnError> {
fn spawn_local_obj(&mut self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> {
(**self).spawn_local_obj(future)
}

Expand Down
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion futures-test/Cargo.toml
Expand Up @@ -16,6 +16,7 @@ name = "futures_test"

[dependencies]
futures-core-preview = { version = "=0.3.0-alpha.19", path = "../futures-core", default-features = false }
futures-task-preview = { version = "=0.3.0-alpha.19", path = "../futures-task", default-features = false }
futures-io-preview = { version = "=0.3.0-alpha.19", path = "../futures-io", default-features = false }
futures-util-preview = { version = "=0.3.0-alpha.19", path = "../futures-util", default-features = false }
futures-executor-preview = { version = "=0.3.0-alpha.19", path = "../futures-executor", default-features = false }
Expand All @@ -26,4 +27,4 @@ futures-preview = { version = "=0.3.0-alpha.19", path = "../futures", default-fe

[features]
default = ["std"]
std = ["futures-core-preview/std", "futures-io-preview/std", "futures-util-preview/std", "futures-util-preview/io", "futures-executor-preview/std"]
std = ["futures-core-preview/std", "futures-task-preview/std", "futures-io-preview/std", "futures-util-preview/std", "futures-util-preview/io", "futures-executor-preview/std"]
2 changes: 1 addition & 1 deletion futures-test/src/task/mod.rs
Expand Up @@ -12,7 +12,7 @@
//! This module provides utilities for creating test
//! [`Context`](futures_core::task::Context)s,
//! [`Waker`](futures_core::task::Waker)s and
//! [`Spawn`](futures_core::task::Spawn) implementations.
//! [`Spawn`](futures_task::Spawn) implementations.
//!
//! Test contexts:
//! - [`noop_context`](crate::task::noop_context) creates a context that ignores calls to
Expand Down
5 changes: 2 additions & 3 deletions futures-test/src/task/noop_spawner.rs
@@ -1,7 +1,6 @@
use futures_core::future::FutureObj;
use futures_core::task::{Spawn, SpawnError};
use futures_task::{Spawn, SpawnError, FutureObj};

/// An implementation of [`Spawn`](futures_core::task::Spawn) that
/// An implementation of [`Spawn`](futures_task::Spawn) that
/// discards spawned futures when used.
///
/// # Examples
Expand Down
5 changes: 2 additions & 3 deletions futures-test/src/task/panic_spawner.rs
@@ -1,7 +1,6 @@
use futures_core::future::FutureObj;
use futures_core::task::{Spawn, SpawnError};
use futures_task::{Spawn, SpawnError, FutureObj};

/// An implementation of [`Spawn`](futures_core::task::Spawn) that panics
/// An implementation of [`Spawn`](futures_task::Spawn) that panics
/// when used.
///
/// # Examples
Expand Down
5 changes: 2 additions & 3 deletions futures-test/src/task/record_spawner.rs
@@ -1,7 +1,6 @@
use futures_core::future::FutureObj;
use futures_core::task::{Spawn, SpawnError};
use futures_task::{Spawn, SpawnError, FutureObj};

/// An implementation of [`Spawn`](futures_core::task::Spawn) that records
/// An implementation of [`Spawn`](futures_task::Spawn) that records
/// any [`Future`](futures_core::future::Future)s spawned on it.
///
/// # Examples
Expand Down
9 changes: 5 additions & 4 deletions futures-util/Cargo.toml
Expand Up @@ -16,8 +16,8 @@ name = "futures_util"

[features]
default = ["std"]
std = ["alloc", "futures-core-preview/std", "slab"]
alloc = ["futures-core-preview/alloc"]
std = ["alloc", "futures-core-preview/std", "futures-task-preview/std", "slab"]
alloc = ["futures-core-preview/alloc", "futures-task-preview/alloc"]
async-await = []
async-await-macro = ["async-await", "futures-macro-preview", "proc-macro-hack", "proc-macro-nested"]
compat = ["std", "futures_01"]
Expand All @@ -29,13 +29,14 @@ channel = ["std", "futures-channel-preview"]
# Unstable features
# These features are outside of the normal semver guarantees and require the
# `unstable` feature as an explicit opt-in to unstable API.
unstable = ["futures-core-preview/unstable"]
cfg-target-has-atomic = ["futures-core-preview/cfg-target-has-atomic"]
unstable = ["futures-core-preview/unstable", "futures-task-preview/unstable"]
cfg-target-has-atomic = ["futures-core-preview/cfg-target-has-atomic", "futures-task-preview/cfg-target-has-atomic"]
bilock = []
read-initializer = ["io", "futures-io-preview/read-initializer", "futures-io-preview/unstable"]

[dependencies]
futures-core-preview = { path = "../futures-core", version = "=0.3.0-alpha.19", default-features = false }
futures-task-preview = { path = "../futures-task", version = "=0.3.0-alpha.19", default-features = false }
futures-channel-preview = { path = "../futures-channel", version = "=0.3.0-alpha.19", default-features = false, features = ["std"], optional = true }
futures-io-preview = { path = "../futures-io", version = "=0.3.0-alpha.19", default-features = false, features = ["std"], optional = true }
futures-sink-preview = { path = "../futures-sink", version = "=0.3.0-alpha.19", default-features = false, optional = true }
Expand Down