diff --git a/Cargo.toml b/Cargo.toml index 260a263..ca31614 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,13 @@ readme = "README.md" description = "Experimental structured concurrency support for async Rust (similar to trio's nurseries). Works with non-Send futures on stable Rust." [dependencies] -futures = "0.3.21" async-trait = "0.1.56" -pin-project = "1.1.5" +futures-channel = { version = "0.3.21", default-features = false, features = ["alloc"] } +futures-core = { version = "0.3.21", default-features = false, features = ["alloc"] } +futures-util = { version = "0.3.21", default-features = false, features = ["alloc"] } +pin-project-lite = "0.2.14" [dev-dependencies] +futures = "0.3.21" anyhow = "1" tokio = { version = "1.17.0", features = ["full"] } diff --git a/src/body.rs b/src/body.rs index 4ad3646..c73c4f6 100644 --- a/src/body.rs +++ b/src/body.rs @@ -1,27 +1,36 @@ use std::{pin::Pin, rc::Rc, task::Poll}; -use futures::Future; -use pin_project::{pin_project, pinned_drop}; +use futures_core::Future; +use pin_project_lite::pin_project; use crate::scope::Scope; -/// The future for a scope's "body". -/// -/// It is not considered complete until (a) the body is done and (b) any spawned futures are done. -/// Its result is whatever the body returned. -/// -/// # Unsafe contract -/// -/// - `body_future` and `result` will be dropped BEFORE `scope`. -#[pin_project(PinnedDrop)] -pub(crate) struct Body<'scope, 'env: 'scope, R, F> -where - R: 'env, -{ - #[pin] - body_future: Option, - result: Option, - scope: Rc>, +pin_project! { + /// The future for a scope's "body". + /// + /// It is not considered complete until (a) the body is done and (b) any spawned futures are done. + /// Its result is whatever the body returned. + /// + /// # Unsafe contract + /// + /// - `body_future` and `result` will be dropped BEFORE `scope`. + pub(crate) struct Body<'scope, 'env: 'scope, R, F> + where + R: 'env, + { + #[pin] + body_future: Option, + result: Option, + scope: Rc>, + } + + impl PinnedDrop for Body<'_, '_, R, F> { + fn drop(this: Pin<&mut Self>) { + // Fulfill our unsafe contract and ensure we drop other fields + // before we drop scope. + this.clear(); + } + } } impl<'scope, 'env, R, F> Body<'scope, 'env, R, F> { @@ -44,15 +53,6 @@ impl<'scope, 'env, R, F> Body<'scope, 'env, R, F> { } } -#[pinned_drop] -impl<'scope, 'env, R, F> PinnedDrop for Body<'scope, 'env, R, F> { - fn drop(self: Pin<&mut Self>) { - // Fulfill our unsafe contract and ensure we drop other fields - // before we drop scope. - self.clear(); - } -} - impl<'scope, 'env, R, F> Future for Body<'scope, 'env, R, F> where F: Future, @@ -80,7 +80,7 @@ where // so forward that result. Otherwise, the `result` from our body future // should be available, so return that. match ready!(this.scope.poll_jobs(cx)) { - Some(v) => return Poll::Ready(v), + Some(v) => Poll::Ready(v), None => match this.result.take() { None => Poll::Pending, Some(v) => Poll::Ready(v), diff --git a/src/lib.rs b/src/lib.rs index 293b8d5..0ae5f75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,7 @@ mod spawned; /// /// ```rust /// # futures::executor::block_on(async { -/// let scope = moro::async_scope!(|scope| {/* ... */}).await; +/// let scope = moro_local::async_scope!(|scope| {/* ... */}).await; /// # }); /// ``` /// @@ -50,7 +50,7 @@ mod spawned; /// ```rust /// # futures::executor::block_on(async { /// let r = 22; -/// let scope = moro::async_scope!(|scope| { +/// let scope = moro_local::async_scope!(|scope| { /// // OK to refer to `r` here /// scope.spawn(async { r }).await /// }); @@ -65,7 +65,7 @@ mod spawned; /// /// ```rust,compile_fail,E0373 /// # futures::executor::block_on(async { -/// let scope = moro::async_scope!(|scope| { +/// let scope = moro_local::async_scope!(|scope| { /// let r = 22; // /// // NOT ok to refer to `r` now, because `r` @@ -88,7 +88,7 @@ mod spawned; /// ```rust /// # futures::executor::block_on(async { /// let v = vec![1, 2, 3, 5]; -/// let scope = moro::async_scope!(|scope| { +/// let scope = moro_local::async_scope!(|scope| { /// let job = scope.spawn(async { /// let r: i32 = v.iter().sum(); /// r @@ -108,7 +108,7 @@ mod spawned; /// /// ```rust /// # futures::executor::block_on(async { -/// let scope = moro::async_scope!(|scope| -> Result<(), u32> { +/// let scope = moro_local::async_scope!(|scope| -> Result<(), u32> { /// Err(22) // Ok type would otherwise be unconstrained /// }); /// let result = scope.await; @@ -139,7 +139,7 @@ macro_rules! async_scope { }}; } -use futures::future::LocalBoxFuture; +use futures_core::future::LocalBoxFuture; pub use self::scope::Scope; pub use self::scope_body::ScopeBody; diff --git a/src/scope.rs b/src/scope.rs index 683ee0a..9c8e08d 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -1,6 +1,8 @@ use std::{cell::RefCell, marker::PhantomData, pin::Pin, rc::Rc, task::Poll}; -use futures::{channel::oneshot, future::LocalBoxFuture, stream::FuturesUnordered, Future, Stream}; +use futures_channel::oneshot; +use futures_core::{future::LocalBoxFuture, Future, Stream}; +use futures_util::stream::FuturesUnordered; use crate::Spawned; @@ -80,7 +82,7 @@ impl<'scope, 'env, R> Scope<'scope, 'env, R> { /// /// ```rust /// # futures::executor::block_on(async { - /// let result = moro::async_scope!(|scope| { + /// let result = moro_local::async_scope!(|scope| { /// scope.spawn(async { /* ... */ }); /// /// // Calling `scope.terminate` here will terminate the async @@ -98,7 +100,7 @@ impl<'scope, 'env, R> Scope<'scope, 'env, R> { T: 'scope, { if self.terminated.borrow().is_none() { - self.terminated.replace(Some(value.into())); + self.terminated.replace(Some(value)); } // The code below will never run diff --git a/src/scope_body.rs b/src/scope_body.rs index 0609b9d..5e83bf7 100644 --- a/src/scope_body.rs +++ b/src/scope_body.rs @@ -1,17 +1,18 @@ use std::pin::Pin; -use futures::Future; -use pin_project::pin_project; +use futures_core::Future; +use pin_project_lite::pin_project; use crate::body::Body; -#[pin_project] -pub struct ScopeBody<'env, R: 'env, F> -where - F: Future, -{ - #[pin] - body: Body<'env, 'env, R, F>, +pin_project! { + pub struct ScopeBody<'env, R: 'env, F> + where + F: Future, + { + #[pin] + body: Body<'env, 'env, R, F>, + } } impl<'env, R, F> ScopeBody<'env, R, F> diff --git a/src/spawned.rs b/src/spawned.rs index d537530..9dd98a4 100644 --- a/src/spawned.rs +++ b/src/spawned.rs @@ -2,7 +2,7 @@ use std::pin::Pin; use crate::prelude::*; use crate::Scope; -use futures::Future; +use futures_core::Future; pub struct Spawned { f: F,