diff --git a/.travis.yml b/.travis.yml index 24028c3452..af161349f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,6 +54,14 @@ matrix: - cargo build --manifest-path futures-sink/Cargo.toml --no-default-features - cargo build --manifest-path futures-util/Cargo.toml --no-default-features + - name: cargo build (alloc) + rust: nightly + script: + - cargo build --manifest-path futures/Cargo.toml --no-default-features --features alloc,nightly + - cargo build --manifest-path futures-core/Cargo.toml --no-default-features --features alloc,nightly + - cargo build --manifest-path futures-sink/Cargo.toml --no-default-features --features alloc,nightly + - cargo build --manifest-path futures-util/Cargo.toml --no-default-features --features alloc,nightly + - name: cargo build (default features) rust: nightly script: @@ -74,6 +82,10 @@ matrix: --target thumbv6m-none-eabi --no-default-features --features nightly,cfg-target-has-atomic + - cargo build --manifest-path futures/Cargo.toml + --target thumbv6m-none-eabi + --no-default-features + --features nightly,alloc,cfg-target-has-atomic - name: cargo build --target=thumbv7m-none-eabi rust: nightly @@ -84,6 +96,10 @@ matrix: - cargo build --manifest-path futures/Cargo.toml --target thumbv7m-none-eabi --no-default-features + - cargo build --manifest-path futures/Cargo.toml + --target thumbv7m-none-eabi + --no-default-features + --features nightly,alloc - name: cargo doc rust: nightly diff --git a/futures-core/Cargo.toml b/futures-core/Cargo.toml index e5c9905eb7..7cb4e5df7e 100644 --- a/futures-core/Cargo.toml +++ b/futures-core/Cargo.toml @@ -16,9 +16,10 @@ name = "futures_core" [features] default = ["std"] -std = ["either/use_std"] +std = ["alloc", "either/use_std"] nightly = [] cfg-target-has-atomic = [] +alloc = [] [dependencies] either = { version = "1.4", default-features = false, optional = true } diff --git a/futures-core/src/future/future_obj.rs b/futures-core/src/future/future_obj.rs index 94c76981b5..d765cabcf5 100644 --- a/futures-core/src/future/future_obj.rs +++ b/futures-core/src/future/future_obj.rs @@ -185,10 +185,11 @@ where unsafe fn drop(_ptr: *mut ()) {} } -#[cfg(feature = "std")] -mod if_std { +#[cfg(feature = "alloc")] +mod if_alloc { use super::*; - use std::mem; + use core::mem; + use alloc::boxed::Box; unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box where F: Future + 'a diff --git a/futures-core/src/future/mod.rs b/futures-core/src/future/mod.rs index efdca7524d..0d539b3876 100644 --- a/futures-core/src/future/mod.rs +++ b/futures-core/src/future/mod.rs @@ -33,9 +33,11 @@ impl FusedFuture for &mut F { } } -#[cfg(feature = "std")] -mod if_std { +#[cfg(feature = "alloc")] +mod if_alloc { + use alloc::boxed::Box; use super::*; + impl FusedFuture for Box { fn is_terminated(&self) -> bool { ::is_terminated(&**self) @@ -48,6 +50,7 @@ mod if_std { } } + #[cfg(feature = "std")] impl FusedFuture for std::panic::AssertUnwindSafe { fn is_terminated(&self) -> bool { ::is_terminated(&**self) diff --git a/futures-core/src/lib.rs b/futures-core/src/lib.rs index 3e2639d861..daf2d3982d 100644 --- a/futures-core/src/lib.rs +++ b/futures-core/src/lib.rs @@ -2,6 +2,7 @@ #![feature(futures_api)] #![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] +#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))] #![cfg_attr(not(feature = "std"), no_std)] @@ -12,6 +13,14 @@ #[cfg(all(feature = "cfg-target-has-atomic", not(feature = "nightly")))] compile_error!("The `cfg-target-has-atomic` feature requires the `nightly` feature as an explicit opt-in to unstable features"); +#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "nightly"))))] +compile_error!("The `alloc` feature without `std` requires the `nightly` feature active to explicitly opt-in to unstable features"); + +#[cfg(all(feature = "alloc", not(feature = "std")))] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std as alloc; + pub mod future; #[doc(hidden)] pub use self::future::{Future, FusedFuture, TryFuture}; diff --git a/futures-core/src/stream/mod.rs b/futures-core/src/stream/mod.rs index 72e813f8d8..cddc11e150 100644 --- a/futures-core/src/stream/mod.rs +++ b/futures-core/src/stream/mod.rs @@ -145,9 +145,9 @@ impl TryStream for S } } -#[cfg(feature = "std")] -mod if_std { - use std::boxed::Box; +#[cfg(feature = "alloc")] +mod if_alloc { + use alloc::boxed::Box; use super::*; impl Stream for Box { @@ -161,6 +161,7 @@ mod if_std { } } + #[cfg(feature = "std")] impl Stream for ::std::panic::AssertUnwindSafe { type Item = S::Item; @@ -172,7 +173,7 @@ mod if_std { } } - impl Stream for ::std::collections::VecDeque { + impl Stream for ::alloc::collections::VecDeque { type Item = T; fn poll_next( diff --git a/futures-core/src/stream/stream_obj.rs b/futures-core/src/stream/stream_obj.rs index dae033e398..70559ecffd 100644 --- a/futures-core/src/stream/stream_obj.rs +++ b/futures-core/src/stream/stream_obj.rs @@ -187,11 +187,11 @@ where unsafe fn drop(_ptr: *mut ()) {} } -#[cfg(feature = "std")] -mod if_std { - use std::boxed::Box; - use std::mem; +#[cfg(feature = "alloc")] +mod if_alloc { use super::*; + use core::mem; + use alloc::boxed::Box; unsafe impl<'a, T, F> UnsafeStreamObj<'a, T> for Box where F: Stream + 'a diff --git a/futures-sink/Cargo.toml b/futures-sink/Cargo.toml index fc615a8826..fd4396735b 100644 --- a/futures-sink/Cargo.toml +++ b/futures-sink/Cargo.toml @@ -15,8 +15,10 @@ The asynchronous `Sink` trait for the futures-rs library. name = "futures_sink" [features] -std = ["either/use_std", "futures-core-preview/std", "futures-channel-preview/std"] +std = ["alloc", "either/use_std", "futures-core-preview/std", "futures-channel-preview/std"] default = ["std"] +nightly = ["futures-core-preview/nightly"] +alloc = ["futures-core-preview/alloc"] [dependencies] either = { version = "1.4", default-features = false, optional = true } diff --git a/futures-sink/src/lib.rs b/futures-sink/src/lib.rs index e7fd141095..973cb3d61f 100644 --- a/futures-sink/src/lib.rs +++ b/futures-sink/src/lib.rs @@ -8,6 +8,15 @@ #![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.13/futures_sink")] #![feature(futures_api)] +#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))] + +#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "nightly"))))] +compile_error!("The `alloc` feature without `std` requires the `nightly` feature active to explicitly opt-in to unstable features"); + +#[cfg(all(feature = "alloc", not(feature = "std")))] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std as alloc; use futures_core::task::{Waker, Poll}; use core::pin::Pin; @@ -155,8 +164,8 @@ impl<'a, S: ?Sized + Sink> Sink for Pin<&'a mut S> { #[cfg(feature = "std")] mod channel_impls; -#[cfg(feature = "std")] -mod if_std { +#[cfg(feature = "alloc")] +mod if_alloc { use super::*; /// The error type for `Vec` and `VecDequeue` when used as `Sink`s. @@ -164,7 +173,7 @@ mod if_std { #[derive(Copy, Clone, Debug)] pub enum VecSinkError {} - impl Sink for ::std::vec::Vec { + impl Sink for ::alloc::vec::Vec { type SinkItem = T; type SinkError = VecSinkError; @@ -187,7 +196,7 @@ mod if_std { } } - impl Sink for ::std::collections::VecDeque { + impl Sink for ::alloc::collections::VecDeque { type SinkItem = T; type SinkError = VecSinkError; @@ -210,7 +219,7 @@ mod if_std { } } - impl Sink for ::std::boxed::Box { + impl Sink for ::alloc::boxed::Box { type SinkItem = S::SinkItem; type SinkError = S::SinkError; @@ -232,8 +241,8 @@ mod if_std { } } -#[cfg(feature = "std")] -pub use self::if_std::*; +#[cfg(feature = "alloc")] +pub use self::if_alloc::*; #[cfg(feature = "either")] use either::Either; diff --git a/futures-util/Cargo.toml b/futures-util/Cargo.toml index 51be739f89..f7bdbc2482 100644 --- a/futures-util/Cargo.toml +++ b/futures-util/Cargo.toml @@ -15,13 +15,14 @@ Common utilities and extension traits for the futures-rs library. name = "futures_util" [features] -std = ["futures-core-preview/std", "futures-io-preview/std", "futures-sink-preview/std", "futures-select-macro-preview/std", "either/use_std", "rand", "rand_core", "slab"] +std = ["alloc", "futures-core-preview/std", "futures-io-preview/std", "futures-sink-preview/std", "futures-select-macro-preview/std", "either/use_std", "rand", "rand_core", "slab"] default = ["std", "futures-core-preview/either", "futures-sink-preview/either"] compat = ["std", "futures_01"] io-compat = ["compat", "tokio-io"] bench = [] -nightly = [] +nightly = ["futures-core-preview/nightly", "futures-sink-preview/nightly"] cfg-target-has-atomic = [] +alloc = ["futures-core-preview/alloc", "futures-sink-preview/alloc"] [dependencies] futures-core-preview = { path = "../futures-core", version = "=0.3.0-alpha.13", default-features = false } diff --git a/futures-util/src/future/abortable.rs b/futures-util/src/future/abortable.rs index cfb51d55be..98e8d6fa2e 100644 --- a/futures-util/src/future/abortable.rs +++ b/futures-util/src/future/abortable.rs @@ -2,9 +2,9 @@ use crate::task::AtomicWaker; use futures_core::future::Future; use futures_core::task::{Waker, Poll}; use pin_utils::unsafe_pinned; -use std::pin::Pin; -use std::sync::Arc; -use std::sync::atomic::{AtomicBool, Ordering}; +use core::pin::Pin; +use core::sync::atomic::{AtomicBool, Ordering}; +use alloc::sync::Arc; /// A future which can be remotely short-circuited using an `AbortHandle`. #[derive(Debug, Clone)] diff --git a/futures-util/src/future/join_all.rs b/futures-util/src/future/join_all.rs index 86c9e91d1c..398f054f2c 100644 --- a/futures-util/src/future/join_all.rs +++ b/futures-util/src/future/join_all.rs @@ -1,13 +1,13 @@ //! Definition of the `JoinAll` combinator, waiting for all of a list of futures //! to finish. -use std::fmt; -use std::future::Future; -use std::iter::FromIterator; -use std::mem; -use std::pin::Pin; -use std::prelude::v1::*; -use std::task::Poll; +use core::fmt; +use core::future::Future; +use core::iter::FromIterator; +use core::mem; +use core::pin::Pin; +use core::task::{Poll, Waker}; +use alloc::prelude::v1::*; #[derive(Debug)] enum ElemState @@ -127,10 +127,7 @@ where { type Output = Vec; - fn poll( - mut self: Pin<&mut Self>, - waker: &::std::task::Waker, - ) -> Poll { + fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll { let mut all_done = true; for mut elem in iter_pin_mut(self.elems.as_mut()) { diff --git a/futures-util/src/future/mod.rs b/futures-util/src/future/mod.rs index 419cca8426..1605a41d23 100644 --- a/futures-util/src/future/mod.rs +++ b/futures-util/src/future/mod.rs @@ -7,6 +7,8 @@ use core::pin::Pin; use futures_core::future::Future; use futures_core::stream::Stream; use futures_core::task::{Waker, Poll}; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; // re-export for `select!` #[doc(hidden)] @@ -67,10 +69,17 @@ pub use self::unit_error::UnitError; mod chain; pub(crate) use self::chain::Chain; -#[cfg(feature = "std")] -mod abortable; -#[cfg(feature = "std")] -pub use self::abortable::{abortable, Abortable, AbortHandle, AbortRegistration, Aborted}; +#[cfg(feature = "alloc")] +mod join_all; +#[cfg(feature = "alloc")] +pub use self::join_all::{join_all, JoinAll}; + +cfg_target_has_atomic! { + #[cfg(feature = "alloc")] + mod abortable; + #[cfg(feature = "alloc")] + pub use self::abortable::{abortable, Abortable, AbortHandle, AbortRegistration, Aborted}; +} #[cfg(feature = "std")] mod catch_unwind; @@ -82,12 +91,6 @@ mod remote_handle; #[cfg(feature = "std")] pub use self::remote_handle::{Remote, RemoteHandle}; -#[cfg(feature = "std")] -mod join_all; - -#[cfg(feature = "std")] -pub use self::join_all::{join_all, JoinAll}; - // #[cfg(feature = "std")] // mod select_all; // #[cfg(feature = "std")] @@ -653,7 +656,7 @@ pub trait FutureExt: Future { } /// Wrap the future in a Box, pinning it. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn boxed(self) -> Pin> where Self: Sized { diff --git a/futures-util/src/lib.rs b/futures-util/src/lib.rs index c528d96070..d01bf36ea6 100644 --- a/futures-util/src/lib.rs +++ b/futures-util/src/lib.rs @@ -2,8 +2,10 @@ //! and the `AsyncRead` and `AsyncWrite` traits. #![feature(futures_api)] -#![cfg_attr(feature = "std", feature(async_await, await_macro, box_into_pin))] +#![cfg_attr(feature = "alloc", feature(box_into_pin))] +#![cfg_attr(feature = "std", feature(async_await, await_macro))] #![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] +#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc, alloc_prelude))] #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] @@ -13,6 +15,14 @@ #[cfg(all(feature = "cfg-target-has-atomic", not(feature = "nightly")))] compile_error!("The `cfg-target-has-atomic` feature requires the `nightly` feature as an explicit opt-in to unstable features"); +#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "nightly"))))] +compile_error!("The `alloc` feature without `std` requires the `nightly` feature active to explicitly opt-in to unstable features"); + +#[cfg(all(feature = "alloc", not(feature = "std")))] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std as alloc; + #[macro_use] mod macros; @@ -91,5 +101,7 @@ pub mod io; #[cfg(feature = "std")] #[doc(hidden)] pub use crate::io::{AsyncReadExt, AsyncWriteExt}; -#[cfg(feature = "std")] -pub mod lock; +cfg_target_has_atomic! { + #[cfg(feature = "alloc")] + pub mod lock; +} diff --git a/futures-util/src/lock/bilock.rs b/futures-util/src/lock/bilock.rs index a8c9676695..8ac3483063 100644 --- a/futures-util/src/lock/bilock.rs +++ b/futures-util/src/lock/bilock.rs @@ -3,17 +3,19 @@ use futures_core::future::Future; use futures_core::task::{Waker, Poll}; +use core::cell::UnsafeCell; +use core::fmt; +use core::mem; +use core::ops::{Deref, DerefMut}; +use core::pin::Pin; +use core::sync::atomic::AtomicUsize; +use core::sync::atomic::Ordering::SeqCst; +use alloc::boxed::Box; +use alloc::sync::Arc; +#[cfg(feature = "std")] use std::any::Any; -use std::boxed::Box; -use std::cell::UnsafeCell; +#[cfg(feature = "std")] use std::error::Error; -use std::fmt; -use std::mem; -use std::ops::{Deref, DerefMut}; -use std::pin::Pin; -use std::sync::Arc; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering::SeqCst; /// A type of futures-powered synchronization primitive which is a mutex between /// two possible owners. @@ -210,6 +212,7 @@ impl fmt::Display for ReuniteError { } } +#[cfg(feature = "std")] impl Error for ReuniteError { fn description(&self) -> &str { "tried to reunite two BiLocks that don't form a pair" diff --git a/futures-util/src/lock/mod.rs b/futures-util/src/lock/mod.rs index e768c22332..38a5537724 100644 --- a/futures-util/src/lock/mod.rs +++ b/futures-util/src/lock/mod.rs @@ -1,6 +1,8 @@ //! Futures-powered synchronization primitives. +#[cfg(feature = "std")] mod mutex; +#[cfg(feature = "std")] pub use self::mutex::{Mutex, MutexLockFuture, MutexGuard}; mod bilock; diff --git a/futures-util/src/macros/mod.rs b/futures-util/src/macros/mod.rs index f0e9f05edc..0a9ac422c1 100644 --- a/futures-util/src/macros/mod.rs +++ b/futures-util/src/macros/mod.rs @@ -1,2 +1,12 @@ #[macro_use] mod poll; + +macro_rules! cfg_target_has_atomic { + ($($item:item)*) => {$( + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + $item + )*}; +} diff --git a/futures-util/src/sink/buffer.rs b/futures-util/src/sink/buffer.rs index e61c1f1a69..4100c184d3 100644 --- a/futures-util/src/sink/buffer.rs +++ b/futures-util/src/sink/buffer.rs @@ -2,8 +2,8 @@ use futures_core::stream::Stream; use futures_core::task::{Waker, Poll}; use futures_sink::Sink; use pin_utils::{unsafe_pinned, unsafe_unpinned}; -use std::collections::VecDeque; -use std::pin::Pin; +use core::pin::Pin; +use alloc::collections::VecDeque; /// Sink for the `Sink::buffer` combinator, which buffers up to some fixed /// number of values when the underlying sink is unable to accept them. diff --git a/futures-util/src/sink/mod.rs b/futures-util/src/sink/mod.rs index bde6d241d6..684735898b 100644 --- a/futures-util/src/sink/mod.rs +++ b/futures-util/src/sink/mod.rs @@ -41,9 +41,9 @@ pub use self::with::With; mod with_flat_map; pub use self::with_flat_map::WithFlatMap; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] mod buffer; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub use self::buffer::Buffer; impl SinkExt for T where T: Sink {} @@ -156,7 +156,7 @@ pub trait SinkExt: Sink { /// /// This method is only available when the `std` feature of this /// library is activated, and it is activated by default. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn buffer(self, capacity: usize) -> Buffer where Self: Sized, { diff --git a/futures-util/src/stream/buffer_unordered.rs b/futures-util/src/stream/buffer_unordered.rs index f42f977fad..34c5252b08 100644 --- a/futures-util/src/stream/buffer_unordered.rs +++ b/futures-util/src/stream/buffer_unordered.rs @@ -4,8 +4,8 @@ use futures_core::stream::{Stream, FusedStream}; use futures_core::task::{Waker, Poll}; use futures_sink::Sink; use pin_utils::{unsafe_pinned, unsafe_unpinned}; -use std::fmt; -use std::pin::Pin; +use core::fmt; +use core::pin::Pin; /// An adaptor for a stream of futures to execute the futures concurrently, if /// possible, delivering results as they become available. diff --git a/futures-util/src/stream/buffered.rs b/futures-util/src/stream/buffered.rs index e8b1b128d1..cafa5f3a98 100644 --- a/futures-util/src/stream/buffered.rs +++ b/futures-util/src/stream/buffered.rs @@ -4,8 +4,8 @@ use futures_core::stream::Stream; use futures_core::task::{Waker, Poll}; use futures_sink::Sink; use pin_utils::{unsafe_pinned, unsafe_unpinned}; -use std::fmt; -use std::pin::Pin; +use core::fmt; +use core::pin::Pin; /// An adaptor for a stream of futures to execute the futures concurrently, if /// possible. diff --git a/futures-util/src/stream/chunks.rs b/futures-util/src/stream/chunks.rs index ae54ae60bd..6c0e631320 100644 --- a/futures-util/src/stream/chunks.rs +++ b/futures-util/src/stream/chunks.rs @@ -2,9 +2,9 @@ use crate::stream::Fuse; use futures_core::stream::Stream; use futures_core::task::{Waker, Poll}; use pin_utils::{unsafe_pinned, unsafe_unpinned}; -use std::mem; -use std::pin::Pin; -use std::prelude::v1::*; +use core::mem; +use core::pin::Pin; +use alloc::prelude::v1::*; /// An adaptor that chunks up elements in a vector. /// diff --git a/futures-util/src/stream/futures_ordered.rs b/futures-util/src/stream/futures_ordered.rs index 443b434337..4f85b91723 100644 --- a/futures-util/src/stream/futures_ordered.rs +++ b/futures-util/src/stream/futures_ordered.rs @@ -3,11 +3,11 @@ use futures_core::future::Future; use futures_core::stream::Stream; use futures_core::task::{Waker, Poll}; use pin_utils::unsafe_pinned; -use std::cmp::{Eq, PartialEq, PartialOrd, Ord, Ordering}; -use std::collections::binary_heap::{BinaryHeap, PeekMut}; -use std::fmt::{self, Debug}; -use std::iter::FromIterator; -use std::pin::Pin; +use core::cmp::{Eq, PartialEq, PartialOrd, Ord, Ordering}; +use core::fmt::{self, Debug}; +use core::iter::FromIterator; +use core::pin::Pin; +use alloc::collections::binary_heap::{BinaryHeap, PeekMut}; #[must_use = "futures do nothing unless polled"] #[derive(Debug)] diff --git a/futures-util/src/stream/futures_unordered/iter.rs b/futures-util/src/stream/futures_unordered/iter.rs index 1eef3e5265..b03e10bb2d 100644 --- a/futures-util/src/stream/futures_unordered/iter.rs +++ b/futures-util/src/stream/futures_unordered/iter.rs @@ -1,7 +1,7 @@ use super::FuturesUnordered; use super::task::Task; -use std::marker::PhantomData; -use std::pin::Pin; +use core::marker::PhantomData; +use core::pin::Pin; #[derive(Debug)] /// Mutable iterator over all futures in the unordered set. diff --git a/futures-util/src/stream/futures_unordered/mod.rs b/futures-util/src/stream/futures_unordered/mod.rs index 29f891c28b..c9431ccc13 100644 --- a/futures-util/src/stream/futures_unordered/mod.rs +++ b/futures-util/src/stream/futures_unordered/mod.rs @@ -4,17 +4,17 @@ use crate::task::{AtomicWaker}; use futures_core::future::{Future, FutureObj, LocalFutureObj}; use futures_core::stream::{FusedStream, Stream}; use futures_core::task::{Waker, Poll, Spawn, LocalSpawn, SpawnError}; -use std::cell::UnsafeCell; -use std::fmt::{self, Debug}; -use std::iter::FromIterator; -use std::marker::PhantomData; -use std::mem; -use std::pin::Pin; -use std::ptr; -use std::sync::atomic::Ordering::SeqCst; -use std::sync::atomic::{AtomicPtr, AtomicBool}; -use std::sync::{Arc, Weak}; -use std::usize; +use core::cell::UnsafeCell; +use core::fmt::{self, Debug}; +use core::iter::FromIterator; +use core::marker::PhantomData; +use core::mem; +use core::pin::Pin; +use core::ptr; +use core::sync::atomic::Ordering::SeqCst; +use core::sync::atomic::{AtomicPtr, AtomicBool}; +use core::usize; +use alloc::sync::{Arc, Weak}; mod abort; diff --git a/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs b/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs index f71b8ff877..210519585e 100644 --- a/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs +++ b/futures-util/src/stream/futures_unordered/ready_to_run_queue.rs @@ -1,9 +1,9 @@ use crate::task::AtomicWaker; -use std::cell::UnsafeCell; -use std::ptr; -use std::sync::Arc; -use std::sync::atomic::AtomicPtr; -use std::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel}; +use core::cell::UnsafeCell; +use core::ptr; +use core::sync::atomic::AtomicPtr; +use core::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel}; +use alloc::sync::Arc; use super::abort::abort; use super::task::Task; diff --git a/futures-util/src/stream/futures_unordered/task.rs b/futures-util/src/stream/futures_unordered/task.rs index 069c750e61..cbfec0c7ea 100644 --- a/futures-util/src/stream/futures_unordered/task.rs +++ b/futures-util/src/stream/futures_unordered/task.rs @@ -1,7 +1,7 @@ -use std::cell::UnsafeCell; -use std::sync::{Arc, Weak}; -use std::sync::atomic::{AtomicPtr, AtomicBool}; -use std::sync::atomic::Ordering::SeqCst; +use core::cell::UnsafeCell; +use core::sync::atomic::{AtomicPtr, AtomicBool}; +use core::sync::atomic::Ordering::SeqCst; +use alloc::sync::{Arc, Weak}; use crate::task::{ArcWake, WakerRef, waker_ref}; use super::ReadyToRunQueue; diff --git a/futures-util/src/stream/mod.rs b/futures-util/src/stream/mod.rs index c3eafdcfc5..3b734dad8e 100644 --- a/futures-util/src/stream/mod.rs +++ b/futures-util/src/stream/mod.rs @@ -9,6 +9,8 @@ use futures_core::future::Future; use futures_core::stream::{FusedStream, Stream}; use futures_core::task::{Waker, Poll}; use futures_sink::Sink; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; mod iter; pub use self::iter::{iter, Iter}; @@ -97,53 +99,52 @@ pub use self::unfold::{unfold, Unfold}; mod zip; pub use self::zip::Zip; -#[cfg(feature = "std")] -use std; - -#[cfg(feature = "std")] -mod buffer_unordered; -#[cfg(feature = "std")] -pub use self::buffer_unordered::BufferUnordered; - -#[cfg(feature = "std")] -mod buffered; -#[cfg(feature = "std")] -pub use self::buffered::Buffered; - -#[cfg(feature = "std")] -mod catch_unwind; -#[cfg(feature = "std")] -pub use self::catch_unwind::CatchUnwind; - -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] mod chunks; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub use self::chunks::Chunks; -#[cfg(feature = "std")] -mod for_each_concurrent; -#[cfg(feature = "std")] -pub use self::for_each_concurrent::ForEachConcurrent; - -#[cfg(feature = "std")] -mod futures_ordered; -#[cfg(feature = "std")] -pub use self::futures_ordered::{futures_ordered, FuturesOrdered}; - -#[cfg(feature = "std")] -mod futures_unordered; -#[cfg(feature = "std")] -pub use self::futures_unordered::{futures_unordered, FuturesUnordered}; - -#[cfg(feature = "std")] -mod split; -#[cfg(feature = "std")] -pub use self::split::{SplitStream, SplitSink, ReuniteError}; +cfg_target_has_atomic! { + #[cfg(feature = "alloc")] + mod buffer_unordered; + #[cfg(feature = "alloc")] + pub use self::buffer_unordered::BufferUnordered; + + #[cfg(feature = "alloc")] + mod buffered; + #[cfg(feature = "alloc")] + pub use self::buffered::Buffered; + + #[cfg(feature = "alloc")] + mod for_each_concurrent; + #[cfg(feature = "alloc")] + pub use self::for_each_concurrent::ForEachConcurrent; + + #[cfg(feature = "alloc")] + mod futures_ordered; + #[cfg(feature = "alloc")] + pub use self::futures_ordered::{futures_ordered, FuturesOrdered}; + + #[cfg(feature = "alloc")] + mod futures_unordered; + #[cfg(feature = "alloc")] + pub use self::futures_unordered::{futures_unordered, FuturesUnordered}; + + #[cfg(feature = "alloc")] + mod split; + #[cfg(feature = "alloc")] + pub use self::split::{SplitStream, SplitSink, ReuniteError}; + + #[cfg(feature = "alloc")] + mod select_all; + #[cfg(feature = "alloc")] + pub use self::select_all::{select_all, SelectAll}; +} #[cfg(feature = "std")] -mod select_all; +mod catch_unwind; #[cfg(feature = "std")] -pub use self::select_all::{select_all, SelectAll}; +pub use self::catch_unwind::CatchUnwind; impl StreamExt for T where T: Stream {} @@ -614,7 +615,11 @@ pub trait StreamExt: Stream { /// await!(fut); /// # }) /// ``` - #[cfg(feature = "std")] + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + #[cfg(feature = "alloc")] fn for_each_concurrent( self, limit: impl Into>, @@ -791,7 +796,7 @@ pub trait StreamExt: Stream { } /// Wrap the stream in a Box, pinning it. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn boxed(self) -> Pin> where Self: Sized { @@ -810,7 +815,11 @@ pub trait StreamExt: Stream { /// /// This method is only available when the `std` feature of this /// library is activated, and it is activated by default. - #[cfg(feature = "std")] + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + #[cfg(feature = "alloc")] fn buffered(self, n: usize) -> Buffered where Self::Item: Future, Self: Sized @@ -854,7 +863,11 @@ pub trait StreamExt: Stream { /// assert_eq!(await!(buffered.next()), None); /// # }) /// ``` - #[cfg(feature = "std")] + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + #[cfg(feature = "alloc")] fn buffer_unordered(self, n: usize) -> BufferUnordered where Self::Item: Future, Self: Sized @@ -945,7 +958,7 @@ pub trait StreamExt: Stream { /// # Panics /// /// This method will panic of `capacity` is zero. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn chunks(self, capacity: usize) -> Chunks where Self: Sized { @@ -993,7 +1006,11 @@ pub trait StreamExt: Stream { /// /// This method is only available when the `std` feature of this /// library is activated, and it is activated by default. - #[cfg(feature = "std")] + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + #[cfg(feature = "alloc")] fn split(self) -> (SplitSink, SplitStream) where Self: Sink + Sized { diff --git a/futures-util/src/stream/select_all.rs b/futures-util/src/stream/select_all.rs index 31039c2011..d48542df5c 100644 --- a/futures-util/src/stream/select_all.rs +++ b/futures-util/src/stream/select_all.rs @@ -1,7 +1,7 @@ //! An unbounded set of streams -use std::fmt::{self, Debug}; -use std::pin::Pin; +use core::fmt::{self, Debug}; +use core::pin::Pin; use futures_core::{Poll, Stream, FusedStream}; use futures_core::task::Waker; diff --git a/futures-util/src/stream/split.rs b/futures-util/src/stream/split.rs index 472b820c03..fea598275c 100644 --- a/futures-util/src/stream/split.rs +++ b/futures-util/src/stream/split.rs @@ -1,10 +1,12 @@ use futures_core::stream::Stream; use futures_core::task::{Waker, Poll}; use futures_sink::Sink; +use core::fmt; +use core::pin::Pin; +#[cfg(feature = "std")] use std::any::Any; +#[cfg(feature = "std")] use std::error::Error; -use std::fmt; -use std::pin::Pin; use crate::lock::BiLock; @@ -139,6 +141,7 @@ impl fmt::Display for ReuniteError { } } +#[cfg(feature = "std")] impl Error for ReuniteError { fn description(&self) -> &str { "tried to reunite a SplitStream and SplitSink that don't form a pair" diff --git a/futures-util/src/task/arc_wake.rs b/futures-util/src/task/arc_wake.rs index aee4285986..f7333e06b6 100644 --- a/futures-util/src/task/arc_wake.rs +++ b/futures-util/src/task/arc_wake.rs @@ -1,6 +1,6 @@ -use std::mem; -use std::sync::Arc; -use std::task::{Waker, RawWaker, RawWakerVTable}; +use core::mem; +use core::task::{Waker, RawWaker, RawWakerVTable}; +use alloc::sync::Arc; /// A way of waking up a specific task. /// diff --git a/futures-util/src/task/mod.rs b/futures-util/src/task/mod.rs index 580b0e12c8..d686272124 100644 --- a/futures-util/src/task/mod.rs +++ b/futures-util/src/task/mod.rs @@ -1,21 +1,31 @@ //! Task notification -/// A macro for creating a `RawWaker` vtable for a type that implements -/// the `ArcWake` trait. -macro_rules! waker_vtable { - ($ty:ident) => { - &RawWakerVTable { - clone: clone_arc_raw::<$ty>, - drop: drop_arc_raw::<$ty>, - wake: wake_arc_raw::<$ty>, - } - }; -} +cfg_target_has_atomic! { + /// A macro for creating a `RawWaker` vtable for a type that implements + /// the `ArcWake` trait. + #[cfg(feature = "alloc")] + macro_rules! waker_vtable { + ($ty:ident) => { + &RawWakerVTable { + clone: clone_arc_raw::<$ty>, + drop: drop_arc_raw::<$ty>, + wake: wake_arc_raw::<$ty>, + } + }; + } -#[cfg(feature = "std")] -mod arc_wake; -#[cfg(feature = "std")] -pub use self::arc_wake::ArcWake; + #[cfg(feature = "alloc")] + mod arc_wake; + #[cfg(feature = "alloc")] + pub use self::arc_wake::ArcWake; + + #[cfg(feature = "alloc")] + mod waker_ref; + #[cfg(feature = "alloc")] + pub use self::waker_ref::{waker_ref, WakerRef}; + + pub use futures_core::task::__internal::AtomicWaker; +} mod noop_waker; pub use self::noop_waker::noop_waker; @@ -25,17 +35,6 @@ pub use self::noop_waker::noop_waker_ref; mod spawn; pub use self::spawn::{SpawnExt, LocalSpawnExt}; -#[cfg(feature = "std")] -mod waker_ref; -#[cfg(feature = "std")] -pub use self::waker_ref::{waker_ref, WakerRef}; - -#[cfg_attr( - feature = "cfg-target-has-atomic", - cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) -)] -pub use futures_core::task::__internal::AtomicWaker; - // re-export for `select!` #[doc(hidden)] pub use futures_core::task::{Waker, Poll}; diff --git a/futures-util/src/task/spawn.rs b/futures-util/src/task/spawn.rs index 58fd89bec7..e414dccf74 100644 --- a/futures-util/src/task/spawn.rs +++ b/futures-util/src/task/spawn.rs @@ -4,10 +4,12 @@ use futures_core::task::{LocalSpawn, Spawn}; #[cfg(feature = "std")] use crate::future::{FutureExt, RemoteHandle}; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] use futures_core::future::{Future, FutureObj, LocalFutureObj}; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] use futures_core::task::SpawnError; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; impl SpawnExt for Sp where Sp: Spawn {} impl LocalSpawnExt for Sp where Sp: LocalSpawn {} @@ -39,7 +41,7 @@ pub trait SpawnExt: Spawn { /// let future = async { /* ... */ }; /// executor.spawn(future).unwrap(); /// ``` - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn spawn(&mut self, future: Fut) -> Result<(), SpawnError> where Fut: Future + Send + 'static, @@ -118,7 +120,7 @@ pub trait LocalSpawnExt: LocalSpawn { /// let future = async { /* ... */ }; /// spawner.spawn_local(future).unwrap(); /// ``` - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn spawn_local(&mut self, future: Fut) -> Result<(), SpawnError> where Fut: Future + 'static, diff --git a/futures-util/src/task/waker_ref.rs b/futures-util/src/task/waker_ref.rs index 9608831b6f..cd5c39dc06 100644 --- a/futures-util/src/task/waker_ref.rs +++ b/futures-util/src/task/waker_ref.rs @@ -1,10 +1,10 @@ #![allow(clippy::cast_ptr_alignment)] // clippy is too strict here use super::arc_wake::{ArcWake, clone_arc_raw, wake_arc_raw}; -use std::marker::PhantomData; -use std::ops::Deref; -use std::sync::Arc; -use std::task::{Waker, RawWaker, RawWakerVTable}; +use alloc::sync::Arc; +use core::marker::PhantomData; +use core::ops::Deref; +use core::task::{Waker, RawWaker, RawWakerVTable}; /// A [`Waker`](::std::task::Waker) that is only valid for a given lifetime. /// diff --git a/futures-util/src/try_future/mod.rs b/futures-util/src/try_future/mod.rs index add19f88d0..3dcce7d4c6 100644 --- a/futures-util/src/try_future/mod.rs +++ b/futures-util/src/try_future/mod.rs @@ -54,10 +54,9 @@ pub use self::or_else::OrElse; mod unwrap_or_else; pub use self::unwrap_or_else::UnwrapOrElse; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] mod try_join_all; - -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub use self::try_join_all::{try_join_all, TryJoinAll}; // Implementation details diff --git a/futures-util/src/try_future/try_join_all.rs b/futures-util/src/try_future/try_join_all.rs index f26625c9cb..d387e0a164 100644 --- a/futures-util/src/try_future/try_join_all.rs +++ b/futures-util/src/try_future/try_join_all.rs @@ -1,13 +1,13 @@ //! Definition of the `TryJoinAll` combinator, waiting for all of a list of //! futures to finish with either success or error. -use std::fmt; -use std::future::Future; -use std::iter::FromIterator; -use std::mem; -use std::pin::Pin; -use std::prelude::v1::*; -use std::task::Poll; +use core::fmt; +use core::future::Future; +use core::iter::FromIterator; +use core::mem; +use core::pin::Pin; +use core::task::{Poll, Waker}; +use alloc::prelude::v1::*; use super::TryFuture; @@ -137,10 +137,7 @@ where { type Output = Result, F::Error>; - fn poll( - mut self: Pin<&mut Self>, - waker: &::std::task::Waker, - ) -> Poll { + fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll { let mut state = FinalState::AllDone; for mut elem in iter_pin_mut(self.elems.as_mut()) { diff --git a/futures-util/src/try_stream/mod.rs b/futures-util/src/try_stream/mod.rs index 488a6f8750..a71798bd07 100644 --- a/futures-util/src/try_stream/mod.rs +++ b/futures-util/src/try_stream/mod.rs @@ -44,17 +44,19 @@ pub use self::try_fold::TryFold; mod try_skip_while; pub use self::try_skip_while::TrySkipWhile; -#[cfg(feature = "std")] -mod try_buffer_unordered; -#[cfg(feature = "std")] -pub use self::try_buffer_unordered::TryBufferUnordered; - -#[cfg(feature = "std")] -mod try_for_each_concurrent; -#[cfg(feature = "std")] -pub use self::try_for_each_concurrent::TryForEachConcurrent; -#[cfg(feature = "std")] -use futures_core::future::Future; +cfg_target_has_atomic! { + #[cfg(feature = "alloc")] + mod try_buffer_unordered; + #[cfg(feature = "alloc")] + pub use self::try_buffer_unordered::TryBufferUnordered; + + #[cfg(feature = "alloc")] + mod try_for_each_concurrent; + #[cfg(feature = "alloc")] + pub use self::try_for_each_concurrent::TryForEachConcurrent; + #[cfg(feature = "alloc")] + use futures_core::future::Future; +} #[cfg(feature = "std")] mod into_async_read; @@ -310,7 +312,11 @@ pub trait TryStreamExt: TryStream { /// assert_eq!(Err(oneshot::Canceled), await!(fut)); /// # }) /// ``` - #[cfg(feature = "std")] + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + #[cfg(feature = "alloc")] fn try_for_each_concurrent( self, limit: impl Into>, @@ -542,7 +548,11 @@ pub trait TryStreamExt: TryStream { /// assert_eq!(await!(buffered.next()), Some(Err("error in the stream"))); /// # }) /// ``` - #[cfg(feature = "std")] + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + #[cfg(feature = "alloc")] fn try_buffer_unordered(self, n: usize) -> TryBufferUnordered where Self::Ok: TryFuture, Self: Sized diff --git a/futures-util/src/try_stream/try_buffer_unordered.rs b/futures-util/src/try_stream/try_buffer_unordered.rs index 6b1f3e5bfa..3cbaad5c9d 100644 --- a/futures-util/src/try_stream/try_buffer_unordered.rs +++ b/futures-util/src/try_stream/try_buffer_unordered.rs @@ -5,7 +5,7 @@ use futures_core::future::TryFuture; use futures_core::stream::{Stream, TryStream}; use futures_core::task::{Waker, Poll}; use pin_utils::{unsafe_pinned, unsafe_unpinned}; -use std::pin::Pin; +use core::pin::Pin; /// A stream returned by the /// [`try_buffer_unordered`](super::TryStreamExt::try_buffer_unordered) method diff --git a/futures/Cargo.toml b/futures/Cargo.toml index b97190e69b..70d8b3ba72 100644 --- a/futures/Cargo.toml +++ b/futures/Cargo.toml @@ -36,9 +36,10 @@ futures-test-preview = { path = "../futures-test", version = "=0.3.0-alpha.13" } tokio = "0.1.11" [features] -nightly = ["futures-util-preview/nightly", "futures-core-preview/nightly"] -std = ["futures-core-preview/std", "futures-executor-preview/std", "futures-io-preview/std", "futures-sink-preview/std", "futures-util-preview/std"] +nightly = ["futures-core-preview/nightly", "futures-sink-preview/nightly", "futures-util-preview/nightly"] +std = ["alloc", "futures-core-preview/std", "futures-executor-preview/std", "futures-io-preview/std", "futures-sink-preview/std", "futures-util-preview/std"] default = ["std"] compat = ["std", "futures-util-preview/compat"] io-compat = ["compat", "futures-util-preview/io-compat"] cfg-target-has-atomic = ["futures-core-preview/cfg-target-has-atomic", "futures-util-preview/cfg-target-has-atomic"] +alloc = ["futures-core-preview/alloc", "futures-sink-preview/alloc", "futures-util-preview/alloc"] diff --git a/futures/src/lib.rs b/futures/src/lib.rs index 8fb7dea1da..96ba9661c8 100644 --- a/futures/src/lib.rs +++ b/futures/src/lib.rs @@ -23,6 +23,7 @@ #![feature(futures_api)] #![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))] +#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))] #![cfg_attr(not(feature = "std"), no_std)] @@ -33,6 +34,9 @@ #[cfg(all(feature = "cfg-target-has-atomic", not(feature = "nightly")))] compile_error!("The `cfg-target-has-atomic` feature requires the `nightly` feature as an explicit opt-in to unstable features"); +#[cfg(all(feature = "alloc", not(any(feature = "std", feature = "nightly"))))] +compile_error!("The `alloc` feature without `std` requires the `nightly` feature active to explicitly opt-in to unstable features"); + #[doc(hidden)] pub use futures_util::core_reexport; #[doc(hidden)] pub use futures_core::future::Future; @@ -198,15 +202,24 @@ pub mod future { Join5, Map, Then, }; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] + pub use futures_util::future::{join_all, JoinAll}; + + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + #[cfg(feature = "alloc")] pub use futures_util::future::{ abortable, Abortable, AbortHandle, AbortRegistration, Aborted, + }; + + #[cfg(feature = "std")] + pub use futures_util::future::{ Remote, RemoteHandle, // For FutureExt: CatchUnwind, Shared, - join_all, JoinAll, - // ToDo: SelectAll, SelectOk, select_all, select_ok }; @@ -217,7 +230,7 @@ pub mod future { TryJoin, TryJoin3, TryJoin4, TryJoin5, }; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub use futures_util::try_future::{ try_join_all, TryJoinAll, }; @@ -295,7 +308,7 @@ pub mod sink { // WithFlatMap, }; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub use futures_util::sink::Buffer; } @@ -327,23 +340,38 @@ pub mod stream { unfold, Unfold, StreamExt, - Chain, Concat, Filter, FilterMap, Flatten, Fold, Forward, ForEach, Fuse, + Chain, Collect, Concat, Filter, FilterMap, Flatten, Fold, Forward, ForEach, Fuse, StreamFuture, Inspect, Map, Next, Peekable, Select, Skip, SkipWhile, Take, TakeWhile, Then, Zip }; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] + pub use futures_util::stream::{ + // For StreamExt: + Chunks, + }; + + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + #[cfg(feature = "alloc")] pub use futures_util::stream::{ futures_ordered, FuturesOrdered, futures_unordered, FuturesUnordered, // For StreamExt: - BufferUnordered, Buffered, CatchUnwind, Chunks, Collect, SplitStream, - SplitSink, ReuniteError, + BufferUnordered, Buffered, SplitStream, SplitSink, select_all, SelectAll, }; + #[cfg(feature = "std")] + pub use futures_util::stream::{ + // For StreamExt: + CatchUnwind, ReuniteError, + }; + pub use futures_util::try_stream::{ TryStreamExt, TryNext, TryForEach, ErrInto, @@ -352,7 +380,11 @@ pub mod stream { // ToDo: AndThen, ErrInto, InspectErr, MapErr, OrElse }; - #[cfg(feature = "std")] + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + #[cfg(feature = "alloc")] pub use futures_util::try_stream::{ // For TryStreamExt: TryBufferUnordered, @@ -378,13 +410,19 @@ pub mod task { pub use futures_util::task::noop_waker; - #[cfg(feature = "std")] + #[cfg_attr( + feature = "cfg-target-has-atomic", + cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr")) + )] + #[cfg(feature = "alloc")] pub use futures_util::task::{ WakerRef, waker_ref, ArcWake, SpawnExt, LocalSpawnExt, - noop_waker_ref, }; + #[cfg(feature = "std")] + pub use futures_util::task::noop_waker_ref; + #[cfg_attr( feature = "cfg-target-has-atomic", cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))