diff options
author | 2020-02-05 04:14:26 +0100 | |
---|---|---|
committer | 2020-02-05 04:14:26 +0100 | |
commit | ca213922d043a5532d9ab352c0d54bfca7563871 (patch) | |
tree | ee4ce50991d974144e23030d31ffb11b975cb603 /futures/src | |
parent | 9a06e481b7f52a9d8e123c909d5614332f607c53 (diff) | |
download | iced-ca213922d043a5532d9ab352c0d54bfca7563871.tar.gz iced-ca213922d043a5532d9ab352c0d54bfca7563871.tar.bz2 iced-ca213922d043a5532d9ab352c0d54bfca7563871.zip |
Drop `Send` in `Command` and `Executor` on Wasm
Diffstat (limited to 'futures/src')
-rw-r--r-- | futures/src/command.rs | 105 | ||||
-rw-r--r-- | futures/src/command/native.rs | 100 | ||||
-rw-r--r-- | futures/src/command/web.rs | 101 | ||||
-rw-r--r-- | futures/src/executor.rs | 11 | ||||
-rw-r--r-- | futures/src/executor/null.rs | 4 | ||||
-rw-r--r-- | futures/src/executor/wasm_bindgen.rs | 5 | ||||
-rw-r--r-- | futures/src/runtime.rs | 6 |
7 files changed, 227 insertions, 105 deletions
diff --git a/futures/src/command.rs b/futures/src/command.rs index e7885fb8..26f58fde 100644 --- a/futures/src/command.rs +++ b/futures/src/command.rs @@ -1,100 +1,11 @@ -use futures::future::{BoxFuture, Future, FutureExt}; +#[cfg(not(target_arch = "wasm32"))] +mod native; -/// A collection of async operations. -/// -/// You should be able to turn a future easily into a [`Command`], either by -/// using the `From` trait or [`Command::perform`]. -/// -/// [`Command`]: struct.Command.html -pub struct Command<T> { - futures: Vec<BoxFuture<'static, T>>, -} +#[cfg(not(target_arch = "wasm32"))] +pub use native::Command; -impl<T> Command<T> { - /// Creates an empty [`Command`]. - /// - /// In other words, a [`Command`] that does nothing. - /// - /// [`Command`]: struct.Command.html - pub fn none() -> Self { - Self { - futures: Vec::new(), - } - } +#[cfg(target_arch = "wasm32")] +mod web; - /// Creates a [`Command`] that performs the action of the given future. - /// - /// [`Command`]: struct.Command.html - pub fn perform<A>( - future: impl Future<Output = T> + 'static + Send, - f: impl Fn(T) -> A + 'static + Send, - ) -> Command<A> { - Command { - futures: vec![future.map(f).boxed()], - } - } - - /// Applies a transformation to the result of a [`Command`]. - /// - /// [`Command`]: struct.Command.html - pub fn map<A>( - mut self, - f: impl Fn(T) -> A + 'static + Send + Sync, - ) -> Command<A> - where - T: 'static, - { - let f = std::sync::Arc::new(f); - - Command { - futures: self - .futures - .drain(..) - .map(|future| { - let f = f.clone(); - - future.map(move |result| f(result)).boxed() - }) - .collect(), - } - } - - /// Creates a [`Command`] that performs the actions of all the given - /// commands. - /// - /// Once this command is run, all the commands will be exectued at once. - /// - /// [`Command`]: struct.Command.html - pub fn batch(commands: impl IntoIterator<Item = Command<T>>) -> Self { - Self { - futures: commands - .into_iter() - .flat_map(|command| command.futures) - .collect(), - } - } - - /// Converts a [`Command`] into its underlying list of futures. - /// - /// [`Command`]: struct.Command.html - pub fn futures(self) -> Vec<BoxFuture<'static, T>> { - self.futures - } -} - -impl<T, A> From<A> for Command<T> -where - A: Future<Output = T> + 'static + Send, -{ - fn from(future: A) -> Self { - Self { - futures: vec![future.boxed()], - } - } -} - -impl<T> std::fmt::Debug for Command<T> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Command").finish() - } -} +#[cfg(target_arch = "wasm32")] +pub use web::Command; diff --git a/futures/src/command/native.rs b/futures/src/command/native.rs new file mode 100644 index 00000000..38cb4e06 --- /dev/null +++ b/futures/src/command/native.rs @@ -0,0 +1,100 @@ +use futures::future::{BoxFuture, Future, FutureExt}; + +/// A collection of async operations. +/// +/// You should be able to turn a future easily into a [`Command`], either by +/// using the `From` trait or [`Command::perform`]. +/// +/// [`Command`]: struct.Command.html +pub struct Command<T> { + futures: Vec<BoxFuture<'static, T>>, +} + +impl<T> Command<T> { + /// Creates an empty [`Command`]. + /// + /// In other words, a [`Command`] that does nothing. + /// + /// [`Command`]: struct.Command.html + pub fn none() -> Self { + Self { + futures: Vec::new(), + } + } + + /// Creates a [`Command`] that performs the action of the given future. + /// + /// [`Command`]: struct.Command.html + pub fn perform<A>( + future: impl Future<Output = T> + 'static + Send, + f: impl Fn(T) -> A + 'static + Send, + ) -> Command<A> { + Command { + futures: vec![future.map(f).boxed()], + } + } + + /// Applies a transformation to the result of a [`Command`]. + /// + /// [`Command`]: struct.Command.html + pub fn map<A>( + mut self, + f: impl Fn(T) -> A + 'static + Send + Sync, + ) -> Command<A> + where + T: 'static, + { + let f = std::sync::Arc::new(f); + + Command { + futures: self + .futures + .drain(..) + .map(|future| { + let f = f.clone(); + + future.map(move |result| f(result)).boxed() + }) + .collect(), + } + } + + /// Creates a [`Command`] that performs the actions of all the given + /// commands. + /// + /// Once this command is run, all the commands will be executed at once. + /// + /// [`Command`]: struct.Command.html + pub fn batch(commands: impl IntoIterator<Item = Command<T>>) -> Self { + Self { + futures: commands + .into_iter() + .flat_map(|command| command.futures) + .collect(), + } + } + + /// Converts a [`Command`] into its underlying list of futures. + /// + /// [`Command`]: struct.Command.html + pub fn futures(self) -> Vec<BoxFuture<'static, T>> { + self.futures + } +} + +impl<T, A> From<A> for Command<T> +where + A: Future<Output = T> + 'static + Send, +{ + fn from(future: A) -> Self { + Self { + futures: vec![future.boxed()], + } + } +} + +impl<T> std::fmt::Debug for Command<T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Command").finish() + } +} diff --git a/futures/src/command/web.rs b/futures/src/command/web.rs new file mode 100644 index 00000000..11b46b90 --- /dev/null +++ b/futures/src/command/web.rs @@ -0,0 +1,101 @@ +use futures::future::{Future, FutureExt}; +use std::pin::Pin; + +/// A collection of async operations. +/// +/// You should be able to turn a future easily into a [`Command`], either by +/// using the `From` trait or [`Command::perform`]. +/// +/// [`Command`]: struct.Command.html +pub struct Command<T> { + futures: Vec<Pin<Box<dyn Future<Output = T> + 'static>>>, +} + +impl<T> Command<T> { + /// Creates an empty [`Command`]. + /// + /// In other words, a [`Command`] that does nothing. + /// + /// [`Command`]: struct.Command.html + pub fn none() -> Self { + Self { + futures: Vec::new(), + } + } + + /// Creates a [`Command`] that performs the action of the given future. + /// + /// [`Command`]: struct.Command.html + pub fn perform<A>( + future: impl Future<Output = T> + 'static, + f: impl Fn(T) -> A + 'static, + ) -> Command<A> { + Command { + futures: vec![future.map(f).boxed_local()], + } + } + + /// Applies a transformation to the result of a [`Command`]. + /// + /// [`Command`]: struct.Command.html + pub fn map<A>( + mut self, + f: impl Fn(T) -> A + 'static + Send + Sync + Unpin, + ) -> Command<A> + where + T: 'static, + { + let f = std::sync::Arc::new(f); + + Command { + futures: self + .futures + .drain(..) + .map(|future| { + let f = f.clone(); + + future.map(move |result| f(result)).boxed_local() + }) + .collect(), + } + } + + /// Creates a [`Command`] that performs the actions of all the given + /// commands. + /// + /// Once this command is run, all the commands will be executed at once. + /// + /// [`Command`]: struct.Command.html + pub fn batch(commands: impl IntoIterator<Item = Command<T>>) -> Self { + Self { + futures: commands + .into_iter() + .flat_map(|command| command.futures) + .collect(), + } + } + + /// Converts a [`Command`] into its underlying list of futures. + /// + /// [`Command`]: struct.Command.html + pub fn futures(self) -> Vec<Pin<Box<dyn Future<Output = T> + 'static>>> { + self.futures + } +} + +impl<T, A> From<A> for Command<T> +where + A: Future<Output = T> + 'static, +{ + fn from(future: A) -> Self { + Self { + futures: vec![future.boxed_local()], + } + } +} + +impl<T> std::fmt::Debug for Command<T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Command").finish() + } +} diff --git a/futures/src/executor.rs b/futures/src/executor.rs index 2a5281af..5378c0b3 100644 --- a/futures/src/executor.rs +++ b/futures/src/executor.rs @@ -1,7 +1,7 @@ //! Choose your preferred executor to power a runtime. mod null; -#[cfg(feature = "thread-pool")] +#[cfg(all(not(target_arch = "wasm32"), feature = "thread-pool"))] mod thread_pool; #[cfg(all(not(target_arch = "wasm32"), feature = "tokio"))] @@ -15,7 +15,7 @@ mod wasm_bindgen; pub use null::Null; -#[cfg(feature = "thread-pool")] +#[cfg(all(not(target_arch = "wasm32"), feature = "thread-pool"))] pub use thread_pool::ThreadPool; #[cfg(all(not(target_arch = "wasm32"), feature = "tokio"))] @@ -41,8 +41,15 @@ pub trait Executor: Sized { /// Spawns a future in the [`Executor`]. /// /// [`Executor`]: trait.Executor.html + #[cfg(not(target_arch = "wasm32"))] fn spawn(&self, future: impl Future<Output = ()> + Send + 'static); + /// Spawns a local future in the [`Executor`]. + /// + /// [`Executor`]: trait.Executor.html + #[cfg(target_arch = "wasm32")] + fn spawn(&self, future: impl Future<Output = ()> + 'static); + /// Runs the given closure inside the [`Executor`]. /// /// Some executors, like `tokio`, require some global state to be in place diff --git a/futures/src/executor/null.rs b/futures/src/executor/null.rs index 6d5cf982..65e2e2df 100644 --- a/futures/src/executor/null.rs +++ b/futures/src/executor/null.rs @@ -11,5 +11,9 @@ impl Executor for Null { Ok(Self) } + #[cfg(not(target_arch = "wasm32"))] fn spawn(&self, _future: impl Future<Output = ()> + Send + 'static) {} + + #[cfg(target_arch = "wasm32")] + fn spawn(&self, _future: impl Future<Output = ()> + 'static) {} } diff --git a/futures/src/executor/wasm_bindgen.rs b/futures/src/executor/wasm_bindgen.rs index 69b7c7e2..94d694c8 100644 --- a/futures/src/executor/wasm_bindgen.rs +++ b/futures/src/executor/wasm_bindgen.rs @@ -9,10 +9,7 @@ impl Executor for WasmBindgen { Ok(Self) } - fn spawn( - &self, - future: impl futures::Future<Output = ()> + Send + 'static, - ) { + fn spawn(&self, future: impl futures::Future<Output = ()> + 'static) { wasm_bindgen_futures::spawn_local(future); } } diff --git a/futures/src/runtime.rs b/futures/src/runtime.rs index 3be45a26..ede529dc 100644 --- a/futures/src/runtime.rs +++ b/futures/src/runtime.rs @@ -73,11 +73,13 @@ where for future in futures { let mut sender = self.sender.clone(); - self.executor.spawn(future.then(|message| async move { + let future = future.then(|message| async move { let _ = sender.send(message).await; () - })); + }); + + self.executor.spawn(future); } } |