1 use futures_task::{LocalSpawn, Spawn}; 2 3 #[cfg(feature = "compat")] 4 use crate::compat::Compat; 5 6 #[cfg(feature = "channel")] 7 #[cfg(feature = "std")] 8 use crate::future::{FutureExt, RemoteHandle}; 9 #[cfg(feature = "alloc")] 10 use alloc::boxed::Box; 11 #[cfg(feature = "alloc")] 12 use futures_core::future::Future; 13 #[cfg(feature = "alloc")] 14 use futures_task::{FutureObj, LocalFutureObj, SpawnError}; 15 16 impl<Sp: ?Sized> SpawnExt for Sp where Sp: Spawn {} 17 impl<Sp: ?Sized> LocalSpawnExt for Sp where Sp: LocalSpawn {} 18 19 /// Extension trait for `Spawn`. 20 pub trait SpawnExt: Spawn { 21 /// Spawns a task that polls the given future with output `()` to 22 /// completion. 23 /// 24 /// This method returns a [`Result`] that contains a [`SpawnError`] if 25 /// spawning fails. 26 /// 27 /// You can use [`spawn_with_handle`](SpawnExt::spawn_with_handle) if 28 /// you want to spawn a future with output other than `()` or if you want 29 /// to be able to await its completion. 30 /// 31 /// Note this method will eventually be replaced with the upcoming 32 /// `Spawn::spawn` method which will take a `dyn Future` as input. 33 /// Technical limitations prevent `Spawn::spawn` from being implemented 34 /// today. Feel free to use this method in the meantime. 35 /// 36 /// ``` 37 /// # if cfg!(miri) { return; } // https://github.com/rust-lang/miri/issues/1038 38 /// use futures::executor::ThreadPool; 39 /// use futures::task::SpawnExt; 40 /// 41 /// let executor = ThreadPool::new().unwrap(); 42 /// 43 /// let future = async { /* ... */ }; 44 /// executor.spawn(future).unwrap(); 45 /// ``` 46 #[cfg(feature = "alloc")] spawn<Fut>(&self, future: Fut) -> Result<(), SpawnError> where Fut: Future<Output = ()> + Send + 'static,47 fn spawn<Fut>(&self, future: Fut) -> Result<(), SpawnError> 48 where 49 Fut: Future<Output = ()> + Send + 'static, 50 { 51 self.spawn_obj(FutureObj::new(Box::new(future))) 52 } 53 54 /// Spawns a task that polls the given future to completion and returns a 55 /// future that resolves to the spawned future's output. 56 /// 57 /// This method returns a [`Result`] that contains a [`RemoteHandle`](crate::future::RemoteHandle), or, if 58 /// spawning fails, a [`SpawnError`]. [`RemoteHandle`](crate::future::RemoteHandle) is a future that 59 /// resolves to the output of the spawned future. 60 /// 61 /// ``` 62 /// # if cfg!(miri) { return; } // https://github.com/rust-lang/miri/issues/1038 63 /// use futures::executor::{block_on, ThreadPool}; 64 /// use futures::future; 65 /// use futures::task::SpawnExt; 66 /// 67 /// let executor = ThreadPool::new().unwrap(); 68 /// 69 /// let future = future::ready(1); 70 /// let join_handle_fut = executor.spawn_with_handle(future).unwrap(); 71 /// assert_eq!(block_on(join_handle_fut), 1); 72 /// ``` 73 #[cfg(feature = "channel")] 74 #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] 75 #[cfg(feature = "std")] spawn_with_handle<Fut>(&self, future: Fut) -> Result<RemoteHandle<Fut::Output>, SpawnError> where Fut: Future + Send + 'static, Fut::Output: Send,76 fn spawn_with_handle<Fut>(&self, future: Fut) -> Result<RemoteHandle<Fut::Output>, SpawnError> 77 where 78 Fut: Future + Send + 'static, 79 Fut::Output: Send, 80 { 81 let (future, handle) = future.remote_handle(); 82 self.spawn(future)?; 83 Ok(handle) 84 } 85 86 /// Wraps a [`Spawn`] and makes it usable as a futures 0.1 `Executor`. 87 /// Requires the `compat` feature to enable. 88 #[cfg(feature = "compat")] 89 #[cfg_attr(docsrs, doc(cfg(feature = "compat")))] compat(self) -> Compat<Self> where Self: Sized,90 fn compat(self) -> Compat<Self> 91 where 92 Self: Sized, 93 { 94 Compat::new(self) 95 } 96 } 97 98 /// Extension trait for `LocalSpawn`. 99 pub trait LocalSpawnExt: LocalSpawn { 100 /// Spawns a task that polls the given future with output `()` to 101 /// completion. 102 /// 103 /// This method returns a [`Result`] that contains a [`SpawnError`] if 104 /// spawning fails. 105 /// 106 /// You can use [`spawn_with_handle`](SpawnExt::spawn_with_handle) if 107 /// you want to spawn a future with output other than `()` or if you want 108 /// to be able to await its completion. 109 /// 110 /// Note this method will eventually be replaced with the upcoming 111 /// `Spawn::spawn` method which will take a `dyn Future` as input. 112 /// Technical limitations prevent `Spawn::spawn` from being implemented 113 /// today. Feel free to use this method in the meantime. 114 /// 115 /// ``` 116 /// use futures::executor::LocalPool; 117 /// use futures::task::LocalSpawnExt; 118 /// 119 /// let executor = LocalPool::new(); 120 /// let spawner = executor.spawner(); 121 /// 122 /// let future = async { /* ... */ }; 123 /// spawner.spawn_local(future).unwrap(); 124 /// ``` 125 #[cfg(feature = "alloc")] spawn_local<Fut>(&self, future: Fut) -> Result<(), SpawnError> where Fut: Future<Output = ()> + 'static,126 fn spawn_local<Fut>(&self, future: Fut) -> Result<(), SpawnError> 127 where 128 Fut: Future<Output = ()> + 'static, 129 { 130 self.spawn_local_obj(LocalFutureObj::new(Box::new(future))) 131 } 132 133 /// Spawns a task that polls the given future to completion and returns a 134 /// future that resolves to the spawned future's output. 135 /// 136 /// This method returns a [`Result`] that contains a [`RemoteHandle`](crate::future::RemoteHandle), or, if 137 /// spawning fails, a [`SpawnError`]. [`RemoteHandle`](crate::future::RemoteHandle) is a future that 138 /// resolves to the output of the spawned future. 139 /// 140 /// ``` 141 /// # if cfg!(miri) { return; } // https://github.com/rust-lang/miri/issues/1038 142 /// use futures::executor::LocalPool; 143 /// use futures::task::LocalSpawnExt; 144 /// 145 /// let mut executor = LocalPool::new(); 146 /// let spawner = executor.spawner(); 147 /// 148 /// let future = async { 1 }; 149 /// let join_handle_fut = spawner.spawn_local_with_handle(future).unwrap(); 150 /// assert_eq!(executor.run_until(join_handle_fut), 1); 151 /// ``` 152 #[cfg(feature = "channel")] 153 #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] 154 #[cfg(feature = "std")] spawn_local_with_handle<Fut>( &self, future: Fut, ) -> Result<RemoteHandle<Fut::Output>, SpawnError> where Fut: Future + 'static,155 fn spawn_local_with_handle<Fut>( 156 &self, 157 future: Fut, 158 ) -> Result<RemoteHandle<Fut::Output>, SpawnError> 159 where 160 Fut: Future + 'static, 161 { 162 let (future, handle) = future.remote_handle(); 163 self.spawn_local(future)?; 164 Ok(handle) 165 } 166 } 167